Skip to content

Commit

Permalink
feat(experimentalIdentityAndAuth): update auth flow
Browse files Browse the repository at this point in the history
  • Loading branch information
Steven Yuan committed Nov 9, 2023
1 parent 6a0055f commit f2981f3
Show file tree
Hide file tree
Showing 12 changed files with 558 additions and 153 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { endpointMiddlewareOptions } from "@smithy/middleware-endpoint";
import { HandlerExecutionContext, Pluggable, RelativeMiddlewareOptions, SerializeHandlerOptions } from "@smithy/types";

import { HttpAuthSchemeParameters } from "../HttpAuthSchemeProvider";
import { HttpAuthSchemeParameters, HttpAuthSchemeParametersProvider } from "../HttpAuthSchemeProvider";
import { IdentityProviderConfig } from "../IdentityProviderConfig";
import { httpAuthSchemeMiddleware, PreviouslyResolved } from "./httpAuthSchemeMiddleware";

/**
Expand All @@ -16,6 +17,19 @@ export const httpAuthSchemeEndpointRuleSetMiddlewareOptions: SerializeHandlerOpt
toMiddleware: endpointMiddlewareOptions.name!,
};

/**
* @internal
*/
interface HttpAuthSchemeEndpointRuleSetPluginOptions<
TConfig extends object,
TContext extends HandlerExecutionContext,
TParameters extends HttpAuthSchemeParameters,
TInput extends object
> {
httpAuthSchemeParametersProvider: HttpAuthSchemeParametersProvider<TConfig, TContext, TParameters, TInput>;
identityProviderConfigCreator: (config: TConfig) => IdentityProviderConfig;
}

/**
* @internal
*/
Expand All @@ -25,9 +39,13 @@ export const getHttpAuthSchemeEndpointRuleSetPlugin = <
TParameters extends HttpAuthSchemeParameters,
TInput extends object
>(
config: TConfig & PreviouslyResolved<TConfig, TContext, TParameters, TInput>
config: TConfig & PreviouslyResolved<TParameters>,
options: HttpAuthSchemeEndpointRuleSetPluginOptions<TConfig, TContext, TParameters, TInput>
): Pluggable<any, any> => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(httpAuthSchemeMiddleware(config), httpAuthSchemeEndpointRuleSetMiddlewareOptions);
clientStack.addRelativeTo(httpAuthSchemeMiddleware(config, {
httpAuthSchemeParametersProvider: options.httpAuthSchemeParametersProvider,
identityProviderConfig: options.identityProviderConfigCreator(config),
}), httpAuthSchemeEndpointRuleSetMiddlewareOptions);
},
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { serializerMiddlewareOption } from "@smithy/middleware-serde";
import { HandlerExecutionContext, Pluggable, RelativeMiddlewareOptions, SerializeHandlerOptions } from "@smithy/types";

import { HttpAuthSchemeParameters } from "../HttpAuthSchemeProvider";
import { HttpAuthSchemeParameters, HttpAuthSchemeParametersProvider } from "../HttpAuthSchemeProvider";
import { IdentityProviderConfig } from "../IdentityProviderConfig";
import { httpAuthSchemeMiddleware, PreviouslyResolved } from "./httpAuthSchemeMiddleware";

/**
Expand All @@ -16,6 +17,19 @@ export const httpAuthSchemeMiddlewareOptions: SerializeHandlerOptions & Relative
toMiddleware: serializerMiddlewareOption.name!,
};

/**
* @internal
*/
interface HttpAuthSchemePluginOptions<
TConfig extends object,
TContext extends HandlerExecutionContext,
TParameters extends HttpAuthSchemeParameters,
TInput extends object
> {
httpAuthSchemeParametersProvider: HttpAuthSchemeParametersProvider<TConfig, TContext, TParameters, TInput>;
identityProviderConfigCreator: (config: TConfig) => IdentityProviderConfig;
}

