Skip to content

Commit 6e19d00

Browse files
committed
Use endpoint auth hints with resolved scheme
1 parent efb7a93 commit 6e19d00

2 files changed

Lines changed: 102 additions & 1 deletion

File tree

client/client-api/src/main/java/software/amazon/smithy/java/client/core/ClientPipeline.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,12 @@ private <I extends SerializableStruct, O extends SerializableStruct> O afterIden
189189
var identity = identityResult.unwrap();
190190
call.context.put(CallContext.IDENTITY, identity);
191191

192-
// TODO: what to do with supportedAuthSchemes of an endpoint?
193192
Endpoint endpoint = resolveEndpoint(call);
194193
call.context.put(CallContext.ENDPOINT, endpoint);
195194

195+
// Augment signer properties with endpoint auth scheme overrides if present.
196+
resolvedAuthScheme = applyEndpointAuthSchemeOverrides(endpoint, resolvedAuthScheme);
197+
196198
RequestT req = protocol.setServiceEndpoint(requestHook.request(), endpoint);
197199
var signResult = resolvedAuthScheme.sign(req);
198200
req = signResult.signedRequest();
@@ -311,6 +313,34 @@ private <I extends SerializableStruct, O extends SerializableStruct> Endpoint re
311313
return call.endpointResolver.resolveEndpoint(request);
312314
}
313315

316+
@SuppressWarnings("unchecked")
317+
private <IdentityT extends Identity> ResolvedScheme<IdentityT, RequestT> applyEndpointAuthSchemeOverrides(
318+
Endpoint endpoint,
319+
ResolvedScheme<IdentityT, RequestT> resolvedScheme
320+
) {
321+
var endpointAuthSchemes = endpoint.authSchemes();
322+
if (!endpointAuthSchemes.isEmpty()) {
323+
var schemeId = resolvedScheme.authScheme().schemeId().toString();
324+
for (var endpointAuthScheme : endpointAuthSchemes) {
325+
if (schemeId.equals(endpointAuthScheme.authSchemeId())) {
326+
var overrides = endpointAuthScheme.properties();
327+
if (overrides.isEmpty()) {
328+
return resolvedScheme;
329+
}
330+
// Apply the found overrides for the auth scheme.
331+
var merged = Context.create();
332+
resolvedScheme.signerProperties().copyTo(merged);
333+
for (var key : overrides) {
334+
merged.put((Context.Key<Object>) key, endpointAuthScheme.property(key));
335+
}
336+
return new ResolvedScheme<>(merged, resolvedScheme.authScheme(), resolvedScheme.identity());
337+
}
338+
}
339+
}
340+
341+
return resolvedScheme;
342+
}
343+
314344
private <I extends SerializableStruct, O extends SerializableStruct> O deserialize(
315345
ClientCall<I, O> call,
316346
RequestT request,

client/client-core/src/test/java/software/amazon/smithy/java/client/core/ClientPipelineTest.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,29 @@
1313

1414
import java.time.Duration;
1515
import java.util.ArrayList;
16+
import java.util.List;
1617
import java.util.Map;
18+
import java.util.concurrent.atomic.AtomicReference;
1719
import org.junit.jupiter.api.Assertions;
1820
import org.junit.jupiter.api.Test;
21+
import software.amazon.smithy.java.auth.api.SignResult;
22+
import software.amazon.smithy.java.auth.api.identity.Identity;
23+
import software.amazon.smithy.java.auth.api.identity.IdentityResolver;
24+
import software.amazon.smithy.java.auth.api.identity.IdentityResult;
1925
import software.amazon.smithy.java.aws.client.restjson.RestJsonClientProtocol;
26+
import software.amazon.smithy.java.client.core.auth.scheme.AuthScheme;
27+
import software.amazon.smithy.java.client.core.auth.scheme.AuthSchemeOption;
2028
import software.amazon.smithy.java.client.core.auth.scheme.AuthSchemeResolver;
29+
import software.amazon.smithy.java.client.core.endpoint.Endpoint;
30+
import software.amazon.smithy.java.client.core.endpoint.EndpointAuthScheme;
2131
import software.amazon.smithy.java.client.core.endpoint.EndpointResolver;
2232
import software.amazon.smithy.java.client.http.JavaHttpClientTransport;
2333
import software.amazon.smithy.java.client.http.mock.MockPlugin;
2434
import software.amazon.smithy.java.client.http.mock.MockQueue;
35+
import software.amazon.smithy.java.context.Context;
2536
import software.amazon.smithy.java.core.serde.document.Document;
2637
import software.amazon.smithy.java.dynamicclient.DynamicClient;
38+
import software.amazon.smithy.java.http.api.HttpRequest;
2739
import software.amazon.smithy.java.http.api.HttpResponse;
2840
import software.amazon.smithy.java.io.datastream.DataStream;
2941
import software.amazon.smithy.java.retries.api.AcquireInitialTokenRequest;
@@ -188,6 +200,65 @@ public Builder toBuilder() {
188200
assertThat(calls, contains("Acquire", "Refresh", "Success: 1"));
189201
}
190202

203+
@Test
204+
public void endpointAuthSchemeOverridesAugmentSignerProperties() {
205+
var service = ShapeId.from("smithy.example#Sprockets");
206+
var testSchemeId = ShapeId.from("smithy.test#testAuth");
207+
var TEST_KEY = Context.<String>key("test-signing-override");
208+
var capturedProperties = new AtomicReference<Context>();
209+
210+
// Auth scheme with a signer that captures the properties it receives.
211+
var testScheme = AuthScheme.of(
212+
testSchemeId,
213+
HttpRequest.class,
214+
Identity.class,
215+
(request, identity, properties) -> {
216+
capturedProperties.set(properties);
217+
return new SignResult<>(request);
218+
});
219+
220+
// Endpoint resolver that returns an endpoint with an auth scheme override.
221+
EndpointResolver endpointResolver = params -> Endpoint.builder()
222+
.uri("https://example.com")
223+
.addAuthScheme(
224+
EndpointAuthScheme.builder()
225+
.authSchemeId(testSchemeId.toString())
226+
.putProperty(TEST_KEY, "overridden-value")
227+
.build())
228+
.build();
229+
230+
var mockQueue = new MockQueue()
231+
.enqueue(HttpResponse.builder()
232+
.statusCode(200)
233+
.body(DataStream.ofString("{\"id\":\"1\"}"))
234+
.build());
235+
var mock = MockPlugin.builder().addQueue(mockQueue).build();
236+
237+
var client = DynamicClient.builder()
238+
.serviceId(service)
239+
.model(MODEL)
240+
.addPlugin(mock)
241+
.endpointResolver(endpointResolver)
242+
.authSchemeResolver(params -> List.of(new AuthSchemeOption(testSchemeId)))
243+
.putSupportedAuthSchemes(testScheme)
244+
.addIdentityResolver(new IdentityResolver<>() {
245+
@Override
246+
public IdentityResult<Identity> resolveIdentity(Context requestProperties) {
247+
return IdentityResult.of(new Identity() {});
248+
}
249+
250+
@Override
251+
public Class<Identity> identityType() {
252+
return Identity.class;
253+
}
254+
})
255+
.build();
256+
257+
client.call("GetSprocket", Document.ofObject(Map.of("id", "1")));
258+
259+
assertThat(capturedProperties.get().get(TEST_KEY), equalTo("overridden-value"));
260+
}
261+
191262
private static final class Token implements RetryToken {
192263
int retry;
193264

0 commit comments

Comments
 (0)