diff --git a/core/http-auth-spi/pom.xml b/core/http-auth-spi/pom.xml
new file mode 100644
index 000000000000..416e3228a055
--- /dev/null
+++ b/core/http-auth-spi/pom.xml
@@ -0,0 +1,86 @@
+
+
+
+
+ 4.0.0
+
+
+ software.amazon.awssdk
+ core
+ 2.20.47-SNAPSHOT
+
+
+ http-auth-spi
+ AWS Java SDK :: HTTP Auth SPI
+
+ The AWS SDK for Java - HTTP Auth SPI module contains the interfaces for authentication that are used by other
+ modules in the library.
+
+ https://aws.amazon.com/sdkforjava
+
+
+
+ software.amazon.awssdk
+ annotations
+ ${awsjavasdk.version}
+
+
+ software.amazon.awssdk
+ utils
+ ${awsjavasdk.version}
+
+
+ software.amazon.awssdk
+ http-client-spi
+ ${awsjavasdk.version}
+
+
+ org.reactivestreams
+ reactive-streams
+ ${reactive-streams.version}
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ nl.jqno.equalsverifier
+ equalsverifier
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ software.amazon.awssdk.http.auth.spi
+
+
+
+
+
+
+
+
diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/HttpSignRequest.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/HttpSignRequest.java
new file mode 100644
index 000000000000..c67b0c4a5bf7
--- /dev/null
+++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/HttpSignRequest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.awssdk.http.auth.spi;
+
+import java.util.Optional;
+import software.amazon.awssdk.annotations.Immutable;
+import software.amazon.awssdk.annotations.SdkPublicApi;
+import software.amazon.awssdk.annotations.ThreadSafe;
+import software.amazon.awssdk.http.SdkHttpRequest;
+import software.amazon.awssdk.http.auth.spi.internal.DefaultHttpSignRequest;
+import software.amazon.awssdk.utils.builder.SdkBuilder;
+
+/**
+ * Represents a request to be signed by {@link HttpSigner}.
+ *
+ * @param The type of payload of this request.
+ */
+@SdkPublicApi
+@Immutable
+@ThreadSafe
+public interface HttpSignRequest {
+
+ /**
+ * Get a new builder for creating a {@link HttpSignRequest}.
+ */
+ static Builder builder(Class payloadType) {
+ return new DefaultHttpSignRequest.BuilderImpl(payloadType);
+ }
+
+ /**
+ * Returns the type of the payload.
+ */
+ Class payloadType();
+
+ /**
+ * Returns the HTTP request object, without the request body payload.
+ */
+ SdkHttpRequest request();
+
+ /**
+ * Returns the body payload of the request. A payload is optional. By default, the payload will be empty.
+ */
+ Optional payload();
+
+ /**
+ * Returns the property that the {@link HttpSigner} can use during signing.
+ */
+ T property(SignerProperty property);
+
+ /**
+ * A builder for a {@link HttpSignRequest}.
+ */
+ interface Builder extends SdkBuilder, HttpSignRequest> {
+
+ /**
+ * Set the HTTP request object, without the request body payload.
+ */
+ Builder request(SdkHttpRequest request);
+
+ /**
+ * Set the body payload of the request. A payload is optional. By default, the payload will be empty.
+ */
+ Builder payload(PayloadT payload);
+
+ /**
+ * Set a property that the {@link HttpSigner} can use during signing.
+ */
+ Builder putProperty(SignerProperty key, T value);
+ }
+}
diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/HttpSigner.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/HttpSigner.java
new file mode 100644
index 000000000000..60596518403f
--- /dev/null
+++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/HttpSigner.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.awssdk.http.auth.spi;
+
+import java.nio.ByteBuffer;
+import org.reactivestreams.Publisher;
+import software.amazon.awssdk.annotations.SdkPublicApi;
+import software.amazon.awssdk.http.ContentStreamProvider;
+
+/**
+ * Interface for the process of modifying a request destined for a service so that the service can authenticate the SDK
+ * customer’s identity
+ */
+@SdkPublicApi
+public interface HttpSigner {
+
+ /**
+ * Method that takes in a request and returns a signed version of the request.
+ *
+ * @param request The request to sign, with sync payload
+ * @return A signed version of the input request
+ */
+ SignedHttpRequest sign(HttpSignRequest extends ContentStreamProvider> request);
+
+ /**
+ * Method that takes in a request and returns a signed version of the request.
+ *
+ * @param request The request to sign, with async payload
+ * @return A signed version of the input request
+ */
+ SignedHttpRequest> signAsync(HttpSignRequest extends Publisher extends ByteBuffer>> request);
+}
diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/SignedHttpRequest.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/SignedHttpRequest.java
new file mode 100644
index 000000000000..380fdff00f46
--- /dev/null
+++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/SignedHttpRequest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.awssdk.http.auth.spi;
+
+import java.util.Optional;
+import software.amazon.awssdk.annotations.Immutable;
+import software.amazon.awssdk.annotations.SdkPublicApi;
+import software.amazon.awssdk.annotations.ThreadSafe;
+import software.amazon.awssdk.http.SdkHttpRequest;
+import software.amazon.awssdk.http.auth.spi.internal.DefaultSignedHttpRequest;
+import software.amazon.awssdk.utils.builder.SdkBuilder;
+
+/**
+ * Represents a request that has been signed by {@link HttpSigner}.
+ *
+ * @param The type of payload of this request.
+ */
+@SdkPublicApi
+@Immutable
+@ThreadSafe
+public interface SignedHttpRequest {
+
+ /**
+ * Get a new builder for creating a {@link SignedHttpRequest}.
+ */
+ static Builder builder(Class payloadType) {
+ return new DefaultSignedHttpRequest.BuilderImpl(payloadType);
+ }
+
+ /**
+ * Returns the type of the payload.
+ */
+ Class payloadType();
+
+ /**
+ * Returns the HTTP request object, without the request body payload.
+ */
+ SdkHttpRequest request();
+
+ /**
+ * Returns the body payload of the request. A payload is optional. By default, the payload will be empty.
+ */
+ Optional payload();
+
+ /**
+ * A builder for a {@link SignedHttpRequest}.
+ */
+ interface Builder extends SdkBuilder, SignedHttpRequest> {
+
+ /**
+ * Set the HTTP request object, without the request body payload.
+ */
+ Builder request(SdkHttpRequest request);
+
+ /**
+ * Set the body payload of the request. A payload is optional. By default, the payload will be empty.
+ */
+ Builder payload(PayloadT payload);
+ }
+}
diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/SignerProperty.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/SignerProperty.java
new file mode 100644
index 000000000000..7a424a71bdb8
--- /dev/null
+++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/SignerProperty.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.awssdk.http.auth.spi;
+
+import java.util.Objects;
+import software.amazon.awssdk.annotations.Immutable;
+import software.amazon.awssdk.annotations.SdkPublicApi;
+import software.amazon.awssdk.annotations.ThreadSafe;
+import software.amazon.awssdk.utils.ToString;
+import software.amazon.awssdk.utils.Validate;
+
+/**
+ * A strongly-typed property for input to an {@link HttpSigner}.
+ * @param The type of the attribute.
+ */
+@SdkPublicApi
+@Immutable
+@ThreadSafe
+public final class SignerProperty {
+ private final Class clazz;
+ private final String name;
+
+ private SignerProperty(Class clazz, String name) {
+ Validate.paramNotNull(clazz, "clazz");
+ Validate.paramNotBlank(name, "name");
+
+ this.clazz = clazz;
+ this.name = name;
+ }
+
+ public static SignerProperty create(Class clazz, String name) {
+ return new SignerProperty<>(clazz, name);
+ }
+
+ @Override
+ public String toString() {
+ return ToString.builder("SignerProperty")
+ .add("clazz", clazz)
+ .add("name", name)
+ .build();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ SignerProperty> that = (SignerProperty>) o;
+
+ return Objects.equals(clazz, that.clazz) &&
+ Objects.equals(name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ int hashCode = 1;
+ hashCode = 31 * hashCode + Objects.hashCode(clazz);
+ hashCode = 31 * hashCode + Objects.hashCode(name);
+ return hashCode;
+ }
+}
diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/internal/DefaultHttpSignRequest.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/internal/DefaultHttpSignRequest.java
new file mode 100644
index 000000000000..d6a814daa262
--- /dev/null
+++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/internal/DefaultHttpSignRequest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.awssdk.http.auth.spi.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.http.SdkHttpRequest;
+import software.amazon.awssdk.http.auth.spi.HttpSignRequest;
+import software.amazon.awssdk.http.auth.spi.SignerProperty;
+import software.amazon.awssdk.utils.ToString;
+import software.amazon.awssdk.utils.Validate;
+
+@SdkInternalApi
+public final class DefaultHttpSignRequest implements HttpSignRequest {
+
+ private final Class payloadType;
+ private final SdkHttpRequest request;
+ private final PayloadT payload;
+ private final Map, Object> properties;
+
+ DefaultHttpSignRequest(BuilderImpl builder) {
+ this.payloadType = Validate.paramNotNull(builder.payloadType, "payloadType");
+ this.request = Validate.paramNotNull(builder.request, "request");
+ this.payload = builder.payload;
+ this.properties = new HashMap<>(builder.properties);
+ }
+
+ @Override
+ public Class payloadType() {
+ return payloadType;
+ }
+
+ @Override
+ public SdkHttpRequest request() {
+ return request;
+ }
+
+ @Override
+ public Optional payload() {
+ return payload == null ? Optional.empty() : Optional.of(payload);
+ }
+
+ @Override
+ public T property(SignerProperty property) {
+ return (T) properties.get(property);
+ }
+
+ @Override
+ public String toString() {
+ return ToString.builder("DefaultHttpSignRequest")
+ .add("payloadType", payloadType)
+ .add("request", request)
+ .add("properties", properties)
+ .build();
+ }
+
+
+ public static final class BuilderImpl implements Builder {
+ private final Class payloadType;
+ private SdkHttpRequest request;
+ private PayloadT payload;
+ private final Map, Object> properties = new HashMap<>();
+
+ public BuilderImpl(Class payloadType) {
+ this.payloadType = payloadType;
+ }
+
+ @Override
+ public Builder request(SdkHttpRequest request) {
+ this.request = request;
+ return this;
+ }
+
+ @Override
+ public Builder payload(PayloadT payload) {
+ this.payload = payload;
+ return this;
+ }
+
+ @Override
+ public Builder putProperty(SignerProperty key, T value) {
+ this.properties.put(key, value);
+ return this;
+ }
+
+ @Override
+ public HttpSignRequest build() {
+ return new DefaultHttpSignRequest(this);
+ }
+ }
+}
diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/internal/DefaultSignedHttpRequest.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/internal/DefaultSignedHttpRequest.java
new file mode 100644
index 000000000000..d256992ca226
--- /dev/null
+++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/internal/DefaultSignedHttpRequest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.awssdk.http.auth.spi.internal;
+
+import java.util.Optional;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.http.SdkHttpRequest;
+import software.amazon.awssdk.http.auth.spi.SignedHttpRequest;
+import software.amazon.awssdk.utils.ToString;
+import software.amazon.awssdk.utils.Validate;
+
+@SdkInternalApi
+public final class DefaultSignedHttpRequest implements SignedHttpRequest {
+
+ private final Class payloadType;
+ private final SdkHttpRequest request;
+ private final PayloadT payload;
+
+ DefaultSignedHttpRequest(BuilderImpl builder) {
+ this.payloadType = Validate.paramNotNull(builder.payloadType, "payloadType");
+ this.request = Validate.paramNotNull(builder.request, "request");
+ this.payload = builder.payload;
+ }
+
+ @Override
+ public Class payloadType() {
+ return payloadType;
+ }
+
+ @Override
+ public SdkHttpRequest request() {
+ return request;
+ }
+
+ @Override
+ public Optional payload() {
+ return payload == null ? Optional.empty() : Optional.of(payload);
+ }
+
+ @Override
+ public String toString() {
+ return ToString.builder("DefaultSignedHttpRequest")
+ .add("payloadType", payloadType)
+ .add("request", request)
+ // .add("payload", payload)
+ .build();
+ }
+
+ public static final class BuilderImpl implements Builder {
+ private final Class payloadType;
+ private SdkHttpRequest request;
+ private PayloadT payload;
+
+ public BuilderImpl(Class payloadType) {
+ this.payloadType = payloadType;
+ }
+
+ @Override
+ public Builder request(SdkHttpRequest request) {
+ this.request = request;
+ return this;
+ }
+
+ @Override
+ public Builder payload(PayloadT payload) {
+ this.payload = payload;
+ return this;
+ }
+
+ @Override
+ public SignedHttpRequest build() {
+ return new DefaultSignedHttpRequest(this);
+ }
+ }
+}
diff --git a/core/http-auth-spi/src/test/java/software/amazon/awssdk/http/auth/spi/SignerPropertyTest.java b/core/http-auth-spi/src/test/java/software/amazon/awssdk/http/auth/spi/SignerPropertyTest.java
new file mode 100644
index 000000000000..2c819ed6e188
--- /dev/null
+++ b/core/http-auth-spi/src/test/java/software/amazon/awssdk/http/auth/spi/SignerPropertyTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.awssdk.http.auth.spi;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Test;
+
+public class SignerPropertyTest {
+
+ @Test
+ public void equalsHashcode() {
+ EqualsVerifier.forClass(SignerProperty.class)
+ .withNonnullFields("clazz", "name")
+ .verify();
+ }
+}
diff --git a/core/pom.xml b/core/pom.xml
index 575ef4238008..3f8e14089963 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -37,6 +37,7 @@
arns
auth
identity-spi
+ http-auth-spi
auth-crt
sdk-core
aws-core