/**
* @internal
*/
Expand All @@ -25,9 +39,13 @@ export const getHttpAuthSchemePlugin = <
TParameters extends HttpAuthSchemeParameters,
TInput extends object
>(
config: TConfig & PreviouslyResolved<TConfig, TContext, TParameters, TInput>
config: TConfig & PreviouslyResolved<TParameters>,
options: HttpAuthSchemePluginOptions<TConfig, TContext, TParameters, TInput>
): Pluggable<any, any> => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(httpAuthSchemeMiddleware(config), httpAuthSchemeMiddlewareOptions);
clientStack.addRelativeTo(httpAuthSchemeMiddleware(config, {
httpAuthSchemeParametersProvider: options.httpAuthSchemeParametersProvider,
identityProviderConfig: options.identityProviderConfigCreator(config),
}), httpAuthSchemeMiddlewareOptions);
},
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
HandlerExecutionContext,
MetadataBearer,
SerializeHandler,
SerializeHandlerArguments,
SerializeHandlerOutput,
Expand All @@ -21,13 +20,21 @@ import { IdentityProviderConfig } from "../IdentityProviderConfig";
* @internal
*/
export interface PreviouslyResolved<
TParameters extends HttpAuthSchemeParameters,
> {
httpAuthSchemes: HttpAuthScheme[];
httpAuthSchemeProvider: HttpAuthSchemeProvider<TParameters>;
}

