import { aws_certificatemanager as acm, aws_cloudfront as cloudfront } from 'aws-cdk-lib'; import * as constructs from 'constructs'; import { Extension, ExtensionConfig, AddBehaviorOptions } from './securedCloudFront'; /** * Props for {@link CognitoCustomUiAuth}. * * Configures customer authentication for a storefront CloudFront distribution * using AWS Cognito with a first-party (custom) login UI. Unauthenticated * requests to protected paths are redirected to {@link unauthenticatedRedirectPath} * on the brand's own domain — never to a Cognito hosted UI. The login page * performs SRP client-side and POSTs the resulting tokens to the session-issuance * endpoint; Cognito tokens are never stored in the browser. * * The backend (user pool, HMAC key, auth table, KVS, config secret) is provided * by {@link CognitoAuthInfrastructure} and referenced here via SSM parameters * written under {@link authSsmParamPrefix}. */ export interface CognitoCustomUiAuthProps { /** * CREATE MODE: default cache behaviour for a distribution this construct will * create. Provide with {@link certificate}. Mutually exclusive with * {@link distribution}. You MAY set `functionAssociations` here (e.g. a * geo-routing viewer-request function) — it is merged with the auth-check * function; CloudFront's one-function-per-event-type rule is enforced with a * clear error rather than an L1 override. */ readonly defaultBehavior?: cloudfront.BehaviorOptions; /** Domain names for the auth config (allowed_domains); first is canonical. Required in both modes. */ readonly domainNames: string[]; /** * Name of the shared session config secret the edge Lambdas fetch by name. * MUST match the name the {@link CognitoSessionBackend} created it under. * Override to decouple from the canonical domain. * @default `cloudfront-auth-config-${domainNames[0]}` */ readonly configSecretName?: string; /** CREATE MODE: ACM certificate (us-east-1) covering {@link domainNames}. */ readonly certificate?: acm.ICertificate; /** CREATE MODE: WAF web ACL ARN to associate with the created distribution. */ readonly webAclId?: string; /** * ATTACH MODE: an existing distribution to add the auth endpoint + protected * behaviours to, instead of creating one. Mutually exclusive with * {@link defaultBehavior}/{@link certificate}. CloudFront allows only one * function per event type per behaviour, so the auth-check is added to protected * PATH behaviours (via {@link protect}) — it is NOT forced onto the existing * default behaviour. Use {@link authFunction} to compose it there yourself. */ readonly distribution?: cloudfront.Distribution; /** * Origin for the auth endpoint behaviours (issuance / refresh / logout). These * endpoints are generated entirely by Lambda@Edge and never reach the origin, * but a CloudFront behaviour still requires one. * * Defaults to the {@link defaultBehavior} origin. Set this to a NON-VPC origin * (for example an S3 origin already on the distribution) when the default * behaviour's origin is a CloudFront VPC origin: AWS does not allow an * origin-request Lambda@Edge association on a VPC-origin behaviour, and these * endpoints run at origin-request. REQUIRED in ATTACH MODE (when * {@link distribution} is set). */ readonly authEndpointOrigin?: cloudfront.IOrigin; /** * SSM parameter prefix under which {@link CognitoAuthInfrastructure} published * `configSecretArn`, `kmsKeyArn`, `authTableArn`, `kvsArn`, `cognitoDomain`, * `clientId` and `userPoolId`. */ readonly authSsmParamPrefix: string; /** Region the auth backend (config secret, auth table) lives in. */ readonly authRegion: string; /** First-party path unauthenticated users are redirected to. @default '/login' */ readonly unauthenticatedRedirectPath?: string; /** Extensions applied to the default behaviour. @default [] (public) */ readonly defaultExtensions?: Extension[]; /** Role configuration for the default behaviour. */ readonly defaultExtensionConfig?: ExtensionConfig; /** Inject validated identity claims as origin headers. @default true */ readonly enableHeaderInjection?: boolean; /** * Map of origin header name to session-JWT claim key. * @default { 'x-customer-id': 'customer_id', 'x-customer-email': 'email' } */ readonly headerInjectionClaims?: Record; /** Path of the session-issuance endpoint (POST). @default '/auth/session' */ readonly sessionIssuancePath?: string; /** Mount the silent-refresh endpoint at '/oauth2/refresh'. @default true */ readonly enableRefreshEndpoint?: boolean; /** Mount the logout endpoint at '/oauth2/logout' (POST). @default true */ readonly enableLogoutEndpoint?: boolean; /** URL of the identity-linking hook the issuance endpoint calls to resolve customer_id. */ readonly identityLinkingHookUrl: string; /** Secrets Manager ARN of the shared secret used to authenticate to the hook. */ readonly identityLinkingHookSecretArn?: string; /** Session JWT lifetime, seconds. @default 3600 */ readonly sessionTtlSeconds?: number; /** Stored refresh-token lifetime, days. @default 30 */ readonly refreshTtlDays?: number; /** Path to redirect to after logout. @default '/' */ readonly postLogoutRedirectPath?: string; /** Add SPA custom error responses. @default false */ readonly enableErrorResponses?: boolean; /** Error page path when {@link enableErrorResponses} is set. @default '/error.html' */ readonly errorResponsePagePath?: string; /** Default root object. @default 'index.html' */ readonly defaultRootObject?: string; /** * CREATE MODE: minimum TLS security policy for the created distribution's * viewer connections. Defaults to the current-generation policy; override only * to relax it (not recommended). Ignored in ATTACH MODE — the passed-in * distribution already fixes its own policy. * @default cloudfront.SecurityPolicyProtocol.TLS_V1_2_2025 */ readonly minimumProtocolVersion?: cloudfront.SecurityPolicyProtocol; /** * Allowed viewer HTTP methods for the auth endpoint behaviours (session * issuance, refresh, logout). These endpoints are POST-driven, so the default * permits all methods; CloudFront's GET/HEAD default would otherwise reject the * POST they require. Override to narrow it (must still include POST). * @default cloudfront.AllowedMethods.ALLOW_ALL */ readonly authEndpointAllowedMethods?: cloudfront.AllowedMethods; } /** * Customer authentication for a storefront CloudFront distribution using Cognito * with a custom, brand-domain login UI. * * OWNS (in this library): the edge session-validation function (reused shared * module, redirecting to a first-party /login), the session-issuance / refresh / * logout Lambda@Edge functions, and their IAM wiring. CONSUMES: the Cognito * backend from {@link CognitoAuthInfrastructure}. Does NOT provision the user * pool — that is the backend construct's job. */ export declare class CognitoCustomUiAuth extends constructs.Construct { readonly distribution: cloudfront.Distribution; private readonly composer; private readonly composedFunctions; private readonly kvs; private readonly loginRedirectPath; private readonly enableHeaderInjection; private readonly headerInjectionClaims; private readonly enableRefresh; private lastCreatedFunction; constructor(scope: constructs.Construct, id: string, props: CognitoCustomUiAuthProps); /** * Add a behaviour. Pass `options.extensions = [Extension.REQUIRE_AUTH]` to * protect the path (unauthenticated requests redirect to the login page and * validated identity claims are injected as origin headers). */ addBehavior(pathPattern: string, origin: cloudfront.IOrigin, options?: AddBehaviorOptions): void; /** * Merge two sets of function associations, enforcing CloudFront's rule of one * function per event type per behaviour. The library never composes or inspects * a consumer's function — it only attaches it; combining two functions on the * same event type is the consumer's responsibility (a single function). */ private mergeFunctionAssociations; /** * Add a PROTECTED behaviour: unauthenticated requests redirect to the login * page and validated identity claims are injected as origin headers. * Convenience wrapper over {@link addBehavior} that ensures REQUIRE_AUTH. */ protect(pathPattern: string, origin: cloudfront.IOrigin, options?: AddBehaviorOptions): void; /** * The composed viewer-request auth-check function (REQUIRE_AUTH). Useful in * ATTACH MODE to associate or compose auth onto a behaviour this construct does * not own — e.g. an existing default behaviour, via an L1 override. */ get authFunction(): cloudfront.Function; private buildFunctionAssociations; private composedAuthFunction; private functionCacheKey; private renderConfigPy; private makeEdgeFunction; }