From d9507e4c367cc870b811e28e3b206ef4661c67d8 Mon Sep 17 00:00:00 2001 From: Clint Munden Date: Tue, 2 Feb 2021 08:31:01 -0330 Subject: [PATCH] fix: oauth1 signing for url encoded content (#538) * Fixed OAuth 1.0 signing for requests with URL Encoded Content (typical of POST and PUT HTTP methods) A simple change the the OAuthParameters intercept method that checks if the request has UrlEncodedContent. If it does, then its content is added to the GenericUrl so that the signature can be computed correctly. After the call to computeSignature, the content parameters are removed from the GenericUrl to leave it in its original form. As per the OAuth 1.0 spec here (https://tools.ietf.org/html/rfc5849#page-28), any form encoded request body with a Content-Type of "application/x-www-form-urlencoded" must be included when the request signature is created. * Changes to support java 1.7. Also added new test code. * style: expanded the wild card imports. --- .../client/auth/oauth/OAuthParameters.java | 21 ++++++++++++++-- .../auth/oauth/OAuthParametersTest.java | 24 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/google-oauth-client/src/main/java/com/google/api/client/auth/oauth/OAuthParameters.java b/google-oauth-client/src/main/java/com/google/api/client/auth/oauth/OAuthParameters.java index 666825826..35de3fd04 100644 --- a/google-oauth-client/src/main/java/com/google/api/client/auth/oauth/OAuthParameters.java +++ b/google-oauth-client/src/main/java/com/google/api/client/auth/oauth/OAuthParameters.java @@ -14,15 +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; @@ -53,7 +57,8 @@ * @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(); @@ -271,7 +276,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 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 entry : urlEncodedParams.entrySet()) { + url.remove(entry.getKey()); + } + } } catch (GeneralSecurityException e) { IOException io = new IOException(); io.initCause(e); diff --git a/google-oauth-client/src/test/java/com/google/api/client/auth/oauth/OAuthParametersTest.java b/google-oauth-client/src/test/java/com/google/api/client/auth/oauth/OAuthParametersTest.java index 7ec46ffc9..244689580 100644 --- a/google-oauth-client/src/test/java/com/google/api/client/auth/oauth/OAuthParametersTest.java +++ b/google-oauth-client/src/test/java/com/google/api/client/auth/oauth/OAuthParametersTest.java @@ -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; /** @@ -75,6 +83,22 @@ public void testSignature() throws GeneralSecurityException { 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 contentParameters = Collections.singletonMap("this", (Object) "that"); + 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();