diff --git a/signpost-core/src/main/java/oauth/signpost/AbstractOAuthConsumer.java b/signpost-core/src/main/java/oauth/signpost/AbstractOAuthConsumer.java index 6bbdf46..f2bc51a 100644 --- a/signpost-core/src/main/java/oauth/signpost/AbstractOAuthConsumer.java +++ b/signpost-core/src/main/java/oauth/signpost/AbstractOAuthConsumer.java @@ -219,7 +219,7 @@ public void setSendEmptyTokens(boolean enable) { */ protected void collectHeaderParameters(HttpRequest request, HttpParameters out) { HttpParameters headerParams = OAuth.oauthHeaderToParamsMap(request.getHeader(OAuth.HTTP_AUTHORIZATION_HEADER)); - out.putAll(headerParams, true); + out.putAll(headerParams, false); } /** diff --git a/signpost-core/src/main/java/oauth/signpost/OAuth.java b/signpost-core/src/main/java/oauth/signpost/OAuth.java index c67c3b0..9dc4629 100644 --- a/signpost-core/src/main/java/oauth/signpost/OAuth.java +++ b/signpost-core/src/main/java/oauth/signpost/OAuth.java @@ -238,6 +238,38 @@ public static String addQueryParameters(String url, Map params) return addQueryParameters(url, kvPairs); } + /** + * Builds an OAuth header from the given list of header fields. All + * parameters starting in 'oauth_*' will be percent encoded. + * + *
+     * String authHeader = OAuth.prepareOAuthHeader("realm", "http://example.com", "oauth_token", "x%y");
+     * 
+ * + * which yields: + * + *
+     * OAuth realm="http://example.com", oauth_token="x%25y"
+     * 
+ * + * @param kvPairs + * the list of key/value pairs + * @return a string eligible to be used as an OAuth HTTP Authorization + * header. + */ + public static String prepareOAuthHeader(String... kvPairs) { + StringBuilder sb = new StringBuilder("OAuth "); + for (int i = 0; i < kvPairs.length; i += 2) { + if (i > 0) { + sb.append(", "); + } + String value = kvPairs[i].startsWith("oauth_") ? OAuth + .percentEncode(kvPairs[i + 1]) : kvPairs[i + 1]; + sb.append(OAuth.percentEncode(kvPairs[i]) + "=\"" + value + "\""); + } + return sb.toString(); + } + public static HttpParameters oauthHeaderToParamsMap(String oauthHeader) { HttpParameters params = new HttpParameters(); if (oauthHeader == null || !oauthHeader.startsWith("OAuth ")) { @@ -247,7 +279,7 @@ public static HttpParameters oauthHeaderToParamsMap(String oauthHeader) { String[] elements = oauthHeader.split(","); for (String keyValuePair : elements) { String[] keyValue = keyValuePair.split("="); - params.put(keyValue[0].trim(), keyValue[1].trim()); + params.put(keyValue[0].trim(), keyValue[1].replace("\"", "").trim()); } return params; } diff --git a/signpost-core/src/test/java/oauth/signpost/OAuthConsumerTest.java b/signpost-core/src/test/java/oauth/signpost/OAuthConsumerTest.java index 374b373..f7a0dd8 100644 --- a/signpost-core/src/test/java/oauth/signpost/OAuthConsumerTest.java +++ b/signpost-core/src/test/java/oauth/signpost/OAuthConsumerTest.java @@ -1,5 +1,6 @@ package oauth.signpost; +import static junit.framework.Assert.assertNull; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -86,13 +87,13 @@ public void shouldIncludeOAuthAndQueryAndBodyParams() throws Exception { // mock a request that has custom query, body, and header params set HttpRequest request = mock(HttpRequest.class); - when(request.getRequestUrl()).thenReturn("http://example.com?a=1"); - ByteArrayInputStream body = new ByteArrayInputStream("b=2".getBytes()); + when(request.getRequestUrl()).thenReturn("http://example.com?a=1+1"); + ByteArrayInputStream body = new ByteArrayInputStream("b=2+2".getBytes()); when(request.getMessagePayload()).thenReturn(body); when(request.getContentType()).thenReturn( "application/x-www-form-urlencoded; charset=ISO-8859-1"); when(request.getHeader("Authorization")).thenReturn( - "OAuth realm=www.example.com, oauth_signature=12345, oauth_version=1.1"); + "OAuth realm=\"http%3A%2F%2Fexample.com\", oauth_token=\"12%25345\", oauth_signature=\"1234\""); OAuthMessageSigner signer = mock(HmacSha1MessageSigner.class); consumer.setMessageSigner(signer); @@ -104,9 +105,12 @@ public void shouldIncludeOAuthAndQueryAndBodyParams() throws Exception { ArgumentMatcher hasAllParameters = new ArgumentMatcher() { public boolean matches(Object argument) { HttpParameters params = (HttpParameters) argument; - assertEquals("1", params.get("a").first()); - assertEquals("2", params.get("b").first()); - assertEquals("1.1", params.get("oauth_version").first()); + assertEquals("1 1", params.getFirst("a", true)); + assertEquals("2 2", params.getFirst("b", true)); + assertEquals("http://example.com", params.getFirst("realm", true)); + assertEquals("12%345", params.getFirst("oauth_token", true)); + // signature should be dropped, not valid to pre-set + assertNull(params.getFirst("oauth_signature")); return true; } }; @@ -217,8 +221,8 @@ private class HasValuesPercentEncoded extends ArgumentMatcher { public boolean matches(Object argument) { String oauthHeader = (String) argument; HttpParameters params = OAuth.oauthHeaderToParamsMap(oauthHeader); - assertEquals("\"1%252\"", params.getFirst("oauth_consumer_key")); - assertEquals("\"3%204\"", params.getFirst("oauth_token")); + assertEquals("1%252", params.getFirst("oauth_consumer_key")); + assertEquals("3%204", params.getFirst("oauth_token")); return true; } } diff --git a/signpost-core/src/test/java/oauth/signpost/OAuthTest.java b/signpost-core/src/test/java/oauth/signpost/OAuthTest.java index 1deff39..4d86c02 100644 --- a/signpost-core/src/test/java/oauth/signpost/OAuthTest.java +++ b/signpost-core/src/test/java/oauth/signpost/OAuthTest.java @@ -91,4 +91,20 @@ public void shouldCorrectlyAppendQueryParameters() { assertEquals("http://www.example.com?x=1&a=1&b=2", OAuth.addQueryParameters(url2, params)); } + + @Test + public void shouldCorrectlyParseOAuthAuthorizationHeader() { + String header = "OAuth realm=\"http://xyz.com\", oauth_callback=\"oob\""; + HttpParameters params = OAuth.oauthHeaderToParamsMap(header); + assertEquals("http://xyz.com", params.getFirst("realm")); + assertEquals("oob", params.getFirst("oauth_callback")); + } + + @Test + public void shouldCorrectlyPrepareOAuthHeader() { + assertEquals("OAuth realm=\"http://x.com\"", OAuth.prepareOAuthHeader("realm", + "http://x.com")); + assertEquals("OAuth realm=\"http://x.com\", oauth_token=\"x%25y\"", OAuth + .prepareOAuthHeader("realm", "http://x.com", "oauth_token", "x%y")); + } }