import * as core from 'aws-cdk-lib'; import { aws_cognito as cognito, aws_iam as iam, aws_kms as kms, aws_lambda as lambda } from 'aws-cdk-lib'; import * as constructs from 'constructs'; type AccountTakeoverRiskConfig = cognito.CfnUserPoolRiskConfigurationAttachment.AccountTakeoverRiskConfigurationTypeProperty; type CompromisedCredentialsRiskConfig = cognito.CfnUserPoolRiskConfigurationAttachment.CompromisedCredentialsRiskConfigurationTypeProperty; /** * Specification for one Cognito app client (e.g. one brand or one front-end). * Public SPA clients: no secret, PKCE (authorization-code grant), SRP. */ export interface CognitoAppClientSpec { /** Logical key used as the construct id and the key in {@link CognitoCustomerPool.userPoolClients}. */ readonly key: string; /** OAuth2 callback URLs for this client (used only by the social/hosted redirect flow). */ readonly callbackUrls?: string[]; /** Logout URLs for this client. */ readonly logoutUrls?: string[]; /** Identity providers this client supports. @default [COGNITO] */ readonly supportedIdentityProviders?: cognito.UserPoolClientIdentityProvider[]; /** Generate a client secret. @default false (public SPA client) */ readonly generateSecret?: boolean; } /** * Same-account SES email configuration for the pool. Synthesises an * `EmailConfiguration` with `EmailSendingAccount: DEVELOPER`. Its purpose is to * satisfy Cognito's precondition for enabling EMAIL_OTP MFA — Cognito requires a * verified same-account SES identity on the pool before it will accept * `EnabledMfas: ['EMAIL_OTP']`, independently of any custom email sender that * overrides actual delivery. */ export interface CognitoCustomerPoolEmailConfig { /** * ARN of a VERIFIED SES identity in the POOL's OWN account (domain identity * preferred; a verified email-address identity also works). Passed to Cognito as * the `EmailConfiguration.SourceArn`. Must be in the pool's region. */ readonly sesVerifiedDomainArn: string; /** * The From address for the pool's SES configuration, e.g. * `2fa@alpha.functionalself.com`. A local-part on the verified identity's domain. */ readonly fromEmail: string; /** Optional display name, e.g. "Functional Self". @default - address only */ readonly fromName?: string; } /** * Optional Cognito Identity Pool + ABAC (attributes-for-access-control) config. * Maps token claims to principal tags so downstream IAM can scope on them. */ export interface CognitoIdentityPoolAbacConfig { /** Allow unauthenticated (guest) identities. @default false */ readonly allowUnauthenticatedIdentities?: boolean; /** * Claim → principal-tag mapping, e.g. `{ sub: 'customer-id' }`. Applied to the * user-pool provider so authenticated sessions carry these as `aws:PrincipalTag/*`. */ readonly principalTags?: Record; /** Managed policies for the authenticated role. @default none (attach your own). */ readonly authenticatedRoleManagedPolicies?: iam.IManagedPolicy[]; } /** * Props for {@link CognitoCustomerPool}. Every value is generic — no * project/brand/domain specifics are baked in; pass them here. */ export interface CognitoCustomerPoolProps { /** User pool name. */ readonly userPoolName?: string; /** Cognito hosted-UI domain prefix (globally unique). */ readonly cognitoDomainPrefix: string; /** App clients to create (typically one per brand/front-end). At least one. */ readonly appClients: CognitoAppClientSpec[]; /** Enable self-service sign-up. @default false */ readonly selfSignUpEnabled?: boolean; /** MFA enforcement. @default REQUIRED */ readonly mfa?: cognito.Mfa; /** Second factors. @default { otp: true, sms: false } */ readonly mfaSecondFactor?: cognito.MfaSecondFactor; /** Password policy. @default minLength 12, upper/lower/digits/symbols. */ readonly passwordPolicy?: cognito.PasswordPolicy; /** Advanced security mode (threat protection). @default OFF */ readonly advancedSecurityMode?: cognito.AdvancedSecurityMode; /** Standard attributes config. */ readonly standardAttributes?: cognito.StandardAttributes; /** Custom attributes. */ readonly customAttributes?: { [key: string]: cognito.ICustomAttribute; }; /** Enable the CUSTOM_AUTH flow on app clients. @default false */ readonly enableCustomAuthFlow?: boolean; /** Access token validity. @default 1 hour */ readonly accessTokenValidity?: core.Duration; /** ID token validity. @default 1 hour */ readonly idTokenValidity?: core.Duration; /** Refresh token validity. @default 30 days */ readonly refreshTokenValidity?: core.Duration; /** Cognito groups to create. */ readonly groups?: string[]; /** * Pre-token-generation Lambda (V2). @default a bundled no-op library Lambda is * created. Pass your own to customise emitted claims. */ readonly preTokenGenerationLambda?: lambda.IFunction; /** * Enable email one-time-password (`EMAIL_OTP`) as the MFA second factor, delivered * by {@link customEmailSenderLambda}. This is set via an L1 override on the * underlying `CfnUserPool` (`EnabledMfas: ['EMAIL_OTP']`) rather than * `mfaSecondFactor.email`, because the CDK L2 requires a managed (`DEVELOPER`) SES * `email` config for `mfaSecondFactor.email` — which is incompatible with a * custom-email-sender-only delivery path. Requires {@link customEmailSenderLambda} * and {@link customSenderKmsKey}, and a pool feature plan of Essentials or higher. * When true, any `otp`/`sms` in {@link mfaSecondFactor} is ignored — EMAIL_OTP is * the sole factor. * @default false */ readonly emailOtpMfa?: boolean; /** * Configure the pool for PASSWORDLESS customer sign-in using choice-based * authentication (`USER_AUTH`) with `EMAIL_OTP` as a first auth factor. The * customer signs in with just their email and a one-time code — no password and * no second factor. Delivered by {@link customEmailSenderLambda}; requires * {@link customSenderKmsKey} and {@link emailConfiguration} (same enablement * precondition as {@link emailOtpMfa}), and an Essentials-or-higher feature plan. * * Hard Cognito constraints this mode encodes (proven against a live pool): * - `PASSWORD` is MANDATORY in `AllowedFirstAuthFactors`; Cognito rejects a list * without it. So the pool allows `[PASSWORD, EMAIL_OTP]` and the CONSUMER's UI * must never offer the password path (always `InitiateAuth(USER_AUTH, * PREFERRED_CHALLENGE=EMAIL_OTP)`). To keep the password unreachable through the * app client too, this mode also drops the `userSrp` auth flow and enables the * `user` (choice-based `ALLOW_USER_AUTH`) flow on the app clients. * - `EMAIL_OTP` as a first factor is INCOMPATIBLE with `MfaConfiguration: ON`, so * this mode forces `mfa: OFF`. NOTE: the `OFF -> ON` transition is irreversible * via the API, so a pool created with this mode cannot later gain MFA in place. * * Mutually exclusive with {@link emailOtpMfa} (email is a first factor here, a * second factor there). @default false */ readonly passwordlessEmailOtp?: boolean; /** * Custom Email Sender Lambda. When set (together with {@link customSenderKmsKey}), * it is wired to the pool via the `CUSTOM_EMAIL_SENDER` trigger and Cognito * delivers all customer emails (MFA codes, verification, temporary passwords) * through this Lambda instead of its default sender or a managed SES sender. * Cognito encrypts each code to {@link customSenderKmsKey}; the Lambda decrypts * it with the AWS Encryption SDK before sending. Requires {@link customSenderKmsKey}. * @default - Cognito's default email delivery */ readonly customEmailSenderLambda?: lambda.IFunction; /** * Symmetric KMS key Cognito uses to encrypt codes for {@link customEmailSenderLambda}. * Required when a custom email sender is provided; ignored otherwise. Cognito is * granted encrypt/decrypt on it; the Lambda must be separately granted decrypt. * @default - no key (only valid when no custom email sender is set) */ readonly customSenderKmsKey?: kms.IKey; /** * Same-account SES email configuration for the pool. REQUIRED when * {@link emailOtpMfa} is set: Cognito refuses to enable EMAIL_OTP MFA unless the * pool carries an `EmailSendingAccount: DEVELOPER` configuration pointing at a * VERIFIED SES identity in the pool's OWN account — this precondition is validated * at the pool-config layer, BEFORE any email is routed, so a * {@link customEmailSenderLambda} (which overrides delivery) does not satisfy it. * * The identity here exists only to satisfy that enablement precondition; when a * custom email sender is attached, Cognito never actually sends through this * identity (the Lambda intercepts every email), so a cross-account or * SES-sandbox delivery path is unaffected. Prefer a verified DOMAIN identity; * a verified email-address identity also works if Cognito rejects the domain form. * @default - no SES config (Cognito default sender; not valid with emailOtpMfa) */ readonly emailConfiguration?: CognitoCustomerPoolEmailConfig; /** * L1 account-takeover risk configuration (requires {@link advancedSecurityMode} * ENFORCED/AUDIT). Passed through to CfnUserPoolRiskConfigurationAttachment. */ readonly accountTakeoverRiskConfiguration?: AccountTakeoverRiskConfig; /** L1 compromised-credentials risk configuration. */ readonly compromisedCredentialsRiskConfiguration?: CompromisedCredentialsRiskConfig; /** Optional identity pool + ABAC configuration. */ readonly identityPool?: CognitoIdentityPoolAbacConfig; /** Removal policy for the pool. @default RETAIN */ readonly removalPolicy?: core.RemovalPolicy; } /** * A generic, reusable secure Cognito **customer** user pool for the custom-UI * (client-side SRP) authentication pattern: public PKCE app clients, MFA, * strong password policy, optional advanced-security threat protection, * per-client (per-brand) app clients, and an optional identity pool with ABAC. * * Provisions ONLY the identity provider. It knows nothing about CloudFront, * sessions, or any specific project — pair it with `CognitoSessionBackend` * (session substrate) and `CognitoCustomUiAuth` (edge/CDN). */ export declare class CognitoCustomerPool extends constructs.Construct { readonly userPool: cognito.UserPool; /** App clients keyed by {@link CognitoAppClientSpec.key}. */ readonly userPoolClients: Record; /** The first app client, for convenience. */ readonly userPoolClient: cognito.UserPoolClient; readonly userPoolDomain: cognito.UserPoolDomain; /** Hosted-UI domain URL, e.g. `.auth..amazoncognito.com`. */ readonly cognitoDomainUrl: string; readonly identityPool?: cognito.CfnIdentityPool; readonly authenticatedRole?: iam.Role; constructor(scope: constructs.Construct, id: string, props: CognitoCustomerPoolProps); } export {};