Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: oauth1 signing for url encoded content #538

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -14,16 +14,19 @@

package com.google.api.client.auth.oauth;

import com.google.api.client.http.HttpContent;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpExecuteInterceptor;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.UrlEncodedContent;
import com.google.api.client.util.Beta;
import com.google.api.client.util.Data;
import com.google.api.client.util.escape.PercentEscaper;

import com.google.common.collect.Multiset;
import com.google.common.collect.SortedMultiset;
import com.google.common.collect.TreeMultiset;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
Expand Down Expand Up @@ -58,7 +61,8 @@ public static HttpRequestFactory createRequestFactory(HttpTransport transport) {
* @author Yaniv Inbar
*/
@Beta
public final class OAuthParameters implements HttpExecuteInterceptor, HttpRequestInitializer {
public final class OAuthParameters implements HttpExecuteInterceptor, HttpRequestInitializer
{

/** Secure random number generator to sign requests. */
private static final SecureRandom RANDOM = new SecureRandom();
Expand Down Expand Up @@ -280,7 +284,19 @@ public void intercept(HttpRequest request) throws IOException {
computeNonce();
computeTimestamp();
try {
computeSignature(request.getRequestMethod(), request.getUrl());
GenericUrl url = request.getUrl();
HttpContent content = request.getContent();
Map<String, Object> urlEncodedParams = null;
if (content instanceof UrlEncodedContent) {
urlEncodedParams = Data.mapOf(((UrlEncodedContent) content).getData());
url.putAll(urlEncodedParams);
}
computeSignature(request.getRequestMethod(), url);
if (urlEncodedParams != null) {
for (Map.Entry<String, Object> entry : urlEncodedParams.entrySet()) {
url.remove(entry.getKey());
}
}
} catch (GeneralSecurityException e) {
IOException io = new IOException();
io.initCause(e);
Expand Down
Expand Up @@ -15,7 +15,15 @@
package com.google.api.client.auth.oauth;

import com.google.api.client.http.GenericUrl;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.Map;

import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.UrlEncodedContent;
import com.google.api.client.http.javanet.NetHttpTransport;
import junit.framework.TestCase;

/**
Expand Down Expand Up @@ -72,6 +80,22 @@ public void testSignature() throws GeneralSecurityException {
assertEquals("GET&https%3A%2F%2Fexample.local&foo%3Dbar%26oauth_signature_method%3Dmock", parameters.signature);
}

public void testSignatureWithUrlEncodedContent() throws IOException {
OAuthParameters parameters = new OAuthParameters();
parameters.signer = new MockSigner();

GenericUrl url = new GenericUrl("https://example.local?foo=bar");
Map<String, Object> contentParameters = Collections.singletonMap("this", (Object) "that");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cast to Object probably isn't needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cast to Object is necessary in order to create the contentParameters templated to a map of type Map<String, Object>. Without the explicit cast to Object, the singletonMap method will template to a map of type Map<String, String>.

UrlEncodedContent content = new UrlEncodedContent(contentParameters);

HttpRequest request = new NetHttpTransport.Builder().build()
.createRequestFactory().buildPostRequest(url, content);
parameters.intercept(request);

assertTrue(parameters.signature.endsWith("%26this%3Dthat"));
assertEquals("https://example.local?foo=bar", url.build());
}

public void testSignatureWithRepeatedParameter() throws GeneralSecurityException {
OAuthParameters parameters = new OAuthParameters();
parameters.signer = new MockSigner();
Expand Down