/**
* @internal
*/
interface HttpAuthSchemeMiddlewareOptions<
TConfig extends object,
TContext extends HandlerExecutionContext,
TParameters extends HttpAuthSchemeParameters,
TInput extends object
> {
httpAuthSchemes: HttpAuthScheme[];
httpAuthSchemeProvider: HttpAuthSchemeProvider<TParameters>;
httpAuthSchemeParametersProvider: HttpAuthSchemeParametersProvider<TConfig, TContext, TParameters, TInput>;
identityProviderConfig: IdentityProviderConfig;
}
Expand Down Expand Up @@ -68,15 +75,16 @@ export const httpAuthSchemeMiddleware = <
TContext extends HttpAuthSchemeMiddlewareHandlerExecutionContext,
TParameters extends HttpAuthSchemeParameters
>(
config: TConfig & PreviouslyResolved<TConfig, TContext, TParameters, TInput>
config: TConfig & PreviouslyResolved<TParameters>,
mwOptions: HttpAuthSchemeMiddlewareOptions<TConfig, TContext, TParameters, TInput>
): SerializeMiddleware<TInput, Output> => (
next: SerializeHandler<TInput, Output>,
context: HttpAuthSchemeMiddlewareHandlerExecutionContext
): SerializeHandler<TInput, Output> => async (
args: SerializeHandlerArguments<TInput>
): Promise<SerializeHandlerOutput<Output>> => {
const options = config.httpAuthSchemeProvider(
await config.httpAuthSchemeParametersProvider(config, context as TContext, args.input)
await mwOptions.httpAuthSchemeParametersProvider(config, context as TContext, args.input)
);
const authSchemes = convertHttpAuthSchemesToMap(config.httpAuthSchemes);
const smithyContext: HttpAuthSchemeMiddlewareSmithyContext = getSmithyContext(context);
Expand All @@ -87,7 +95,7 @@ export const httpAuthSchemeMiddleware = <
failureReasons.push(`HttpAuthScheme \`${option.schemeId}\` was not enabled for this service.`);
continue;
}
const identityProvider = scheme.identityProvider(config.identityProviderConfig);
const identityProvider = scheme.identityProvider(mwOptions.identityProviderConfig);
if (!identityProvider) {
failureReasons.push(`HttpAuthScheme \`${option.schemeId}\` did not have an IdentityProvider configured.`);
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@
import software.amazon.smithy.typescript.codegen.TypeScriptDelegator;
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
import software.amazon.smithy.typescript.codegen.auth.AuthUtils;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthOptionProperty.Type;
import software.amazon.smithy.typescript.codegen.auth.http.sections.DefaultHttpAuthSchemeParametersProviderFunctionCodeSection;
import software.amazon.smithy.typescript.codegen.auth.http.sections.DefaultHttpAuthSchemeProviderFunctionCodeSection;
import software.amazon.smithy.typescript.codegen.auth.http.sections.HttpAuthOptionFunctionsCodeSection;
import software.amazon.smithy.typescript.codegen.auth.http.sections.HttpAuthSchemeParametersProviderInterfaceCodeSection;
import software.amazon.smithy.typescript.codegen.auth.http.sections.HttpAuthSchemeProviderInterfaceCodeSection;
import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration;
import software.amazon.smithy.utils.SmithyInternalApi;
import software.amazon.smithy.utils.StringUtils;
Expand All @@ -42,13 +48,13 @@
@SmithyInternalApi
public class HttpAuthSchemeProviderGenerator implements Runnable {
private final TypeScriptDelegator delegator;
private final Model model;

private final SupportedHttpAuthSchemesIndex authIndex;
private final ServiceIndex serviceIndex;
private final ServiceShape serviceShape;
private final Symbol serviceSymbol;
private final String serviceName;
private final Map<ShapeId, HttpAuthScheme> effectiveHttpAuthSchemes;
private final Map<String, HttpAuthSchemeParameter> httpAuthSchemeParameters;

/**
Expand All @@ -67,15 +73,16 @@ public HttpAuthSchemeProviderGenerator(
List<TypeScriptIntegration> integrations
) {
this.delegator = delegator;
this.model = model;

this.authIndex = new SupportedHttpAuthSchemesIndex(integrations);
this.serviceIndex = ServiceIndex.of(model);
this.serviceShape = settings.getService(model);
this.serviceSymbol = symbolProvider.toSymbol(serviceShape);
this.serviceName = CodegenUtils.getServiceName(settings, model, symbolProvider);
this.httpAuthSchemeParameters = AuthUtils.collectHttpAuthSchemeParameters(
AuthUtils.getAllEffectiveNoAuthAwareAuthSchemes(serviceShape, serviceIndex, authIndex).values());
this.effectiveHttpAuthSchemes =
AuthUtils.getAllEffectiveNoAuthAwareAuthSchemes(serviceShape, serviceIndex, authIndex);
this.httpAuthSchemeParameters =
AuthUtils.collectHttpAuthSchemeParameters(effectiveHttpAuthSchemes.values());
}

@Override
Expand All @@ -98,6 +105,9 @@ export interface WeatherHttpAuthSchemeParameters extends HttpAuthSchemeParameter
*/
private void generateHttpAuthSchemeParametersInterface() {
delegator.useFileWriter(AuthUtils.HTTP_AUTH_SCHEME_PROVIDER_PATH, w -> {
w.pushState(HttpAuthSchemeProviderInterfaceCodeSection.builder()
.serviceName(serviceName)
.build());
w.addDependency(TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.addImport("HttpAuthSchemeParameters", null, TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.openBlock("""
Expand All @@ -111,6 +121,7 @@ export interface $LHttpAuthSchemeParameters extends HttpAuthSchemeParameters {""
w.write("$L?: $C;", parameter.name(), parameter.type());
}
});
w.popState();
});
}

Expand All @@ -129,6 +140,10 @@ export interface WeatherHttpAuthSchemeParametersProvider extends HttpAuthSchemeP
*/
private void generateHttpAuthSchemeParametersProviderInterface() {
delegator.useFileWriter(AuthUtils.HTTP_AUTH_SCHEME_PROVIDER_PATH, w -> {
w.pushState(HttpAuthSchemeParametersProviderInterfaceCodeSection.builder()
.serviceSymbol(serviceSymbol)
.serviceName(serviceName)
.build());
w.addRelativeImport(serviceSymbol.getName() + "ResolvedConfig", null,
Paths.get(".", serviceSymbol.getNamespace()));
w.addDependency(TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
Expand All @@ -146,6 +161,7 @@ export interface $LHttpAuthSchemeParametersProvider extends \
$LHttpAuthSchemeParameters, \
object> {}""",
serviceName, serviceSymbol.getName(), serviceName);
w.popState();
});
}

Expand All @@ -160,6 +176,11 @@ export interface $LHttpAuthSchemeParametersProvider extends \
*/
private void generateDefaultHttpAuthSchemeParametersProviderFunction() {
delegator.useFileWriter(AuthUtils.HTTP_AUTH_SCHEME_PROVIDER_PATH, w -> {
w.pushState(DefaultHttpAuthSchemeParametersProviderFunctionCodeSection.builder()
.serviceSymbol(serviceSymbol)
.serviceName(serviceName)
.httpAuthSchemeParameters(httpAuthSchemeParameters)
.build());
w.addRelativeImport(serviceSymbol.getName() + "ResolvedConfig", null,
Paths.get(".", serviceSymbol.getNamespace()));
w.addDependency(TypeScriptDependency.SMITHY_TYPES);
Expand All @@ -183,15 +204,22 @@ private void generateDefaultHttpAuthSchemeParametersProviderFunction() {
}
});
});
w.popState();
});
}

