Skip to content

Commit 79ebe3f

Browse files
committed
Add more documentation and code snippet for custom signer
1 parent 9f2e918 commit 79ebe3f

File tree

10 files changed

+690
-23
lines changed

10 files changed

+690
-23
lines changed

core/auth/src/main/java/software/amazon/awssdk/auth/signer/AwsSignerExecutionAttribute.java

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import software.amazon.awssdk.auth.credentials.AwsCredentials;
2525
import software.amazon.awssdk.auth.credentials.CredentialUtils;
2626
import software.amazon.awssdk.auth.signer.params.Aws4SignerParams;
27+
import software.amazon.awssdk.core.SdkRequest;
2728
import software.amazon.awssdk.core.SelectedAuthScheme;
2829
import software.amazon.awssdk.core.interceptor.ExecutionAttribute;
2930
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
@@ -36,11 +37,13 @@
3637
import software.amazon.awssdk.http.auth.aws.signer.AwsV4aHttpSigner;
3738
import software.amazon.awssdk.http.auth.aws.signer.RegionSet;
3839
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
40+
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider;
3941
import software.amazon.awssdk.http.auth.spi.signer.AsyncSignRequest;
4042
import software.amazon.awssdk.http.auth.spi.signer.AsyncSignedRequest;
4143
import software.amazon.awssdk.http.auth.spi.signer.HttpSigner;
4244
import software.amazon.awssdk.http.auth.spi.signer.SignRequest;
4345
import software.amazon.awssdk.http.auth.spi.signer.SignedRequest;
46+
import software.amazon.awssdk.http.auth.spi.signer.SignerProperty;
4447
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
4548
import software.amazon.awssdk.identity.spi.Identity;
4649
import software.amazon.awssdk.regions.Region;
@@ -51,8 +54,8 @@
5154
* AWS-specific signing attributes attached to the execution. This information is available to {@link ExecutionInterceptor}s and
5255
* {@link Signer}s.
5356
*
54-
* @deprecated Signer execution attributes have been deprecated in favor of signer properties, set on the auth scheme's signer
55-
* option.
57+
* @deprecated Signer execution attributes have been deprecated in favor of {@link SignerProperty}s, set on the
58+
* {@link AuthSchemeOption}. See {@link AuthSchemeProvider} for how to use it.
5659
*/
5760
@Deprecated
5861
@SdkProtectedApi
@@ -61,9 +64,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute {
6164
* The key under which the request credentials are set.
6265
*
6366
* @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
64-
* from execution interceptors, you should instead be overriding the credential provider via the {@code SdkRequest}'s
67+
* from execution interceptors, you should instead be overriding the credential provider via the {@link SdkRequest}'s
6568
* {@code overrideConfiguration.credentialsProvider}. If you're using it to call the SDK's signers, you should migrate to a
66-
* subtype of {@code HttpSigner}.
69+
* subtype of {@link HttpSigner}.
6770
*/
6871
@Deprecated
6972
public static final ExecutionAttribute<AwsCredentials> AWS_CREDENTIALS =
@@ -79,9 +82,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute {
7982
* for global services like IAM.
8083
*
8184
* @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
82-
* from execution interceptors, you should instead be overriding the signing region via the {@code AuthSchemeProvider} that
85+
* from execution interceptors, you should instead be overriding the signing region via the {@link AuthSchemeProvider} that
8386
* is configured on the SDK client builder. If you're using it to call the SDK's signers, you should migrate to a
84-
* subtype of {@code HttpSigner}.
87+
* subtype of {@link HttpSigner}.
8588
*/
8689
@Deprecated
8790
public static final ExecutionAttribute<Region> SIGNING_REGION =
@@ -97,9 +100,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute {
97100
* for global services like IAM.
98101
*
99102
* @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
100-
* from execution interceptors, you should instead be overriding the signing region scope via the {@code AuthSchemeProvider}
103+
* from execution interceptors, you should instead be overriding the signing region scope via the {@link AuthSchemeProvider}
101104
* that is configured on the SDK client builder. If you're using it to call the SDK's signers, you should migrate to a
102-
* subtype of {@code HttpSigner}.
105+
* subtype of {@link HttpSigner}.
103106
*/
104107
@Deprecated
105108
public static final ExecutionAttribute<RegionScope> SIGNING_REGION_SCOPE =
@@ -114,9 +117,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute {
114117
* The signing name of the service to be using in SigV4 signing
115118
*
116119
* @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
117-
* from execution interceptors, you should instead be overriding the signing region name via the {@code AuthSchemeProvider}
120+
* from execution interceptors, you should instead be overriding the signing region name via the {@link AuthSchemeProvider}
118121
* that is configured on the SDK client builder. If you're using it to call the SDK's signers, you should migrate to a
119-
* subtype of {@code HttpSigner}.
122+
* subtype of {@link HttpSigner}.
120123
*/
121124
@Deprecated
122125
public static final ExecutionAttribute<String> SERVICE_SIGNING_NAME =
@@ -131,9 +134,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute {
131134
* The key to specify whether to use double url encoding during signing.
132135
*
133136
* @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
134-
* from execution interceptors, you should instead be overriding the double-url-encode setting via the {@code
137+
* from execution interceptors, you should instead be overriding the double-url-encode setting via the {@link
135138
* AuthSchemeProvider} that is configured on the SDK client builder. If you're using it to call the SDK's signers, you
136-
* should migrate to a subtype of {@code HttpSigner}.
139+
* should migrate to a subtype of {@link HttpSigner}.
137140
*/
138141
@Deprecated
139142
public static final ExecutionAttribute<Boolean> SIGNER_DOUBLE_URL_ENCODE =
@@ -148,9 +151,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute {
148151
* The key to specify whether to normalize the resource path during signing.
149152
*
150153
* @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
151-
* from execution interceptors, you should instead be overriding the normalize-path setting via the {@code
154+
* from execution interceptors, you should instead be overriding the normalize-path setting via the {@link
152155
* AuthSchemeProvider} that is configured on the SDK client builder. If you're using it to call the SDK's signers, you
153-
* should migrate to a subtype of {@code HttpSigner}.
156+
* should migrate to a subtype of {@link HttpSigner}.
154157
*/
155158
@Deprecated
156159
public static final ExecutionAttribute<Boolean> SIGNER_NORMALIZE_PATH =
@@ -167,9 +170,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute {
167170
* @see Aws4SignerParams.Builder#signingClockOverride(Clock)
168171
*
169172
* @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
170-
* from execution interceptors, you should instead be overriding the clock setting via the {@code
173+
* from execution interceptors, you should instead be overriding the clock setting via the {@link
171174
* AuthSchemeProvider} that is configured on the SDK client builder. If you're using it to call the SDK's signers, you
172-
* should migrate to a subtype of {@code HttpSigner}.
175+
* should migrate to a subtype of {@link HttpSigner}.
173176
*/
174177
@Deprecated
175178
public static final ExecutionAttribute<Clock> SIGNING_CLOCK =
@@ -184,9 +187,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute {
184187
* The key to specify the expiration time when pre-signing aws requests.
185188
*
186189
* @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it
187-
* from execution interceptors, you should instead be overriding the expiration via the {@code AuthSchemeProvider} that is
190+
* from execution interceptors, you should instead be overriding the expiration via the {@link AuthSchemeProvider} that is
188191
* configured on the SDK client builder. If you're using it to call the SDK's signers, you should migrate to a subtype of
189-
* {@code HttpSigner}.
192+
* {@link HttpSigner}.
190193
*/
191194
@Deprecated
192195
public static final ExecutionAttribute<Instant> PRESIGNER_EXPIRATION = new ExecutionAttribute<>("PresignerExpiration");

core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthScheme.java

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,118 @@
3131
* <li>A signer - An API that can be used to sign HTTP requests.</li>
3232
* </ol>
3333
*
34+
* <p>
35+
* Auth schemes are used to configure how requests are authenticated. The SDK provides built-in schemes like
36+
* {@code AwsV4AuthScheme} for AWS Signature Version 4, but you can implement custom schemes for specialized
37+
* authentication requirements.
38+
*
39+
* <p>
3440
* See example auth schemes defined <a href="https://smithy.io/2.0/spec/authentication-traits.html">here</a>.
3541
*
42+
* <p>
43+
* <b>Implementing a Custom Auth Scheme</b>
44+
* <p>
45+
* To implement a custom authentication scheme, you need to:
46+
* <ol>
47+
* <li>Implement the {@link AuthScheme} interface</li>
48+
* <li>Implement a custom {@link HttpSigner}</li>
49+
* <li>Configure the scheme on the client builder</li>
50+
* </ol>
51+
*
52+
* <p>
53+
* Example - Custom authentication scheme with custom signer:
54+
*
55+
* {@snippet :
56+
* // Step 1: Implement custom signer
57+
* public class CustomHttpSigner implements HttpSigner<AwsCredentialsIdentity> {
58+
* public static final SignerProperty<String> CUSTOM_HEADER =
59+
* SignerProperty.create(CustomHttpSigner.class, "CustomHeader");
60+
*
61+
* @Override
62+
* public SignedRequest sign(SignRequest<? extends AwsCredentialsIdentity> request) {
63+
* String headerValue = request.property(CUSTOM_HEADER);
64+
* SdkHttpRequest signedRequest = request.request().toBuilder()
65+
* .putHeader("X-Custom-Auth", headerValue)
66+
* .build();
67+
* return SignedRequest.builder()
68+
* .request(signedRequest)
69+
* .payload(request.payload().orElse(null))
70+
* .build();
71+
* }
72+
*
73+
* @Override
74+
* public CompletableFuture<AsyncSignedRequest> signAsync(AsyncSignRequest<? extends AwsCredentialsIdentity> request) {
75+
* // Async implementation
76+
* }
77+
* }
78+
*
79+
* // Step 2: Implement custom auth scheme
80+
* public class CustomAuthScheme implements AwsV4AuthScheme {
81+
* private static final String SCHEME_ID = "custom.auth#v1";
82+
*
83+
* @Override
84+
* public String schemeId() {
85+
* return SCHEME_ID;
86+
* }
87+
*
88+
* @Override
89+
* public IdentityProvider<AwsCredentialsIdentity> identityProvider(IdentityProviders providers) {
90+
* return providers.identityProvider(AwsCredentialsIdentity.class);
91+
* }
92+
*
93+
* @Override
94+
* public AwsV4HttpSigner signer() {
95+
* return new CustomHttpSigner();
96+
* }
97+
* }
98+
*
99+
* // Step 3: Configure on client
100+
* S3AsyncClient s3 = S3AsyncClient.builder()
101+
* .region(Region.US_WEST_2)
102+
* .credentialsProvider(CREDENTIALS)
103+
* .putAuthScheme(new CustomAuthScheme())
104+
* .build();
105+
* }
106+
*
107+
* <p>
108+
* <b>Overriding Built-in Auth Schemes</b>
109+
* <p>
110+
* You can override built-in auth schemes by providing a custom implementation with the same scheme ID.
111+
* The custom scheme will take precedence over the default.
112+
*
113+
* <p>
114+
* Example - Overriding the default SigV4 scheme:
115+
*
116+
* {@snippet :
117+
* public class CustomSigV4AuthScheme implements AwsV4AuthScheme {
118+
* @Override
119+
* public String schemeId() {
120+
* // Use the same scheme ID as the default SigV4 scheme
121+
* return AwsV4AuthScheme.SCHEME_ID;
122+
* }
123+
*
124+
* @Override
125+
* public IdentityProvider<AwsCredentialsIdentity> identityProvider(IdentityProviders providers) {
126+
* return providers.identityProvider(AwsCredentialsIdentity.class);
127+
* }
128+
*
129+
* @Override
130+
* public AwsV4HttpSigner signer() {
131+
* return new CustomSigV4Signer();
132+
* }
133+
* }
134+
*
135+
* S3AsyncClient s3 = S3AsyncClient.builder()
136+
* .region(Region.US_WEST_2)
137+
* .credentialsProvider(CREDENTIALS)
138+
* .putAuthScheme(new CustomSigV4AuthScheme())
139+
* .build();
140+
* }
141+
*
36142
* @param <T> The type of the {@link Identity} used by this authentication scheme.
37143
* @see IdentityProvider
38144
* @see HttpSigner
145+
* @see AuthSchemeProvider
39146
*/
40147
@SdkPublicApi
41148
public interface AuthScheme<T extends Identity> {

core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthSchemeOption.java

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,108 @@
2525
/**
2626
* An authentication scheme option, composed of the scheme ID and properties for use when resolving the identity and signing
2727
* the request.
28+
*
29+
* <p>
30+
* Auth scheme options are returned by {@link AuthSchemeProvider}s to specify which authentication schemes should be used
31+
* for a request, along with the properties needed to configure the identity provider and signer. The SDK will attempt
32+
* to use the schemes in the order they are returned.
33+
*
34+
* <p>
35+
* Each option contains:
36+
* <ul>
37+
* <li>A scheme ID - Identifies which {@link AuthScheme} to use (e.g., "aws.auth#sigv4")</li>
38+
* <li>Identity properties - Configuration for the identity provider (e.g., account ID, role ARN)</li>
39+
* <li>Signer properties - Configuration for the signer (e.g., signing name, region, algorithm parameters)</li>
40+
* </ul>
41+
*
42+
* <p>
43+
* <b>Using Auth Scheme Options</b>
44+
* <p>
45+
* Auth scheme options are typically created and modified within custom {@link AuthSchemeProvider} implementations
46+
* to customize authentication behavior.
47+
*
48+
* <p>
49+
* Example - Modifying signer properties in an auth scheme option:
50+
*
51+
* {@snippet :
52+
* public class CustomSigningNameAuthSchemeProvider implements S3AuthSchemeProvider {
53+
* private final S3AuthSchemeProvider delegate;
54+
*
55+
* public CustomSigningNameAuthSchemeProvider() {
56+
* this.delegate = S3AuthSchemeProvider.defaultProvider();
57+
* }
58+
*
59+
* @Override
60+
* public List<AuthSchemeOption> resolveAuthScheme(S3AuthSchemeParams authSchemeParams) {
61+
* List<AuthSchemeOption> options = delegate.resolveAuthScheme(authSchemeParams);
62+
* return options.stream()
63+
* .map(option -> option.toBuilder()
64+
* .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "custom-service")
65+
* .putSignerProperty(AwsV4HttpSigner.REGION_NAME, "us-west-2")
66+
* .build())
67+
* .collect(Collectors.toList());
68+
* }
69+
* }
70+
* }
71+
*
72+
* <p>
73+
* <b>Creating Custom Auth Scheme Options</b>
2874
* <p>
29-
* This is used in the output from the auth scheme resolver. The resolver returns a list of these, in the order the auth scheme
30-
* resolver wishes to use them.
75+
* You can create custom auth scheme options from scratch when implementing a custom {@link AuthSchemeProvider}.
76+
*
77+
* <p>
78+
* Example - Creating a custom auth scheme option:
79+
*
80+
* {@snippet :
81+
* public class CustomAuthSchemeProvider implements S3AuthSchemeProvider {
82+
* @Override
83+
* public List<AuthSchemeOption> resolveAuthScheme(S3AuthSchemeParams authSchemeParams) {
84+
* AuthSchemeOption customOption = AuthSchemeOption.builder()
85+
* .schemeId("custom.auth#v1")
86+
* .putSignerProperty(CustomHttpSigner.CUSTOM_HEADER, "custom-value")
87+
* .putIdentityProperty(IdentityProperty.create(CustomAuthSchemeProvider.class, "AccountId"), "123456789")
88+
* .build();
89+
*
90+
* return Collections.singletonList(customOption);
91+
* }
92+
* }
93+
* }
94+
*
95+
* <p>
96+
* <b>Reading Properties from Auth Scheme Options</b>
97+
* <p>
98+
* Within a custom {@link software.amazon.awssdk.http.auth.spi.signer.HttpSigner}, you can read properties from
99+
* the auth scheme option via the sign request.
100+
*
101+
* <p>
102+
* Example - Reading signer properties in a custom signer:
103+
*
104+
* {@snippet :
105+
* public class CustomHttpSigner implements HttpSigner<AwsCredentialsIdentity> {
106+
* public static final SignerProperty<String> CUSTOM_HEADER =
107+
* SignerProperty.create(CustomHttpSigner.class, "CustomHeader");
108+
*
109+
* @Override
110+
* public SignedRequest sign(SignRequest<? extends AwsCredentialsIdentity> request) {
111+
* // Read property that was set on the AuthSchemeOption
112+
* String headerValue = request.property(CUSTOM_HEADER);
113+
*
114+
* SdkHttpRequest signedRequest = request.request().toBuilder()
115+
* .putHeader("X-Custom-Auth", headerValue)
116+
* .build();
117+
*
118+
* return SignedRequest.builder()
119+
* .request(signedRequest)
120+
* .payload(request.payload().orElse(null))
121+
* .build();
122+
* }
123+
* }
124+
* }
31125
*
32126
* @see AuthScheme
127+
* @see AuthSchemeProvider
128+
* @see SignerProperty
129+
* @see IdentityProperty
33130
*/
34131
@SdkPublicApi
35132
public interface AuthSchemeOption extends ToCopyableBuilder<AuthSchemeOption.Builder, AuthSchemeOption> {

0 commit comments

Comments
 (0)