Skip to content

Commit 26bb6dc

Browse files
authored
Fix signature mismatch exception generated when signing query parameters with empty-value keys. (#3369)
1 parent ea0c5ef commit 26bb6dc

File tree

4 files changed

+56
-0
lines changed

4 files changed

+56
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "bugfix",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "",
5+
"description": "Fix signature mismatch exception generated when signing query parameters with empty-value keys."
6+
}

core/auth/src/main/java/software/amazon/awssdk/auth/signer/internal/AbstractAwsSigner.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,13 @@ protected void addCanonicalizedQueryString(StringBuilder result, SdkHttpRequest.
238238
* encoding in addition to sorted parameter names.
239239
*/
240240
httpRequest.forEachRawQueryParameter((key, values) -> {
241+
if (StringUtils.isEmpty(key)) {
242+
// Do not sign empty keys.
243+
return;
244+
}
245+
241246
String encodedParamName = SdkHttpUtils.urlEncode(key);
247+
242248
List<String> encodedValues = new ArrayList<>(values.size());
243249
for (String value : values) {
244250
String encodedValue = SdkHttpUtils.urlEncode(value);

core/auth/src/test/java/software/amazon/awssdk/auth/signer/Aws4SignerTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,23 @@ public void canonicalizedHeaderString_valuesWithExtraWhitespace_areTrimmed() thr
217217
+ "Signature=6d3520e3397e7aba593d8ebd8361fc4405e90aed71bc4c7a09dcacb6f72460b9");
218218
}
219219

220+
/**
221+
* Query strings with empty keys should not be included in the canonical string.
222+
*/
223+
@Test
224+
public void canonicalizedQueryString_keyWithEmptyNames_doNotGetSigned() throws Exception {
225+
AwsBasicCredentials credentials = AwsBasicCredentials.create("akid", "skid");
226+
SdkHttpFullRequest.Builder request = generateBasicRequest();
227+
request.putRawQueryParameter("", (String) null);
228+
229+
SdkHttpFullRequest actual = SignerTestUtils.signRequest(signer, request.build(), credentials, "demo", signingOverrideClock, "us-east-1");
230+
231+
assertThat(actual.firstMatchingHeader("Authorization"))
232+
.hasValue("AWS4-HMAC-SHA256 Credential=akid/19810216/us-east-1/demo/aws4_request, "
233+
+ "SignedHeaders=host;x-amz-archive-description;x-amz-date, "
234+
+ "Signature=581d0042389009a28d461124138f1fe8eeb8daed87611d2a2b47fd3d68d81d73");
235+
}
236+
220237
private SdkHttpFullRequest.Builder generateBasicRequest() {
221238
return SdkHttpFullRequest.builder()
222239
.contentStreamProvider(() -> new ByteArrayInputStream("{\"TableName\": \"foo\"}".getBytes()))
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.services.s3;
17+
18+
import org.junit.Test;
19+
20+
public class EmptyQueryStringSignerIntegrationTest extends S3IntegrationTestBase {
21+
@Test
22+
public void emptyQueryStringsDoNotThrowSignatureMismatch() {
23+
s3.listBuckets(r -> r.overrideConfiguration(c -> c.putRawQueryParameter("", (String) null)));
24+
s3.listBuckets(r -> r.overrideConfiguration(c -> c.putRawQueryParameter("", "foo")));
25+
s3.listBuckets(r -> r.overrideConfiguration(c -> c.putRawQueryParameter("", "")));
26+
}
27+
}

0 commit comments

Comments
 (0)