private void generateHttpAuthOptionFunctions() {
Map<ShapeId, HttpAuthScheme> effectiveAuthSchemes =
AuthUtils.getAllEffectiveNoAuthAwareAuthSchemes(serviceShape, serviceIndex, authIndex);
for (Entry<ShapeId, HttpAuthScheme> entry : effectiveAuthSchemes.entrySet()) {
generateHttpAuthOptionFunction(entry.getKey(), entry.getValue());
}
delegator.useFileWriter(AuthUtils.HTTP_AUTH_SCHEME_PROVIDER_PATH, w -> {
w.pushState(HttpAuthOptionFunctionsCodeSection.builder()
.effectiveHttpAuthSchemes(effectiveHttpAuthSchemes)
.serviceName(serviceName)
.serviceShape(serviceShape)
.build());
for (Entry<ShapeId, HttpAuthScheme> entry : effectiveHttpAuthSchemes.entrySet()) {
generateHttpAuthOptionFunction(w, entry.getKey(), entry.getValue());
}
w.popState();
});
}

/*
Expand All @@ -211,42 +239,44 @@ function createSmithyApiHttpApiKeyAuthHttpAuthOption(authParameters: WeatherHttp
};
};
*/
private void generateHttpAuthOptionFunction(ShapeId shapeId, HttpAuthScheme authScheme) {
delegator.useFileWriter(AuthUtils.HTTP_AUTH_SCHEME_PROVIDER_PATH, w -> {
String normalizedAuthSchemeName = normalizeAuthSchemeName(shapeId);
w.addDependency(TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.addImport("HttpAuthOption", null, TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.openBlock("""
function create$LHttpAuthOption(authParameters: $LHttpAuthSchemeParameters): \
HttpAuthOption {""", "};",
normalizedAuthSchemeName, serviceName,
() -> {
w.openBlock("return {", "};", () -> {
w.write("schemeId: $S,", shapeId.toString());
// If no HttpAuthScheme is registered, there are no HttpAuthOptionProperties available.
if (authScheme == null) {
return;
}
Trait trait = serviceShape.findTrait(authScheme.getTraitId()).orElse(null);
List<HttpAuthOptionProperty> identityProperties =
authScheme.getHttpAuthSchemeOptionParametersByType(Type.IDENTITY);
if (!identityProperties.isEmpty()) {
w.openBlock("identityProperties: {", "},", () -> {
for (HttpAuthOptionProperty parameter : identityProperties) {
w.write("$L: $C,", parameter.name(), parameter.source().apply(trait));
}
});
}
List<HttpAuthOptionProperty> signingProperties =
authScheme.getHttpAuthSchemeOptionParametersByType(Type.SIGNING);
if (!signingProperties.isEmpty()) {
w.openBlock("signingProperties: {", "},", () -> {
for (HttpAuthOptionProperty parameter : signingProperties) {
w.write("$L: $C,", parameter.name(), parameter.source().apply(trait));
}
});
}
});
private void generateHttpAuthOptionFunction(
TypeScriptWriter w,
ShapeId shapeId,
HttpAuthScheme authScheme
) {
String normalizedAuthSchemeName = normalizeAuthSchemeName(shapeId);
w.addDependency(TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.addImport("HttpAuthOption", null, TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.openBlock("""
function create$LHttpAuthOption(authParameters: $LHttpAuthSchemeParameters): \
HttpAuthOption {""", "};\n",
normalizedAuthSchemeName, serviceName,
() -> {
w.openBlock("return {", "};", () -> {
w.write("schemeId: $S,", shapeId.toString());
// If no HttpAuthScheme is registered, there are no HttpAuthOptionProperties available.
if (authScheme == null) {
return;
}
Trait trait = serviceShape.findTrait(authScheme.getTraitId()).orElse(null);
List<HttpAuthOptionProperty> identityProperties =
authScheme.getHttpAuthSchemeOptionParametersByType(Type.IDENTITY);
if (!identityProperties.isEmpty()) {
w.openBlock("identityProperties: {", "},", () -> {
for (HttpAuthOptionProperty parameter : identityProperties) {
w.write("$L: $C,", parameter.name(), parameter.source().apply(trait));
}
});
}
List<HttpAuthOptionProperty> signingProperties =
authScheme.getHttpAuthSchemeOptionParametersByType(Type.SIGNING);
if (!signingProperties.isEmpty()) {
w.openBlock("signingProperties: {", "},", () -> {
for (HttpAuthOptionProperty parameter : signingProperties) {
w.write("$L: $C,", parameter.name(), parameter.source().apply(trait));
}
});
}
});
});
}
Expand All @@ -267,6 +297,9 @@ export interface WeatherHttpAuthSchemeProvider extends HttpAuthSchemeProvider<We
*/
private void generateHttpAuthSchemeProviderInterface() {
delegator.useFileWriter(AuthUtils.HTTP_AUTH_SCHEME_PROVIDER_PATH, w -> {
w.pushState(HttpAuthSchemeProviderInterfaceCodeSection.builder()
.serviceName(serviceName)
.build());
w.addDependency(TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.addImport("HttpAuthSchemeProvider", null, TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.write("""
Expand All @@ -275,6 +308,7 @@ private void generateHttpAuthSchemeProviderInterface() {
*/
export interface $LHttpAuthSchemeProvider extends HttpAuthSchemeProvider<$LHttpAuthSchemeParameters> {}
""", serviceName, serviceName);
w.popState();
});
}

Expand All @@ -292,6 +326,11 @@ export interface $LHttpAuthSchemeProvider extends HttpAuthSchemeProvider<$LHttpA
*/
private void generateDefaultHttpAuthSchemeProviderFunction() {
delegator.useFileWriter(AuthUtils.HTTP_AUTH_SCHEME_PROVIDER_PATH, w -> {
w.pushState(DefaultHttpAuthSchemeProviderFunctionCodeSection.builder()
.serviceName(serviceName)
.serviceIndex(serviceIndex)
.serviceShape(serviceShape)
.build());
w.openBlock("""
/**
* @internal
Expand Down Expand Up @@ -328,6 +367,7 @@ private void generateDefaultHttpAuthSchemeProviderFunction() {
});
w.write("return options;");
});
w.popState();
});
}
}
Loading

0 comments on commit f2981f3

Please sign in to comment.