Move auth scheme resolution to pipeline stage from interceptors#6755
Move auth scheme resolution to pipeline stage from interceptors#6755S-Saranya1 wants to merge 3 commits intofeature/master/core-interceptors-migrationfrom
Conversation
| tasks.add(generateModelBasedProvider()); | ||
| tasks.add(generatePreferenceProvider()); | ||
| tasks.add(generateAuthSchemeInterceptor()); | ||
| // AuthSchemeInterceptor removed - auth scheme resolution now happens in client operation methods |
There was a problem hiding this comment.
Are these comments needed? Are they for customers or us and will be removed when merging to master?
There was a problem hiding this comment.
Yeah, will remove them before merging to master.
There was a problem hiding this comment.
+1 can we remove them now? (I blame kiro because it really likes adding unnecessary comments, should probably update our guideline)
| } | ||
| } | ||
|
|
||
| private MethodSpec resolveAuthSchemeOptionsMethod() { |
There was a problem hiding this comment.
This method is quite large. Could we try extracting the logic, such as the endpoint-based and non-endpoint-based logic into separate helper methods?
| poetExtensions.getSyncWaiterInterface()); | ||
| } | ||
|
|
||
| private MethodSpec resolveAuthSchemeOptionsMethod() { |
There was a problem hiding this comment.
Do we consider to move this method to a utility class to avoid dupilication?
| tasks.add(generateModelBasedProvider()); | ||
| tasks.add(generatePreferenceProvider()); | ||
| tasks.add(generateAuthSchemeInterceptor()); | ||
| // AuthSchemeInterceptor removed - auth scheme resolution now happens in client operation methods |
There was a problem hiding this comment.
+1 can we remove them now? (I blame kiro because it really likes adding unnecessary comments, should probably update our guideline)
| List<ClassName> builtInInterceptors = new ArrayList<>(); | ||
|
|
||
| builtInInterceptors.add(authSchemeSpecUtils.authSchemeInterceptor()); | ||
| // AuthSchemeInterceptor removed - auth scheme resolution now happens in client operation methods |
| .add(".withErrorResponseHandler(errorResponseHandler)\n") | ||
| .add(".withRequestConfiguration(clientConfiguration)") | ||
| .add(".withMetricCollector(apiCallMetricCollector)\n") | ||
| .add(".withAuthSchemeOptions(resolveAuthSchemeOptions($L, $S, clientConfiguration))\n", |
There was a problem hiding this comment.
Don't we need to update codegen fixtures test files, but I don't see the files in this PR
There was a problem hiding this comment.
I remember we discussed about passing a callback of how to resolve auth scheme options instead because they could also be modified by execution interceptor
There was a problem hiding this comment.
Yeah, right. There are a lot of codegen fixture files that we'll need to update again after the endpoints refactoring. I thought maybe we could update them directly before merging to
master. Sure, better to keep these changes. I'll add them.
There was a problem hiding this comment.
I remember we discussed about passing a callback of how to resolve auth scheme options instead because they could also be modified by execution interceptor
Oh yeah right, I remember now, I'll update it.
| /** | ||
| * Records business metrics for auth scheme selection (SigV4a, bearer token). | ||
| */ | ||
| private static void recordAuthSchemeBusinessMetrics(List<AuthSchemeOption> authSchemeOptions, |
There was a problem hiding this comment.
Question: should we record the metrics in AuthSchemeResolutionStage?
There was a problem hiding this comment.
AuthSchemeResolutionStage happens after ApplyUserAgentStage, so metrics wont get recorded then.
| * Pipeline stage that resolves the auth scheme and identity for signing. | ||
| */ | ||
| @SdkInternalApi | ||
| public final class AuthSchemeResolutionStage implements RequestToRequestPipeline { |
There was a problem hiding this comment.
Can we add a unit test for this class?
There was a problem hiding this comment.
My bad, missed committing the file, added the tests now.
| @@ -240,7 +244,7 @@ private List<ExecutionInterceptor> initializeInterceptors() { | |||
| List<ExecutionInterceptor> s3Interceptors = | |||
| interceptorFactory.getInterceptors("software/amazon/awssdk/services/s3/execution.interceptors"); | |||
| List<ExecutionInterceptor> additionalInterceptors = new ArrayList<>(); | |||
| additionalInterceptors.add(new S3AuthSchemeInterceptor()); | |||
| // S3AuthSchemeInterceptor removed - auth scheme resolution now done inline | |||
| poetExtensions.getSyncWaiterInterface()); | ||
| } | ||
|
|
||
| private MethodSpec resolveAuthSchemeOptionsMethod() { |
| /// | ||
| /// A container for the identity resolver, signer and auth option that we selected for use with this service call attempt. | ||
| /// ## The Hierarchy | ||
| /// ``` | ||
| /// IDENTITY_PROVIDERS (IdentityProviders) | ||
| /// └── contains multiple IdentityProvider<T> instances | ||
| /// e.g., IdentityProvider<AwsCredentialsIdentity> for AWS credentials | ||
| /// e.g., IdentityProvider<TokenIdentity> for bearer tokens | ||
| /// | ||
| /// AUTH_SCHEMES (Map<String, AuthScheme<?>>) | ||
| /// └── each AuthScheme knows: | ||
| /// - which IdentityProvider type it needs | ||
| /// - which HttpSigner to use | ||
| /// | ||
| /// SELECTED_AUTH_SCHEME (SelectedAuthScheme<T>) | ||
| /// └── the chosen auth scheme, containing: | ||
| /// - identity: CompletableFuture<T> ← the resolved identity! | ||
| /// - signer: HttpSigner<T> | ||
| /// - authSchemeOption: AuthSchemeOption | ||
| /// ``` |
There was a problem hiding this comment.
should we use a single/* */ instead of /// on each line?
There was a problem hiding this comment.
Markdown is much better! 😛 https://openjdk.org/jeps/467
| /** | ||
| * Apply credential overrides from request configuration. | ||
| */ | ||
| private IdentityProviders applyCredentialOverrides(SdkRequest request, IdentityProviders base) { |
There was a problem hiding this comment.
This method is identical to AwsIdentityProviderUpdater.update(), should we remove and just call AwsIdentityProviderUpdater.INSTANCE.update()?
|
Is AwsExecutionContextBuilder.resolveIdentityProviders() redundant now that we resolve in |
Migrate identity resolution from interceptor to pipeline stage
Note: This PR targets a feature branch. Some tests are failing due to endpoint resolution happening before auth scheme resolution in the pipeline unlike before. This will be addressed in Part 2 (Endpoint Resolution Refactoring).
Motivation and Context
The SDK used
ExecutionInterceptorfor internal auth scheme resolution logic, but this interface was designed for customer extensibility. TheAuthSchemeInterceptor.beforeExecution()resolved identity before customer interceptors ranmodifyRequest(), causing credential overrides to be ignored. This refactoring movesidentity resolution to a new AuthSchemeResolutionStage in the request pipeline that runs after all interceptors complete, ensuring credentials injected by users are
respected.
Modifications
Added
AuthSchemeResolutionStage/AsyncAuthSchemeResolutionStage(runs after interceptors complete)Created
IdentityProviderUpdaterinterface for credential override callbackGenerate
resolveAuthSchemeOptions()in client classes, pass options viaClientExecutionParamsMigrated business metrics (SIGV4A_SIGNING, BEARER_SERVICE_ENV_VARS) to
AwsExecutionContextBuilderUpdated S3 presigner for endpoint-based auth provider
Testing
Existing tests - Verified existing auth tests in codegen-generated-classes-test are passing after refactoring .
IdentityResolutionOverrideTest- Verifies credential injection fixNew tests - Unit tests added for AwsIdentityProviderUpdater and AuthSchemeResolutionStage/ AsyncAuthSchemeResolutionStage
Screenshots (if appropriate)
Types of changes
Checklist
mvn installsucceedsscripts/new-changescript and following the instructions. Commit the new file created by the script in.changes/next-releasewith your changes.License