-
Notifications
You must be signed in to change notification settings - Fork 947
Description
Describe the bug
Credentials injected via ExecutionInterceptor
using request override configuration are not respected when using the new auth scheme (SRA). The same credentials ARE respected when using the legacy Aws4Signer
.
This indicates that the new auth scheme resolves credentials too early in the request lifecycle, before interceptors have a chance to modify them.
Regression Issue
- Select this option if this issue appears to be a regression.
Expected Behavior
The request should fail with an authentication error:
Exception in thread "main" software.amazon.awssdk.services.appconfig.model.AppConfigException:
The security token included in the request is invalid.
This is the expected behavior because the invalid credentials (akid
/skid
) should be used for signing.
Current Behavior
Without legacy signer override:
- The request SUCCEEDS despite invalid credentials being injected
- This indicates the injected credentials are being IGNORED
- The SDK uses the default credentials from the environment/chain instead
With legacy signer override (.signer(Aws4Signer.create())
):
- The request FAILS as expected with authentication error
- This indicates the injected credentials ARE being respected
Reproduction Steps
AppConfigClient client = AppConfigClient.builder()
.overrideConfiguration(o -> o.addExecutionInterceptor(new ExecutionInterceptor() {
@Override
public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) {
if (context.request() instanceof AwsRequest awsRequest) {
return awsRequest.toBuilder()
.overrideConfiguration(o -> o
.signer(Aws4Signer.create()) // <-- Only works when this line is present
.credentialsProvider(() -> AwsBasicCredentials.create("akid", "skid")))
.build();
}
return ExecutionInterceptor.super.modifyRequest(context, executionAttributes);
}
}))
.build();
client.listApplications(ListApplicationsRequest.builder().build());
Possible Solution
No response
Additional Information/Context
Root Cause Analysis
New Auth Scheme Flow (Broken)
AppConfigAuthSchemeInterceptor.beforeExecution
(generated class) resolves the identity early:CompletableFuture<? extends T> identity = identityProvider.resolveIdentity(...) SelectedAuthScheme selectedAuthScheme = new SelectedAuthScheme<>(identity, signer, authOption); executionAttributes.putAttribute(SELECTED_AUTH_SCHEME, selectedAuthScheme);
- See screenshots of debugger below for evidence credentials are being resolved early (used origAkid to scrub my real credentials)


-
User interceptor runs (
modifyRequest
) and modifies the request's credential provider -
The identity is already resolved and stored in
SelectedAuthScheme
. When credentials are updated viaAwsSignerExecutionAttribute.AWS_CREDENTIALS
, the write mapping creates a newSelectedAuthScheme
but:- The auth scheme interceptor may have already copied the old identity reference
- The signing stage uses the identity that was resolved in step 1
- Location:
core/auth/src/main/java/software/amazon/awssdk/auth/signer/AwsSignerExecutionAttribute.java:208-224
-
SigningStage.sraSignRequest
uses the pre-resolved identity:T identity = CompletableFutureUtils.joinLikeSync(identityFuture);
- Location:
core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/SigningStage.java:91-92
- Location:
Legacy Signer Flow (Works)
- Auth scheme setup in
beforeExecution
- User interceptor runs and modifies request
SigningStage
callssigner.sign(request, executionAttributes)
BaseAws4Signer.sign()
callsextractSignerParams()
at signing time:Aws4SignerParams signingParams = extractSignerParams(Aws4SignerParams.builder(), executionAttributes) .build();
- This reads from
AwsSignerExecutionAttribute.AWS_CREDENTIALS
AT SIGNING TIME - Location:
core/auth/src/main/java/software/amazon/awssdk/auth/signer/internal/BaseAws4Signer.java:34-38
- Location:
core/auth/src/main/java/software/amazon/awssdk/auth/signer/internal/AbstractAws4Signer.java:413-419
- This reads from
Key Difference
Legacy signer: Reads credentials from ExecutionAttributes at signing time (lazy evaluation)
New auth scheme: Resolves credentials in beforeExecution
before interceptors run (eager evaluation)
Impact
This breaks any use case where:
- Credentials need to be determined based on the request content
- Credentials are dynamically injected in interceptors
- Per-request credential override is needed after the request is created
Examples:
- Assume-role workflows that determine role based on request parameters
- Multi-tenant applications that select credentials based on request context
- Testing scenarios that inject mock credentials
Workaround
Force the use of the legacy signer by setting it in the request override configuration:
.overrideConfiguration(o -> o
.signer(Aws4Signer.create()) // Force legacy signer
.credentialsProvider(customProvider))
Note: This workaround uses deprecated APIs and may not work long-term.
AWS Java SDK version used
2.34.9
JDK version used
Java17
Operating System and version
AL2