Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add httpAuthSchemeMiddleware to select an auth scheme #929

Merged
merged 6 commits into from
Sep 20, 2023

Conversation

syall
Copy link
Contributor

@syall syall commented Sep 13, 2023

Issue #, if available:

N/A.

Description of changes:

Dependent on: #948, #949

This PR has changes to codegen httpAuthSchemeMiddleware.

  • Add memoizeIdentityProvider() for normalizing and memoizing config identity properties
  • Allow DefaultIdentityProviderConfig to accept undefined properties
  • Add the httpAuthSchemeMiddleware implementation to select an auth scheme
  • Codegen service-specific interface for HttpAuthSchemeParametersProvider
  • Codegen httpAuthSchemeMiddleware and refactor ConfigField codegen
    • Codegen httpAuthSchemeMiddleware, and also generate resolveHttpAuthSchemeConfig and input / resolved config interfaces.
    • resolveHttpAuthSchemeConfig normalizes ConfigField values, and for the "main" ConfigFields, the property is mapped in DefaultIdentityProviderConfig.
    • ConfigField codegen is removed from ServiceBareBonesClientGenerator and is moved to AddHttpAuthSchemeMiddleware::addConfigInterfaceFields().

Testing:

Note: all changes are gated by the experimentalIdentityAndAuth flag

The codegen diff is as follows:

diff --color -Nur /Users/yuasteve/development/ts-ia/smithy-typescript/smithy-typescript-codegen-test/build_old/smithyprojections/smithy-typescript-codegen-test/client-experimental-identity-and-auth/typescript-codegen/src/WeatherClient.ts /Users/yuasteve/development/ts-ia/smithy-typescript/smithy-typescript-codegen-test/build/smithyprojections/smithy-typescript-codegen-test/client-experimental-identity-and-auth/typescript-codegen/src/WeatherClient.ts
--- /Users/yuasteve/development/ts-ia/smithy-typescript/smithy-typescript-codegen-test/build_old/smithyprojections/smithy-typescript-codegen-test/client-experimental-identity-and-auth/typescript-codegen/src/WeatherClient.ts	2023-09-20 13:49:32
+++ /Users/yuasteve/development/ts-ia/smithy-typescript/smithy-typescript-codegen-test/build/smithyprojections/smithy-typescript-codegen-test/client-experimental-identity-and-auth/typescript-codegen/src/WeatherClient.ts	2023-09-20 13:50:03
@@ -1,6 +1,11 @@
 // smithy-typescript generated code
-import { WeatherHttpAuthSchemeProvider } from "./auth/httpAuthSchemeProvider";
 import {
+  HttpAuthSchemeInputConfig,
+  HttpAuthSchemeResolvedConfig,
+  WeatherHttpAuthSchemeProvider,
+  resolveHttpAuthSchemeConfig,
+} from "./auth/httpAuthSchemeProvider";
+import {
   CreateCityCommandInput,
   CreateCityCommandOutput,
 } from "./commands/CreateCityCommand";
@@ -104,11 +109,8 @@
   resolveEventStreamSerdeConfig,
 } from "@smithy/eventstream-serde-config-resolver";
 import {
-  ApiKeyIdentity,
-  ApiKeyIdentityProvider,
   HttpAuthScheme,
-  TokenIdentity,
-  TokenIdentityProvider,
+  getHttpAuthSchemePlugin,
   getHttpSigningPlugin,
 } from "@smithy/experimental-identity-and-auth";
 import { getContentLengthPlugin } from "@smithy/middleware-content-length";
