Skip to content

Commit 8c1eba8

Browse files
committed
Percent-encode key when building OAuth1 header, close AsyncHttpClient#1415
1 parent be58015 commit 8c1eba8

File tree

5 files changed

+40
-4
lines changed

5 files changed

+40
-4
lines changed

client/src/main/java/org/asynchttpclient/oauth/ConsumerKey.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,20 @@
1616
*/
1717
package org.asynchttpclient.oauth;
1818

19+
import org.asynchttpclient.util.Utf8UrlEncoder;
20+
1921
/**
2022
* Value class for OAuth consumer keys.
2123
*/
2224
public class ConsumerKey {
2325
private final String key;
2426
private final String secret;
27+
private final String percentEncodedKey;
2528

2629
public ConsumerKey(String key, String secret) {
2730
this.key = key;
2831
this.secret = secret;
32+
this.percentEncodedKey = Utf8UrlEncoder.percentEncodeQueryElement(key);
2933
}
3034

3135
public String getKey() {
@@ -36,6 +40,10 @@ public String getSecret() {
3640
return secret;
3741
}
3842

43+
String getPercentEncodedKey() {
44+
return percentEncodedKey;
45+
}
46+
3947
@Override
4048
public String toString() {
4149
StringBuilder sb = new StringBuilder("{Consumer key, key=");

client/src/main/java/org/asynchttpclient/oauth/OAuthSignatureCalculatorInstance.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,11 @@ private String encodedParams(ConsumerKey consumerAuth, RequestToken userAuth, lo
123123
* List of all query and form parameters added to this request; needed for calculating request signature
124124
*/
125125
// start with standard OAuth parameters we need
126-
parameters.add(KEY_OAUTH_CONSUMER_KEY, Utf8UrlEncoder.percentEncodeQueryElement(consumerAuth.getKey()))
126+
parameters.add(KEY_OAUTH_CONSUMER_KEY, consumerAuth.getPercentEncodedKey())
127127
.add(KEY_OAUTH_NONCE, Utf8UrlEncoder.percentEncodeQueryElement(nonce)).add(KEY_OAUTH_SIGNATURE_METHOD, OAUTH_SIGNATURE_METHOD)
128128
.add(KEY_OAUTH_TIMESTAMP, String.valueOf(oauthTimestamp));
129129
if (userAuth.getKey() != null) {
130-
parameters.add(KEY_OAUTH_TOKEN, Utf8UrlEncoder.percentEncodeQueryElement(userAuth.getKey()));
130+
parameters.add(KEY_OAUTH_TOKEN, userAuth.getPercentEncodedKey());
131131
}
132132
parameters.add(KEY_OAUTH_VERSION, OAUTH_VERSION_1_0);
133133

@@ -173,9 +173,9 @@ private byte[] digest(ConsumerKey consumerAuth, RequestToken userAuth, ByteBuffe
173173
String constructAuthHeader(ConsumerKey consumerAuth, RequestToken userAuth, String signature, String nonce, long oauthTimestamp) {
174174
StringBuilder sb = StringBuilderPool.DEFAULT.stringBuilder();
175175
sb.append("OAuth ");
176-
sb.append(KEY_OAUTH_CONSUMER_KEY).append("=\"").append(consumerAuth.getKey()).append("\", ");
176+
sb.append(KEY_OAUTH_CONSUMER_KEY).append("=\"").append(consumerAuth.getPercentEncodedKey()).append("\", ");
177177
if (userAuth.getKey() != null) {
178-
sb.append(KEY_OAUTH_TOKEN).append("=\"").append(userAuth.getKey()).append("\", ");
178+
sb.append(KEY_OAUTH_TOKEN).append("=\"").append(userAuth.getPercentEncodedKey()).append("\", ");
179179
}
180180
sb.append(KEY_OAUTH_SIGNATURE_METHOD).append("=\"").append(OAUTH_SIGNATURE_METHOD).append("\", ");
181181

client/src/main/java/org/asynchttpclient/oauth/RequestToken.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*/
1717
package org.asynchttpclient.oauth;
1818

19+
import org.asynchttpclient.util.Utf8UrlEncoder;
20+
1921
/**
2022
* Value class used for OAuth tokens (request secret, access secret);
2123
* simple container with two parts, public id part ("key") and
@@ -24,10 +26,12 @@
2426
public class RequestToken {
2527
private final String key;
2628
private final String secret;
29+
private final String percentEncodedKey;
2730

2831
public RequestToken(String key, String token) {
2932
this.key = key;
3033
this.secret = token;
34+
this.percentEncodedKey = Utf8UrlEncoder.percentEncodeQueryElement(key);
3135
}
3236

3337
public String getKey() {
@@ -38,6 +42,10 @@ public String getSecret() {
3842
return secret;
3943
}
4044

45+
String getPercentEncodedKey() {
46+
return percentEncodedKey;
47+
}
48+
4149
@Override
4250
public String toString() {
4351
StringBuilder sb = new StringBuilder("{ key=");

client/src/main/java/org/asynchttpclient/util/Utf8UrlEncoder.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ public static StringBuilder encodeAndAppendFormElement(StringBuilder sb, CharSeq
143143
}
144144

145145
public static String percentEncodeQueryElement(String input) {
146+
if (input == null) {
147+
return null;
148+
}
146149
StringBuilder sb = new StringBuilder(input.length() + 6);
147150
encodeAndAppendPercentEncoded(sb, input);
148151
return sb.toString();

client/src/test/java/org/asynchttpclient/oauth/OAuthSignatureCalculatorTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import org.asynchttpclient.Param;
2929
import org.asynchttpclient.Request;
30+
import org.asynchttpclient.RequestBuilder;
3031
import org.testng.annotations.Test;
3132

3233
/**
@@ -312,4 +313,20 @@ public void testSignatureGenerationWithAsteriskInPath() throws InvalidKeyExcepti
312313
String generatedAuthHeader = new OAuthSignatureCalculatorInstance().constructAuthHeader(consumerKey, requestToken, actualSignature, nonce, timestamp);
313314
assertTrue(generatedAuthHeader.contains("oauth_signature=\"cswi%2Fv3ZqhVkTyy5MGqW841BxDA%3D\""));
314315
}
316+
317+
@Test
318+
public void testPercentEncodeKeyValues() throws NoSuchAlgorithmException {
319+
// see https://github.com/AsyncHttpClient/async-http-client/issues/1415
320+
String keyValue = "\u3b05\u000c\u375b";
321+
322+
ConsumerKey consumer = new ConsumerKey(keyValue, "secret");
323+
RequestToken reqToken = new RequestToken(keyValue, "secret");
324+
OAuthSignatureCalculator calc = new OAuthSignatureCalculator(consumer, reqToken);
325+
326+
RequestBuilder reqBuilder = new RequestBuilder()
327+
.setUrl("https://api.dropbox.com/1/oauth/access_token?oauth_token=%EC%AD%AE%E3%AC%82%EC%BE%B8%E7%9C%9A%E8%BD%BD%E1%94%A5%E8%AD%AF%E8%98%93%E0%B9%99%E5%9E%96%EF%92%A2%EA%BC%97%EA%90%B0%E4%8A%91%E8%97%BF%EF%A8%BB%E5%B5%B1%DA%98%E2%90%87%E2%96%96%EE%B5%B5%E7%B9%AD%E9%AD%87%E3%BE%93%E5%AF%92%EE%BC%8F%E3%A0%B2%E8%A9%AB%E1%8B%97%EC%BF%80%EA%8F%AE%ED%87%B0%E5%97%B7%E9%97%BF%E8%BF%87%E6%81%A3%E5%BB%A1%EC%86%92%E8%92%81%E2%B9%94%EB%B6%86%E9%AE%8A%E6%94%B0%EE%AC%B5%E6%A0%99%EB%8B%AD%EB%BA%81%E7%89%9F%E5%B3%B7%EA%9D%B7%EC%A4%9C%E0%BC%BA%EB%BB%B9%ED%84%A9%E8%A5%B9%E8%AF%A0%E3%AC%85%0C%E3%9D%9B%E8%B9%8B%E6%BF%8C%EB%91%98%E7%8B%B3%E7%BB%A8%E2%A7%BB%E6%A3%84%E1%AB%B2%E8%8D%93%E4%BF%98%E9%B9%B9%EF%9A%8B%E8%A5%93");
328+
Request req = reqBuilder.build();
329+
330+
calc.calculateAndAddSignature(req, reqBuilder);
331+
}
315332
}

0 commit comments

Comments
 (0)