From a366cdc5bbfc7562085ad01b0ed8f804c1881ba6 Mon Sep 17 00:00:00 2001 From: Zoe Wang <33073555+zoewangg@users.noreply.github.com> Date: Thu, 27 Nov 2025 15:05:34 -0800 Subject: [PATCH 1/2] Add more documentation and code snippet for custom signer --- .../signer/AwsSignerExecutionAttribute.java | 39 ++++--- .../signer/S3SignerExecutionAttribute.java | 6 +- .../http/auth/spi/scheme/AuthScheme.java | 107 ++++++++++++++++++ .../auth/spi/scheme/AuthSchemeOption.java | 101 ++++++++++++++++- .../auth/spi/scheme/AuthSchemeProvider.java | 40 +++++++ .../http/auth/spi/signer/HttpSigner.java | 58 +++++++++- .../http/auth/spi/signer/SignerProperty.java | 101 +++++++++++++++++ .../awssdk/identity/spi/IdentityProvider.java | 98 ++++++++++++++++ .../identity/spi/IdentityProviders.java | 67 ++++++++++- .../config/SdkAdvancedClientOption.java | 25 ++++ .../amazon/awssdk/core/signer/Signer.java | 77 +++++++++++++ 11 files changed, 694 insertions(+), 25 deletions(-) diff --git a/core/auth/src/main/java/software/amazon/awssdk/auth/signer/AwsSignerExecutionAttribute.java b/core/auth/src/main/java/software/amazon/awssdk/auth/signer/AwsSignerExecutionAttribute.java index e8969952670c..7d85704a2e79 100644 --- a/core/auth/src/main/java/software/amazon/awssdk/auth/signer/AwsSignerExecutionAttribute.java +++ b/core/auth/src/main/java/software/amazon/awssdk/auth/signer/AwsSignerExecutionAttribute.java @@ -24,6 +24,7 @@ import software.amazon.awssdk.auth.credentials.AwsCredentials; import software.amazon.awssdk.auth.credentials.CredentialUtils; import software.amazon.awssdk.auth.signer.params.Aws4SignerParams; +import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SelectedAuthScheme; import software.amazon.awssdk.core.interceptor.ExecutionAttribute; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; @@ -36,11 +37,13 @@ import software.amazon.awssdk.http.auth.aws.signer.AwsV4aHttpSigner; import software.amazon.awssdk.http.auth.aws.signer.RegionSet; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; +import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider; import software.amazon.awssdk.http.auth.spi.signer.AsyncSignRequest; import software.amazon.awssdk.http.auth.spi.signer.AsyncSignedRequest; import software.amazon.awssdk.http.auth.spi.signer.HttpSigner; import software.amazon.awssdk.http.auth.spi.signer.SignRequest; import software.amazon.awssdk.http.auth.spi.signer.SignedRequest; +import software.amazon.awssdk.http.auth.spi.signer.SignerProperty; import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; import software.amazon.awssdk.identity.spi.Identity; import software.amazon.awssdk.regions.Region; @@ -51,8 +54,8 @@ * AWS-specific signing attributes attached to the execution. This information is available to {@link ExecutionInterceptor}s and * {@link Signer}s. * - * @deprecated Signer execution attributes have been deprecated in favor of signer properties, set on the auth scheme's signer - * option. + * @deprecated Signer execution attributes have been deprecated in favor of {@link SignerProperty}s, set on the + * {@link AuthSchemeOption}. See {@link AuthSchemeProvider} and {@link SignerProperty} for how to use it. */ @Deprecated @SdkProtectedApi @@ -61,9 +64,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute { * The key under which the request credentials are set. * * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it - * from execution interceptors, you should instead be overriding the credential provider via the {@code SdkRequest}'s + * from execution interceptors, you should instead be overriding the credential provider via the {@link SdkRequest}'s * {@code overrideConfiguration.credentialsProvider}. If you're using it to call the SDK's signers, you should migrate to a - * subtype of {@code HttpSigner}. + * subtype of {@link HttpSigner}. */ @Deprecated public static final ExecutionAttribute AWS_CREDENTIALS = @@ -79,9 +82,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute { * for global services like IAM. * * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it - * from execution interceptors, you should instead be overriding the signing region via the {@code AuthSchemeProvider} that + * from execution interceptors, you should instead be overriding the signing region via the {@link AuthSchemeProvider} that * is configured on the SDK client builder. If you're using it to call the SDK's signers, you should migrate to a - * subtype of {@code HttpSigner}. + * subtype of {@link HttpSigner}. */ @Deprecated public static final ExecutionAttribute SIGNING_REGION = @@ -97,9 +100,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute { * for global services like IAM. * * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it - * from execution interceptors, you should instead be overriding the signing region scope via the {@code AuthSchemeProvider} + * from execution interceptors, you should instead be overriding the signing region scope via the {@link AuthSchemeProvider} * that is configured on the SDK client builder. If you're using it to call the SDK's signers, you should migrate to a - * subtype of {@code HttpSigner}. + * subtype of {@link HttpSigner}. */ @Deprecated public static final ExecutionAttribute SIGNING_REGION_SCOPE = @@ -114,9 +117,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute { * The signing name of the service to be using in SigV4 signing * * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it - * from execution interceptors, you should instead be overriding the signing region name via the {@code AuthSchemeProvider} + * from execution interceptors, you should instead be overriding the signing region name via the {@link AuthSchemeProvider} * that is configured on the SDK client builder. If you're using it to call the SDK's signers, you should migrate to a - * subtype of {@code HttpSigner}. + * subtype of {@link HttpSigner}. */ @Deprecated public static final ExecutionAttribute SERVICE_SIGNING_NAME = @@ -131,9 +134,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute { * The key to specify whether to use double url encoding during signing. * * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it - * from execution interceptors, you should instead be overriding the double-url-encode setting via the {@code + * from execution interceptors, you should instead be overriding the double-url-encode setting via the {@link * AuthSchemeProvider} that is configured on the SDK client builder. If you're using it to call the SDK's signers, you - * should migrate to a subtype of {@code HttpSigner}. + * should migrate to a subtype of {@link HttpSigner}. */ @Deprecated public static final ExecutionAttribute SIGNER_DOUBLE_URL_ENCODE = @@ -148,9 +151,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute { * The key to specify whether to normalize the resource path during signing. * * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it - * from execution interceptors, you should instead be overriding the normalize-path setting via the {@code + * from execution interceptors, you should instead be overriding the normalize-path setting via the {@link * AuthSchemeProvider} that is configured on the SDK client builder. If you're using it to call the SDK's signers, you - * should migrate to a subtype of {@code HttpSigner}. + * should migrate to a subtype of {@link HttpSigner}. */ @Deprecated public static final ExecutionAttribute SIGNER_NORMALIZE_PATH = @@ -167,9 +170,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute { * @see Aws4SignerParams.Builder#signingClockOverride(Clock) * * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it - * from execution interceptors, you should instead be overriding the clock setting via the {@code + * from execution interceptors, you should instead be overriding the clock setting via the {@link * AuthSchemeProvider} that is configured on the SDK client builder. If you're using it to call the SDK's signers, you - * should migrate to a subtype of {@code HttpSigner}. + * should migrate to a subtype of {@link HttpSigner}. */ @Deprecated public static final ExecutionAttribute SIGNING_CLOCK = @@ -184,9 +187,9 @@ public final class AwsSignerExecutionAttribute extends SdkExecutionAttribute { * The key to specify the expiration time when pre-signing aws requests. * * @deprecated This is a protected class that is internal to the SDK, so you shouldn't be using it. If you are using it - * from execution interceptors, you should instead be overriding the expiration via the {@code AuthSchemeProvider} that is + * from execution interceptors, you should instead be overriding the expiration via the {@link AuthSchemeProvider} that is * configured on the SDK client builder. If you're using it to call the SDK's signers, you should migrate to a subtype of - * {@code HttpSigner}. + * {@link HttpSigner}. */ @Deprecated public static final ExecutionAttribute PRESIGNER_EXPIRATION = new ExecutionAttribute<>("PresignerExpiration"); diff --git a/core/auth/src/main/java/software/amazon/awssdk/auth/signer/S3SignerExecutionAttribute.java b/core/auth/src/main/java/software/amazon/awssdk/auth/signer/S3SignerExecutionAttribute.java index e35c1f8d4f89..20528a5d0407 100644 --- a/core/auth/src/main/java/software/amazon/awssdk/auth/signer/S3SignerExecutionAttribute.java +++ b/core/auth/src/main/java/software/amazon/awssdk/auth/signer/S3SignerExecutionAttribute.java @@ -23,19 +23,21 @@ import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.http.auth.aws.signer.AwsV4FamilyHttpSigner; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; +import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider; import software.amazon.awssdk.http.auth.spi.signer.AsyncSignRequest; import software.amazon.awssdk.http.auth.spi.signer.AsyncSignedRequest; import software.amazon.awssdk.http.auth.spi.signer.HttpSigner; import software.amazon.awssdk.http.auth.spi.signer.SignRequest; import software.amazon.awssdk.http.auth.spi.signer.SignedRequest; +import software.amazon.awssdk.http.auth.spi.signer.SignerProperty; import software.amazon.awssdk.identity.spi.Identity; import software.amazon.awssdk.utils.CompletableFutureUtils; /** * S3-specific signing attributes attached to the execution. * - * @deprecated Signer execution attributes have been deprecated in favor of signer properties, set on the auth scheme's signer - * option. + * @deprecated Signer execution attributes have been deprecated in favor of {@link SignerProperty}s, set on the + * {@link AuthSchemeOption}. See {@link AuthSchemeProvider} and {@link SignerProperty} for how to use it. */ @SdkProtectedApi @Deprecated diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthScheme.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthScheme.java index 6f76e7624a1a..ac386e2783e8 100644 --- a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthScheme.java +++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthScheme.java @@ -31,11 +31,118 @@ *
  • A signer - An API that can be used to sign HTTP requests.
  • * * + *

    + * Auth schemes are used to configure how requests are authenticated. The SDK provides built-in schemes like + * {@code AwsV4AuthScheme} for AWS Signature Version 4, but you can implement custom schemes for specialized + * authentication requirements. + * + *

    * See example auth schemes defined here. * + *

    + * Implementing a Custom Auth Scheme + *

    + * To implement a custom authentication scheme, you need to: + *

      + *
    1. Implement the {@link AuthScheme} interface
    2. + *
    3. Implement a custom {@link HttpSigner}
    4. + *
    5. Configure the scheme on the client builder
    6. + *
    + * + *

    + * Example - Custom authentication scheme with custom signer: + * + * {@snippet : + * // Step 1: Implement custom signer + * public class CustomHttpSigner implements HttpSigner { + * public static final SignerProperty CUSTOM_HEADER = + * SignerProperty.create(CustomHttpSigner.class, "CustomHeader"); + * + * @Override + * public SignedRequest sign(SignRequest request) { + * String headerValue = request.property(CUSTOM_HEADER); + * SdkHttpRequest signedRequest = request.request().toBuilder() + * .putHeader("X-Custom-Auth", headerValue) + * .build(); + * return SignedRequest.builder() + * .request(signedRequest) + * .payload(request.payload().orElse(null)) + * .build(); + * } + * + * @Override + * public CompletableFuture signAsync(AsyncSignRequest request) { + * // Async implementation + * } + * } + * + * // Step 2: Implement custom auth scheme + * public class CustomAuthScheme implements AwsV4AuthScheme { + * private static final String SCHEME_ID = "custom.auth#v1"; + * + * @Override + * public String schemeId() { + * return SCHEME_ID; + * } + * + * @Override + * public IdentityProvider identityProvider(IdentityProviders providers) { + * return providers.identityProvider(AwsCredentialsIdentity.class); + * } + * + * @Override + * public AwsV4HttpSigner signer() { + * return new CustomHttpSigner(); + * } + * } + * + * // Step 3: Configure on client + * S3AsyncClient s3 = S3AsyncClient.builder() + * .region(Region.US_WEST_2) + * .credentialsProvider(CREDENTIALS) + * .putAuthScheme(new CustomAuthScheme()) + * .build(); + * } + * + *

    + * Overriding Built-in Auth Schemes + *

    + * You can override built-in auth schemes by providing a custom implementation with the same scheme ID. + * The custom scheme will take precedence over the default. + * + *

    + * Example - Overriding the default SigV4 scheme: + * + * {@snippet : + * public class CustomSigV4AuthScheme implements AwsV4AuthScheme { + * @Override + * public String schemeId() { + * // Use the same scheme ID as the default SigV4 scheme + * return AwsV4AuthScheme.SCHEME_ID; + * } + * + * @Override + * public IdentityProvider identityProvider(IdentityProviders providers) { + * return providers.identityProvider(AwsCredentialsIdentity.class); + * } + * + * @Override + * public AwsV4HttpSigner signer() { + * return new CustomSigV4Signer(); + * } + * } + * + * S3AsyncClient s3 = S3AsyncClient.builder() + * .region(Region.US_WEST_2) + * .credentialsProvider(CREDENTIALS) + * .putAuthScheme(new CustomSigV4AuthScheme()) + * .build(); + * } + * * @param The type of the {@link Identity} used by this authentication scheme. * @see IdentityProvider * @see HttpSigner + * @see AuthSchemeProvider */ @SdkPublicApi public interface AuthScheme { diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthSchemeOption.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthSchemeOption.java index b53cbaaab38c..6954f769ec05 100644 --- a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthSchemeOption.java +++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthSchemeOption.java @@ -25,11 +25,108 @@ /** * An authentication scheme option, composed of the scheme ID and properties for use when resolving the identity and signing * the request. + * + *

    + * Auth scheme options are returned by {@link AuthSchemeProvider}s to specify which authentication schemes should be used + * for a request, along with the properties needed to configure the identity provider and signer. The SDK will attempt + * to use the schemes in the order they are returned. + * + *

    + * Each option contains: + *

      + *
    • A scheme ID - Identifies which {@link AuthScheme} to use (e.g., "aws.auth#sigv4")
    • + *
    • Identity properties - Configuration for the identity provider (e.g., account ID, role ARN)
    • + *
    • Signer properties - Configuration for the signer (e.g., signing name, region, algorithm parameters)
    • + *
    + * + *

    + * Using Auth Scheme Options + *

    + * Auth scheme options are typically created and modified within custom {@link AuthSchemeProvider} implementations + * to customize authentication behavior. + * + *

    + * Example - Modifying signer properties in an auth scheme option: + * + * {@snippet : + * public class CustomSigningNameAuthSchemeProvider implements S3AuthSchemeProvider { + * private final S3AuthSchemeProvider delegate; + * + * public CustomSigningNameAuthSchemeProvider() { + * this.delegate = S3AuthSchemeProvider.defaultProvider(); + * } + * + * @Override + * public List resolveAuthScheme(S3AuthSchemeParams authSchemeParams) { + * List options = delegate.resolveAuthScheme(authSchemeParams); + * return options.stream() + * .map(option -> option.toBuilder() + * .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "custom-service") + * .putSignerProperty(AwsV4HttpSigner.REGION_NAME, "us-west-2") + * .build()) + * .collect(Collectors.toList()); + * } + * } + * } + * + *

    + * Creating Custom Auth Scheme Options *

    - * This is used in the output from the auth scheme resolver. The resolver returns a list of these, in the order the auth scheme - * resolver wishes to use them. + * You can create custom auth scheme options from scratch when implementing a custom {@link AuthSchemeProvider}. + * + *

    + * Example - Creating a custom auth scheme option: + * + * {@snippet : + * public class CustomAuthSchemeProvider implements S3AuthSchemeProvider { + * @Override + * public List resolveAuthScheme(S3AuthSchemeParams authSchemeParams) { + * AuthSchemeOption customOption = AuthSchemeOption.builder() + * .schemeId("custom.auth#v1") + * .putSignerProperty(CustomHttpSigner.CUSTOM_HEADER, "custom-value") + * .putIdentityProperty(IdentityProperty.create(CustomAuthSchemeProvider.class, "AccountId"), "123456789") + * .build(); + * + * return Collections.singletonList(customOption); + * } + * } + * } + * + *

    + * Reading Properties from Auth Scheme Options + *

    + * Within a custom {@link software.amazon.awssdk.http.auth.spi.signer.HttpSigner}, you can read properties from + * the auth scheme option via the sign request. + * + *

    + * Example - Reading signer properties in a custom signer: + * + * {@snippet : + * public class CustomHttpSigner implements HttpSigner { + * public static final SignerProperty CUSTOM_HEADER = + * SignerProperty.create(CustomHttpSigner.class, "CustomHeader"); + * + * @Override + * public SignedRequest sign(SignRequest request) { + * // Read property that was set on the AuthSchemeOption + * String headerValue = request.property(CUSTOM_HEADER); + * + * SdkHttpRequest signedRequest = request.request().toBuilder() + * .putHeader("X-Custom-Auth", headerValue) + * .build(); + * + * return SignedRequest.builder() + * .request(signedRequest) + * .payload(request.payload().orElse(null)) + * .build(); + * } + * } + * } * * @see AuthScheme + * @see AuthSchemeProvider + * @see SignerProperty + * @see IdentityProperty */ @SdkPublicApi public interface AuthSchemeOption extends ToCopyableBuilder { diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthSchemeProvider.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthSchemeProvider.java index d08bdbe520c1..fe81b1e07657 100644 --- a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthSchemeProvider.java +++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/scheme/AuthSchemeProvider.java @@ -16,10 +16,50 @@ package software.amazon.awssdk.http.auth.spi.scheme; import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.http.auth.spi.signer.SignerProperty; /** * A marker interface for an auth scheme provider. An auth scheme provider takes as input a set of service-specific parameters, * and resolves a list of {@link AuthSchemeOption} based on the given parameters. + * + *

    + * Customizing Signer Properties + *

    + * If you need to override specific {@link SignerProperty} values (such as signing name or region), + * it is recommended to wrap the service's default auth scheme provider and update properties on the + * resolved {@link AuthSchemeOption}s. This approach is simpler than implementing a custom {@code HttpSigner}. + * + *

    + * Example - Overriding the service signing name: + * + * {@snippet : + * + * S3AsyncClient s3 = S3AsyncClient.builder() + * .region(Region.US_WEST_2) + * .credentialsProvider(CREDENTIALS) + * .authSchemeProvider(new CustomSigningNameAuthSchemeProvider()) + * .build(); + * + * public class CustomSigningNameAuthSchemeProvider implements S3AuthSchemeProvider { + * + * private final S3AuthSchemeProvider delegate; + * + * public CustomSigningNameAuthSchemeProvider() { + * this.delegate = S3AuthSchemeProvider.defaultProvider(); + * } + * + * @Override + * public List resolveAuthScheme(S3AuthSchemeParams authSchemeParams) { + * List options = delegate.resolveAuthScheme(authSchemeParams); + * return options.stream() + * .map(option -> option.toBuilder() + * .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "MyService") + * .build()) + * .collect(Collectors.toCollection(() -> new ArrayList<>(options.size()))); + * } + * } + * + * } */ @SdkPublicApi public interface AuthSchemeProvider { diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/signer/HttpSigner.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/signer/HttpSigner.java index 0f60bae1d7e0..c5a6b1c57cd6 100644 --- a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/signer/HttpSigner.java +++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/signer/HttpSigner.java @@ -22,11 +22,65 @@ import software.amazon.awssdk.http.auth.spi.internal.signer.DefaultAsyncSignRequest; import software.amazon.awssdk.http.auth.spi.internal.signer.DefaultSignRequest; import software.amazon.awssdk.http.auth.spi.internal.signer.NoOpHttpSigner; +import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme; +import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider; import software.amazon.awssdk.identity.spi.Identity; /** - * Interface for the process of modifying a request destined for a service so that the service can authenticate the SDK - * customer’s identity. + * Interface for the process of modifying a request destined for a service so that the service can authenticate the SDK customer’s + * identity. + * + *

    + * You can configure the signer by first implementing a custom {@link AuthScheme} returning this signer and then configuring + * the {@link AuthScheme}s on the client builder via {@code SdkClientBuilder#putAuthScheme(AuthScheme)}. + * + *

    + * Example - Custom signer implementation: + * + * {@snippet : + * S3AsyncClient s3 = S3AsyncClient.builder() + * .region(Region.US_WEST_2) + * .credentialsProvider(CREDENTIALS) + * .putAuthScheme(new CustomSigV4AuthScheme()) + * .build(); + * + * public class CustomSigV4AuthScheme implements AwsV4AuthScheme { + * @Override + * public String schemeId() { + * return AwsV4AuthScheme.SCHEME_ID; + * } + * + * @Override + * public IdentityProvider identityProvider(IdentityProviders providers) { + * return providers.identityProvider(AwsCredentialsIdentity.class); + * } + * + * @Override + * public AwsV4HttpSigner signer() { + * return new CustomSigV4Signer(); + * } + * + * private class CustomSigV4Signer implements AwsV4HttpSigner { + * @Override + * public SignedRequest sign(SignRequest request) { + * // Custom implementation + * } + * + * @Override + * public CompletableFuture signAsync(AsyncSignRequest request) { + * // Custom implementation + * } + * } + * } + * } + * + *

    + * When to Use Each Approach + *

      + *
    • Use custom {@link AuthSchemeProvider} when you only need to override signing properties + * (service name, region, etc.). See {@link AuthSchemeProvider} for examples.
    • + *
    • Use custom {@link HttpSigner} when you need to change the signing algorithm or logic itself.
    • + *
    * * @param The type of the identity. */ diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/signer/SignerProperty.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/signer/SignerProperty.java index 4c1921f92b96..bb909d4fc63b 100644 --- a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/signer/SignerProperty.java +++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/signer/SignerProperty.java @@ -27,7 +27,108 @@ /** * A strongly-typed property for input to an {@link HttpSigner}. + * + *

    + * Signer properties are used to configure signing behavior by passing parameters to signers through + * {@link software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption}s. Common properties include signing region, + * service name, and signing algorithm parameters. + * + *

    + * Common Built-in Properties + *

    + * The SDK provides several built-in AWS V4 signer properties: + *

      + *
    • {@code AwsV4FamilyHttpSigner.SERVICE_SIGNING_NAME} - The service name to use in the signature
    • + *
    • {@code AwsV4FamilyHttpSigner.REGION_NAME} - The AWS region for signing
    • + *
    • {@code AwsV4FamilyHttpSigner.DOUBLE_URL_ENCODE} - Whether to double URL-encode the path
    • + *
    • {@code AwsV4FamilyHttpSigner.NORMALIZE_PATH} - Whether to normalize the request path
    • + *
    • {@code AwsV4FamilyHttpSigner.PAYLOAD_SIGNING_ENABLED} - Whether to indicate that a payload is signed or not.
    • + *
    + * + *

    + * Overriding Properties via AuthSchemeProvider + *

    + * To override signer properties, implement a custom {@link software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider} + * that wraps the default provider and modifies the properties on resolved + * {@link software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption}s. + * + *

    + * Example - Overriding service signing name: + * + * {@snippet : + * S3AsyncClient s3 = S3AsyncClient.builder() + * .region(Region.US_WEST_2) + * .credentialsProvider(CREDENTIALS) + * .authSchemeProvider(new CustomSigningNameAuthSchemeProvider()) + * .build(); + * + * public class CustomSigningNameAuthSchemeProvider implements S3AuthSchemeProvider { + * private final S3AuthSchemeProvider delegate; + * + * public CustomSigningNameAuthSchemeProvider() { + * this.delegate = S3AuthSchemeProvider.defaultProvider(); + * } + * + * @Override + * public List resolveAuthScheme(S3AuthSchemeParams authSchemeParams) { + * List options = delegate.resolveAuthScheme(authSchemeParams); + * return options.stream() + * .map(option -> option.toBuilder() + * .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "custom-service") + * .build()) + * .collect(Collectors.toList()); + * } + * } + * } + * + *

    + * Creating Custom Properties + *

    + * When implementing a custom {@link HttpSigner}, you can define your own properties to accept additional configuration. + * Properties should be defined as public static constants in your signer class. + * + *

    + * Example - Custom signer with custom property: + * + * {@snippet : + * public class CustomHttpSigner implements HttpSigner { + * // Define custom property + * public static final SignerProperty CUSTOM_HEADER_NAME = + * SignerProperty.create(CustomHttpSigner.class, "CustomHeaderName"); + * + * @Override + * public SignedRequest sign(SignRequest request) { + * // Retrieve property value + * String headerName = request.property(CUSTOM_HEADER_NAME); + * // Use the property in signing logic + * // ... + * } + * } + * + * // Configure the property via AuthSchemeProvider + * public class CustomPropertyAuthSchemeProvider implements S3AuthSchemeProvider { + * private final S3AuthSchemeProvider delegate; + * + * public CustomPropertyAuthSchemeProvider() { + * this.delegate = S3AuthSchemeProvider.defaultProvider(); + * } + * + * @Override + * public List resolveAuthScheme(S3AuthSchemeParams authSchemeParams) { + * List options = delegate.resolveAuthScheme(authSchemeParams); + * return options.stream() + * .map(option -> option.toBuilder() + * .putSignerProperty(CustomHttpSigner.CUSTOM_HEADER_NAME, "X-Custom-Auth") + * .build()) + * .collect(Collectors.toList()); + * } + * } + * } + * * @param The type of the property. + * @see HttpSigner + * @see software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption + * @see software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider */ @SdkPublicApi @Immutable diff --git a/core/identity-spi/src/main/java/software/amazon/awssdk/identity/spi/IdentityProvider.java b/core/identity-spi/src/main/java/software/amazon/awssdk/identity/spi/IdentityProvider.java index f1729a748477..10a9d3b3bb64 100644 --- a/core/identity-spi/src/main/java/software/amazon/awssdk/identity/spi/IdentityProvider.java +++ b/core/identity-spi/src/main/java/software/amazon/awssdk/identity/spi/IdentityProvider.java @@ -22,6 +22,104 @@ /** * Interface for loading {@link Identity} that is used for authentication. + * + *

    + * Identity providers are responsible for resolving credentials, tokens, or other authentication identities + * that are used by signers to authenticate requests. The SDK provides built-in identity providers for common + * identity types like {@link AwsCredentialsIdentity} and {@link TokenIdentity}. + * + *

    + * Common Built-in Identity Providers + *

      + *
    • {@code DefaultCredentialsProvider} - Resolves AWS credentials from the default credential chain
    • + *
    • {@code StaticCredentialsProvider} - Provides static AWS credentials
    • + *
    • {@code ProfileCredentialsProvider} - Resolves credentials from AWS profiles
    • + *
    • {@code StsAssumeRoleCredentialsProvider} - Assumes an IAM role using STS
    • + *
    + * + *

    + * How Identity Providers Work + *

    + * Identity providers are selected by {@link software.amazon.awssdk.http.auth.spi.scheme.AuthScheme}s based on the + * identity type they produce. The SDK matches the identity type required by the auth scheme with the appropriate + * provider from {@link IdentityProviders}. + * + *

    + * Implementing a Custom Identity Provider + *

    + * You can implement custom identity providers for specialized authentication scenarios, such as retrieving + * credentials from a custom credential store or implementing a custom token provider. + * + *

    + * Example - Custom credentials provider: + * + * {@snippet : + * public class CustomCredentialsProvider implements IdentityProvider { + * @Override + * public Class identityType() { + * return AwsCredentialsIdentity.class; + * } + * + * @Override + * public CompletableFuture resolveIdentity(ResolveIdentityRequest request) { + * // Retrieve credentials from custom source + * String accessKeyId = retrieveAccessKeyFromCustomStore(); + * String secretAccessKey = retrieveSecretKeyFromCustomStore(); + * + * AwsCredentialsIdentity credentials = AwsBasicCredentials.create(accessKeyId, secretAccessKey); + * return CompletableFuture.completedFuture(credentials); + * } + * + * private String retrieveAccessKeyFromCustomStore() { + * // Custom implementation + * } + * + * private String retrieveSecretKeyFromCustomStore() { + * // Custom implementation + * } + * } + * + * // Configure on client + * S3Client s3 = S3Client.builder() + * .region(Region.US_WEST_2) + * .credentialsProvider(new CustomCredentialsProvider()) + * .build(); + * } + * + *

    + * Using Identity Properties + *

    + * Identity providers can read {@link IdentityProperty} values from the {@link ResolveIdentityRequest} to + * customize identity resolution based on request-specific parameters. + * + *

    + * Example - Identity provider using properties: + * + * {@snippet : + * public class RoleBasedCredentialsProvider implements IdentityProvider { + * public static final IdentityProperty ROLE_ARN = + * IdentityProperty.create(RoleBasedCredentialsProvider.class, "RoleArn"); + * + * @Override + * public Class identityType() { + * return AwsCredentialsIdentity.class; + * } + * + * @Override + * public CompletableFuture resolveIdentity(ResolveIdentityRequest request) { + * // Read property from request + * String roleArn = request.property(ROLE_ARN); + * + * // Assume role and return credentials + * return assumeRoleAndGetCredentials(roleArn); + * } + * } + * } + * + * @see Identity + * @see IdentityProviders + * @see IdentityProperty + * @see software.amazon.awssdk.http.auth.spi.scheme.AuthScheme */ @SdkPublicApi @ThreadSafe diff --git a/core/identity-spi/src/main/java/software/amazon/awssdk/identity/spi/IdentityProviders.java b/core/identity-spi/src/main/java/software/amazon/awssdk/identity/spi/IdentityProviders.java index 9fd22da84b50..1e5c63d739d2 100644 --- a/core/identity-spi/src/main/java/software/amazon/awssdk/identity/spi/IdentityProviders.java +++ b/core/identity-spi/src/main/java/software/amazon/awssdk/identity/spi/IdentityProviders.java @@ -21,7 +21,72 @@ import software.amazon.awssdk.utils.builder.ToCopyableBuilder; /** - * An interface to allow retrieving an IdentityProvider based on the identity type. + * An interface to allow retrieving an {@link IdentityProvider} based on the identity type. + * + *

    + * {@code IdentityProviders} is a registry that maps identity types to their corresponding identity providers. + * It is used by {@link software.amazon.awssdk.http.auth.spi.scheme.AuthScheme}s to retrieve the appropriate + * identity provider for resolving authentication identities. + * + *

    + * How It Works + *

    + * When an auth scheme needs to resolve an identity, it calls {@link #identityProvider(Class)} with the identity + * type it requires (e.g., {@link AwsCredentialsIdentity}.class). The registry returns the corresponding provider + * that was configured on the client. + * + *

    + * Default Configuration + *

    + * The SDK automatically configures identity providers based on the client configuration: + *

      + *
    • When you set {@code credentialsProvider()} on the client builder, it registers an + * {@link AwsCredentialsIdentity} provider
    • + *
    • When you set {@code tokenProvider()} on the client builder, it registers a {@link TokenIdentity} provider
    • + *
    + * + *

    + * Usage in Auth Schemes + *

    + * Auth schemes use {@code IdentityProviders} to retrieve the appropriate identity provider for their + * identity type. + * + *

    + * Example - Auth scheme using IdentityProviders: + * + * {@snippet : + * public class CustomAuthScheme implements AwsV4AuthScheme { + * @Override + * public String schemeId() { + * return AwsV4AuthScheme.SCHEME_ID; + * } + * + * @Override + * public IdentityProvider identityProvider(IdentityProviders providers) { + * // Retrieve the AWS credentials provider from the registry + * return providers.identityProvider(AwsCredentialsIdentity.class); + * } + * + * @Override + * public AwsV4HttpSigner signer() { + * return new CustomSigV4Signer(); + * } + * } + * } + * + *

    + * Standard Identity Types + *

    + * The SDK provides standard identity types: + *

      + *
    • {@link AwsCredentialsIdentity} - AWS access key credentials
    • + *
    • {@link TokenIdentity} - Bearer tokens
    • + *
    • {@link AwsSessionCredentialsIdentity} - AWS credentials with session token
    • + *
    + * + * @see IdentityProvider + * @see Identity + * @see software.amazon.awssdk.http.auth.spi.scheme.AuthScheme */ @SdkPublicApi public interface IdentityProviders extends ToCopyableBuilder { diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkAdvancedClientOption.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkAdvancedClientOption.java index 8528c36852ab..2bfede1b4636 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkAdvancedClientOption.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkAdvancedClientOption.java @@ -19,7 +19,12 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.core.client.builder.SdkClientBuilder; import software.amazon.awssdk.core.signer.Signer; +import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme; +import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider; +import software.amazon.awssdk.http.auth.spi.signer.HttpSigner; +import software.amazon.awssdk.http.auth.spi.signer.SignerProperty; /** @@ -47,11 +52,31 @@ public class SdkAdvancedClientOption extends ClientOption { /** * Define the signer that should be used when authenticating with AWS. + * + * @deprecated Replaced by {@link HttpSigner}. + *

    + * Migration options: + *

      + *
    • To customize signing logic: Configure via {@link SdkClientBuilder#putAuthScheme(AuthScheme)}. + * See {@link Signer} for examples.
    • + *
    • To override signing properties only: Use custom {@link AuthSchemeProvider}. + * See {@link AuthSchemeProvider} for examples.
    • + *
    */ + @Deprecated public static final SdkAdvancedClientOption SIGNER = new SdkAdvancedClientOption<>(Signer.class); /** * Define the signer that should be used for token-based authentication with AWS. + * @deprecated Replaced by {@link HttpSigner}. + *

    + * Migration options: + *

      + *
    • To customize signing logic: Configure via {@link SdkClientBuilder#putAuthScheme(AuthScheme)}. + * See {@link Signer} for examples.
    • + *
    • To override signing properties only: Use custom {@link AuthSchemeProvider}. + * See {@link AuthSchemeProvider} for examples.
    • + *
    */ public static final SdkAdvancedClientOption TOKEN_SIGNER = new SdkAdvancedClientOption<>(Signer.class); diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/signer/Signer.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/signer/Signer.java index e43b420d908c..35fa65fb4cca 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/signer/Signer.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/signer/Signer.java @@ -17,13 +17,90 @@ import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.core.CredentialType; +import software.amazon.awssdk.core.client.builder.SdkClientBuilder; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme; +import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider; /** * Interface for the signer used for signing the requests. All SDK signer implementations will implement this interface. * * @deprecated Replaced by {@code software.amazon.awssdk.http.auth.spi.signer.HttpSigner} in 'http-auth-spi'. + *

    + * Migration Guide: + *

      + *
    • For custom signing logic: Implement {@code HttpSigner} and configure via {@link AuthScheme}. See example 1 below.
    • + *
    • For overriding signing properties only: Use custom {@link AuthSchemeProvider} instead. See example 2 below.
    • + *
    + *

    + * Example 1 - Custom signer implementation: + *

    + * {@snippet : + * S3AsyncClient s3 = S3AsyncClient.builder() + * .region(Region.US_WEST_2) + * .credentialsProvider(CREDENTIALS) + * .putAuthScheme(new CustomSigV4AuthScheme()) + * .build(); + * + * public class CustomSigV4AuthScheme implements AwsV4AuthScheme { + * @Override + * public String schemeId() { + * return AwsV4AuthScheme.SCHEME_ID; + * } + * + * @Override + * public IdentityProvider identityProvider(IdentityProviders providers) { + * return providers.identityProvider(AwsCredentialsIdentity.class); + * } + * + * @Override + * public AwsV4HttpSigner signer() { + * return new CustomSigV4Signer(); + * } + * + * private class CustomSigV4Signer implements AwsV4HttpSigner { + * @Override + * public SignedRequest sign(SignRequest request) { + * // Custom implementation + * } + * + * @Override + * public CompletableFuture signAsync(AsyncSignRequest request) { + * // Custom implementation + * } + * } + * } + * } + * + *

    + * Example 2 - Overriding signer properties only: + *

    + * {@snippet : + * S3AsyncClient s3 = S3AsyncClient.builder() + * .region(Region.US_WEST_2) + * .credentialsProvider(CREDENTIALS) + * .authSchemeProvider(new CustomSigningNameAuthSchemeProvider()) + * .build(); + * + * public class CustomSigningNameAuthSchemeProvider implements S3AuthSchemeProvider { + * private final S3AuthSchemeProvider delegate; + * + * public CustomSigningNameAuthSchemeProvider() { + * this.delegate = S3AuthSchemeProvider.defaultProvider(); + * } + * + * @Override + * public List resolveAuthScheme(S3AuthSchemeParams authSchemeParams) { + * List options = delegate.resolveAuthScheme(authSchemeParams); + * return options.stream() + * .map(option -> option.toBuilder() + * .putSignerProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "custom-service") + * .build()) + * .collect(Collectors.toList()); + * } + * } + * } */ @SdkPublicApi @FunctionalInterface From c850c33cd318ff01b10e56587d77ec9309733636 Mon Sep 17 00:00:00 2001 From: Zoe Wang <33073555+zoewangg@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:06:55 -0800 Subject: [PATCH 2/2] Fix build --- .../awssdk/core/client/config/SdkAdvancedClientOption.java | 1 - .../src/main/java/software/amazon/awssdk/core/signer/Signer.java | 1 - 2 files changed, 2 deletions(-) diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkAdvancedClientOption.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkAdvancedClientOption.java index 2bfede1b4636..28924e9aea2d 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkAdvancedClientOption.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkAdvancedClientOption.java @@ -24,7 +24,6 @@ import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider; import software.amazon.awssdk.http.auth.spi.signer.HttpSigner; -import software.amazon.awssdk.http.auth.spi.signer.SignerProperty; /** diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/signer/Signer.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/signer/Signer.java index 35fa65fb4cca..d17fd58526f2 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/signer/Signer.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/signer/Signer.java @@ -17,7 +17,6 @@ import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.core.CredentialType; -import software.amazon.awssdk.core.client.builder.SdkClientBuilder; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;