@@ -131,8 +133,6 @@
   SmithyResolvedConfiguration as __SmithyResolvedConfiguration,
 } from "@smithy/smithy-client";
 import {
-  AwsCredentialIdentity,
-  AwsCredentialIdentityProvider,
   BodyLengthCalculator as __BodyLengthCalculator,
   CheckOptionalClientConfig as __CheckOptionalClientConfig,
   Checksum as __Checksum,
@@ -274,18 +274,6 @@
   disableHostPrefix?: boolean;
 
   /**
-   * experimentalIdentityAndAuth: Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme.
-   * @internal
-   */
-  httpAuthSchemes?: HttpAuthScheme[];
-
-  /**
-   * experimentalIdentityAndAuth: Configuration of an HttpAuthSchemeProvider for a client which resolves which HttpAuthScheme to use.
-   * @internal
-   */
-  httpAuthSchemeProvider?: WeatherHttpAuthSchemeProvider;
-
-  /**
    * Value for how many times a request will be made at most in case of retry.
    */
   maxAttempts?: number | __Provider<number>;
@@ -330,31 +318,23 @@
   defaultsMode?: __DefaultsMode | __Provider<__DefaultsMode>;
 
   /**
-   * The internal function that inject utilities to runtime-specific stream to help users consume the data
+   * experimentalIdentityAndAuth: Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme.
    * @internal
    */
-  sdkStreamMixin?: __SdkStreamMixinInjector;
+  httpAuthSchemes?: HttpAuthScheme[];
 
   /**
-   * The API key to use when making requests.
+   * experimentalIdentityAndAuth: Configuration of an HttpAuthSchemeProvider for a client which resolves which HttpAuthScheme to use.
+   * @internal
    */
-  apiKey?: ApiKeyIdentity | ApiKeyIdentityProvider;
+  httpAuthSchemeProvider?: WeatherHttpAuthSchemeProvider;
 
   /**
-   * The credentials used to sign requests.
+   * The internal function that inject utilities to runtime-specific stream to help users consume the data
+   * @internal
    */
-  credentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider;
+  sdkStreamMixin?: __SdkStreamMixinInjector;
 
-  /**
-   * The AWS region to which this client will send requests.
-   */
-  region?: string | __Provider<string>;
-
-  /**
-   * The token used to authenticate requests.
-   */
-  token?: TokenIdentity | TokenIdentityProvider;
-
 }
 
 /**
@@ -367,6 +347,7 @@
   & CustomEndpointsInputConfig
   & RetryInputConfig
   & EventStreamSerdeInputConfig
+  & HttpAuthSchemeInputConfig
   & ClientInputEndpointParameters
 /**
  * @public
@@ -386,6 +367,7 @@
   & CustomEndpointsResolvedConfig
   & RetryResolvedConfig
   & EventStreamSerdeResolvedConfig
+  & HttpAuthSchemeResolvedConfig
   & ClientResolvedEndpointParameters
 /**
  * @public
@@ -417,11 +399,13 @@
     let _config_4 = resolveCustomEndpointsConfig(_config_3);
     let _config_5 = resolveRetryConfig(_config_4);
     let _config_6 = resolveEventStreamSerdeConfig(_config_5);
-    let _config_7 = resolveRuntimeExtensions(_config_6, configuration?.extensions || []);
-    super(_config_7);
-    this.config = _config_7;
+    let _config_7 = resolveHttpAuthSchemeConfig(_config_6);
+    let _config_8 = resolveRuntimeExtensions(_config_7, configuration?.extensions || []);
+    super(_config_8);
+    this.config = _config_8;
     this.middlewareStack.use(getRetryPlugin(this.config));
     this.middlewareStack.use(getContentLengthPlugin(this.config));
+    this.middlewareStack.use(getHttpAuthSchemePlugin(this.config));
     this.middlewareStack.use(getHttpSigningPlugin(this.config));
   }
 
diff --color -Nur /Users/yuasteve/development/ts-ia/smithy-typescript/smithy-typescript-codegen-test/build_old/smithyprojections/smithy-typescript-codegen-test/client-experimental-identity-and-auth/typescript-codegen/src/auth/httpAuthSchemeProvider.ts /Users/yuasteve/development/ts-ia/smithy-typescript/smithy-typescript-codegen-test/build/smithyprojections/smithy-typescript-codegen-test/client-experimental-identity-and-auth/typescript-codegen/src/auth/httpAuthSchemeProvider.ts
--- /Users/yuasteve/development/ts-ia/smithy-typescript/smithy-typescript-codegen-test/build_old/smithyprojections/smithy-typescript-codegen-test/client-experimental-identity-and-auth/typescript-codegen/src/auth/httpAuthSchemeProvider.ts	2023-09-20 13:49:32
+++ /Users/yuasteve/development/ts-ia/smithy-typescript/smithy-typescript-codegen-test/build/smithyprojections/smithy-typescript-codegen-test/client-experimental-identity-and-auth/typescript-codegen/src/auth/httpAuthSchemeProvider.ts	2023-09-20 13:50:03
@@ -1,13 +1,27 @@
 // smithy-typescript generated code
 import { WeatherClientResolvedConfig } from "../WeatherClient";
 import {
+  ApiKeyIdentity,
+  ApiKeyIdentityProvider,
+  DefaultIdentityProviderConfig,
   HttpApiKeyAuthLocation,
   HttpAuthOption,
   HttpAuthSchemeParameters,
   HttpAuthSchemeParametersProvider,
   HttpAuthSchemeProvider,
+  IdentityProviderConfig,
+  TokenIdentity,
+  TokenIdentityProvider,
+  doesIdentityRequireRefresh,
+  isIdentityExpired,
+  memoizeIdentityProvider,
 } from "@smithy/experimental-identity-and-auth";
 import {
+  AwsCredentialIdentity,
+  AwsCredentialIdentityProvider,
+  Provider as __Provider,
+} from "@smithy/types";
+import {
   getSmithyContext,
   normalizeProvider,
 } from "@smithy/util-middleware";
@@ -22,7 +36,12 @@
 /**
  * @internal
  */
-export const defaultWeatherHttpAuthSchemeParametersProvider: HttpAuthSchemeParametersProvider<WeatherClientResolvedConfig, WeatherHttpAuthSchemeParameters> = async (config, context) => {
+export interface WeatherHttpAuthSchemeParametersProvider extends HttpAuthSchemeParametersProvider<WeatherClientResolvedConfig, WeatherHttpAuthSchemeParameters> {}
+
+/**
+ * @internal
+ */
+export const defaultWeatherHttpAuthSchemeParametersProvider: WeatherHttpAuthSchemeParametersProvider = async (config, context, input) => {
   return {
     operation: getSmithyContext(context).operation as string,
     region: await normalizeProvider(config.region)() || (() => {
@@ -128,4 +147,81 @@
     };
   };
   return options;
+};
+
+/**
+ * @internal
+ */
+export interface HttpAuthSchemeInputConfig {
+  /**
+   * The API key to use when making requests.
+   */
+  apiKey?: ApiKeyIdentity | ApiKeyIdentityProvider;
+  /**
+   * The credentials used to sign requests.
+   */
+  credentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider;
+  /**
+   * The AWS region to which this client will send requests.
+   */
+  region?: string | __Provider<string>;
+  /**
+   * The token used to authenticate requests.
+   */
+  token?: TokenIdentity | TokenIdentityProvider;
+}
+
+/**
+ * @internal
+ */
+export interface HttpAuthSchemeResolvedConfig {
+  /**
+   * The API key to use when making requests.
+   */
+  readonly apiKey?: ApiKeyIdentityProvider;
+  /**
+   * The credentials used to sign requests.
+   */
+  readonly credentials?: AwsCredentialIdentityProvider;
+  /**
+   * The AWS region to which this client will send requests.
+   */
+  readonly region?: __Provider<string>;
+  /**
+   * The token used to authenticate requests.
+   */
+  readonly token?: TokenIdentityProvider;
+  /**
+   * experimentalIdentityAndAuth: provides parameters for HttpAuthSchemeProvider.
+   * @internal
+   */
+  readonly httpAuthSchemeParametersProvider: WeatherHttpAuthSchemeParametersProvider;
+  /**
+   * experimentalIdentityAndAuth: abstraction around identity configuration fields
+   * @internal
+   */
+  readonly identityProviderConfig: IdentityProviderConfig;
+}
+
+/**
+ * @internal
+ */
+export const resolveHttpAuthSchemeConfig = (config: HttpAuthSchemeInputConfig): HttpAuthSchemeResolvedConfig => {
+  const apiKey = memoizeIdentityProvider(config.apiKey, isIdentityExpired, doesIdentityRequireRefresh);
+  const credentials = memoizeIdentityProvider(config.credentials, isIdentityExpired, doesIdentityRequireRefresh);
+  const region = config.region ? normalizeProvider(config.region) : undefined;
+  const token = memoizeIdentityProvider(config.token, isIdentityExpired, doesIdentityRequireRefresh);
+  return {
+    ...config,
+    apiKey,
+    credentials,
+    region,
+    token,
+    httpAuthSchemeParametersProvider: defaultWeatherHttpAuthSchemeParametersProvider,
+    identityProviderConfig: new DefaultIdentityProviderConfig({
+      "aws.auth#sigv4": credentials,
+      "smithy.api#httpApiKeyAuth": apiKey,
+      "smithy.api#httpBearerAuth": token,
+    }),
+  };
 };

If one or more of the packages in the /packages directory has been modified, be sure yarn changeset add has been run and its output has
been committed and included in this pull request. See CONTRIBUTING.md.


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@syall syall force-pushed the add-httpAuthSchemeMiddleware branch 7 times, most recently from bf62a56 to 62e52ec Compare September 14, 2023 21:30
@syall syall force-pushed the add-httpAuthSchemeMiddleware branch 11 times, most recently from 36b9869 to 98ac040 Compare September 19, 2023 02:04
@syall syall marked this pull request as ready for review September 19, 2023 02:48
@syall syall requested review from a team as code owners September 19, 2023 02:48
@syall syall marked this pull request as draft September 19, 2023 18:29
@syall syall force-pushed the add-httpAuthSchemeMiddleware branch 6 times, most recently from 7333963 to 2300662 Compare September 20, 2023 06:40
@syall syall marked this pull request as ready for review September 20, 2023 06:49
@syall syall force-pushed the add-httpAuthSchemeMiddleware branch from 2300662 to d521c11 Compare September 20, 2023 17:34
Steven Yuan added 4 commits September 20, 2023 10:52
`memoizeIdentityProvider()` is based off of `memoize()` in
`@smithy/property-provider`.

`isIdentityExpired()` and `doesIdentityRequireRefresh()` is based on
both `normalizeTokenProvider()` and `normalizeCredentialProvider()`.
@syall syall force-pushed the add-httpAuthSchemeMiddleware branch from d521c11 to 396e4f9 Compare September 20, 2023 17:52
@@ -310,42 +305,10 @@ private void generateClientDefaults() {
+ "trait of an operation.");
writer.write("disableHostPrefix?: boolean;\n");

// feat(experimentalIdentityAndAuth): write httpAuthSchemes and httpAuthSchemeProvider into ClientDefaults
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is moved into AddHttpAuthSchemeMiddleware::addConfigInterfaceFields()

Comment on lines -337 to -340
// feat(experimentalIdentityAndAuth): write any HttpAuthScheme config fields into ClientDefaults
// WARNING: may be changed later in lieu of {@link TypeScriptIntegration#addConfigInterfaceFields()},
// but will depend after HttpAuthScheme integration implementations.
if (settings.getExperimentalIdentityAndAuth()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is moved into AddHttpAuthSchemeMiddleware::customize() where the following interfaces and function are generated:

  • HttpAuthSchemeInputConfig
  • HttpAuthSchemeResolvedConfig
  • resolveHttpAuthSchemeConfig

/**
* @internal
*/
export const memoizeIdentityProvider = <IdentityT extends Identity>(
Copy link
Contributor Author

@syall syall Sep 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is based on memoize() in @smithy/property-provider, except:

  • it also handles undefined values.
  • passes in options from MemoizedIdentityProvider to each call of the initial supplied provider.

@syall syall force-pushed the add-httpAuthSchemeMiddleware branch from 396e4f9 to 3f6c922 Compare September 20, 2023 18:19
… and refactor `ConfigField` codegen

Codegen `httpAuthSchemeMiddleware`, and also generate
`resolveHttpAuthSchemeConfig` and input / resolved config interfaces.

`resolveHttpAuthSchemeConfig` normalizes `ConfigField` values, and for
the "main" `ConfigField`s, the property is mapped in
`DefaultIdentityProviderConfig`.

`ConfigField` codegen is removed from `ServiceBareBonesClientGenerator`
and is moved to
`AddHttpAuthSchemeMiddleware::addConfigInterfaceFields()`.
@syall syall force-pushed the add-httpAuthSchemeMiddleware branch from 3f6c922 to 2a56477 Compare September 20, 2023 20:42
@syall syall merged commit 76e2ef3 into smithy-lang:main Sep 20, 2023
@syall syall deleted the add-httpAuthSchemeMiddleware branch September 20, 2023 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants