/** * Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You * may not use this file except in compliance with the License. A copy of * the License is located at * * http://aws.amazon.com/apache2.0/ * * or in the "license" file accompanying this file. This file is * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF * ANY KIND, either express or implied. See the License for the specific * language governing permissions and limitations under the License. */ import { IdleState, BusyState, TokensFromSignIn } from "./model.js"; export type MediationMode = "conditional" | "immediate" | "optional" | "required" | "silent"; /** * WebAuthn Client Capabilities as defined in the W3C spec. * @see https://w3c.github.io/webauthn/#sctn-client-capabilities */ export interface WebAuthnClientCapabilities { /** Client can create discoverable credentials */ conditionalCreate?: boolean; /** Client can authenticate using discoverable credentials (autofill) */ conditionalGet?: boolean; /** Client supports hybrid transport (Bluetooth, NFC, USB) */ hybridTransport?: boolean; /** Client has passkey platform authenticator with MFA support */ passkeyPlatformAuthenticator?: boolean; /** Client has user-verifying platform authenticator */ userVerifyingPlatformAuthenticator?: boolean; /** Client supports Related Origin Requests */ relatedOrigins?: boolean; /** Client supports signalAllAcceptedCredentials() */ signalAllAcceptedCredentials?: boolean; /** Client supports signalCurrentUserDetails() */ signalCurrentUserDetails?: boolean; /** Client supports signalUnknownCredential() */ signalUnknownCredential?: boolean; /** Chrome-specific: immediate mediation support (Chrome 139+, origin trial) */ immediateGet?: boolean; /** Extension support: prefixed with 'extension:' */ [key: `extension:${string}`]: boolean | undefined; } /** * Get WebAuthn client capabilities with proper type safety. * Returns null if getClientCapabilities is not supported. * * @example * ```typescript * const capabilities = await getClientCapabilities(); * if (capabilities?.immediateGet) { * // Use immediate mediation * } * ``` */ export declare function getClientCapabilities(): Promise; /** * Feature detection for WebAuthn mediation capabilities. * Simplified helper that checks both conditional and immediate mediation support. * * @returns Object with capability flags * * @example * ```typescript * const capabilities = await detectMediationCapabilities(); * if (capabilities.conditional) { * // Use conditional mediation for autofill * authenticateWithFido2({ mediation: 'conditional' }); * } else if (capabilities.immediate) { * // Use immediate mediation for smart sign-in button * try { * await authenticateWithFido2({ mediation: 'immediate' }); * } catch (error) { * if (error.name === 'NotAllowedError') { * showPasswordForm(); * } * } * } * ``` */ export declare function detectMediationCapabilities(): Promise<{ conditional: boolean; immediate: boolean; }>; export interface StoredCredential { credentialId: string; friendlyName: string; createdAt: Date; lastSignIn?: Date; signCount: number; transports?: AuthenticatorTransport[]; } export interface ParsedFido2Assertion { credentialIdB64: string; authenticatorDataB64: string; clientDataJSON_B64: string; signatureB64: string; userHandleB64: string | null; } export interface PreparedFido2SignIn { username: string; session: string; credential: ParsedFido2Assertion; existingDeviceKey?: string; } export declare function fido2CreateCredential({ friendlyName, }: { friendlyName: string | (() => string | Promise); }): Promise; interface StartCreateCredentialResponse { challenge: string; attestation: "none"; rp: { name: string; id?: string; }; user: { id: string; name: string; displayName: string; }; pubKeyCredParams: { type: "public-key"; alg: -7 | -257; }[]; authenticatorSelection: { userVerification: UserVerificationRequirement; }; timeout: number; excludeCredentials: { id: string; type: "public-key"; }[]; } export interface ParsedCredential { clientDataJSON_B64: string; attestationObjectB64: string; transports?: string[]; } export declare function fido2StartCreateCredential(): Promise; export declare function fido2CompleteCreateCredential({ credential, friendlyName, }: { credential: PublicKeyCredential | ParsedCredential; friendlyName: string; }): Promise; export declare function fido2ListCredentials(): Promise<{ authenticators: { createdAt: Date; lastSignIn: Date | undefined; friendlyName: string; credentialId: string; signCount: number; }[]; }>; export declare function fido2DeleteCredential({ credentialId, }: { credentialId: string; }): Promise; export declare function fido2UpdateCredential({ credentialId, friendlyName, }: { credentialId: string; friendlyName: string; }): Promise; interface Fido2Options { challenge: string; timeout?: number; userVerification?: UserVerificationRequirement; relyingPartyId?: string; credentials?: { id: string; transports?: AuthenticatorTransport[]; }[]; signal?: AbortSignal; mediation?: MediationMode; } export declare function fido2getCredential({ relyingPartyId, challenge, credentials, timeout, userVerification, signal, mediation, }: Fido2Options): Promise; /** * Prepares a FIDO2 sign-in by obtaining WebAuthn credentials and Cognito session. * Can be called early (e.g., page load) and the result passed to authenticateWithFido2 later. * * **Performance Tip**: For conditional mediation (autofill), always provide the username if available: * - ✅ WITH username: Challenge created upfront → fast, correct flow * - ⚠️ WITHOUT username: Credential first → extract username → get session → slower, requires backend coordination * * Password managers typically store usernames, so username-based flow is recommended. * * @example * ```typescript * // ✅ Recommended: Fast path with username * const prepared = await prepareFido2SignIn({ * username: 'alice@example.com', * mediation: 'conditional' * }); * * // ⚠️ Slower: Usernameless (only use when username truly unknown) * const prepared = await prepareFido2SignIn({ * mediation: 'conditional' * }); * ``` */ export declare function prepareFido2SignIn({ username, credentials, credentialGetter, mediation, signal, }: { /** Username or alias. Providing this enables the FAST username-based flow. */ username?: string; credentials?: { id: string; transports?: AuthenticatorTransport[]; }[]; credentialGetter?: typeof fido2getCredential; mediation?: MediationMode; signal?: AbortSignal; }): Promise; export declare function authenticateWithFido2({ username, credentials, tokensCb, statusCb, currentStatus, clientMetadata, credentialGetter, mediation, prepared, }: { /** * Username, or alias (e-mail, phone number) * If not specified, sign in with FIDO2 Passkey (discoverable credential) will be attempted */ username?: string; /** * The FIDO2 credentials to use. * Must be specified for non-discoverable credentials to work, optional for Passkeys (discoverable credentials). * Ignored if username is not specified, to force the user agent to look for Passkeys (discoverable credentials). */ credentials?: { id: string; transports?: AuthenticatorTransport[]; }[]; tokensCb?: (tokens: TokensFromSignIn) => void | Promise; statusCb?: (status: BusyState | IdleState) => void; currentStatus?: BusyState | IdleState; clientMetadata?: Record; credentialGetter?: typeof fido2getCredential; /** * WebAuthn mediation mode for controlling authentication flow. * * **'conditional'** - Autofill UI (Password Manager Integration): * - Passkeys appear in browser autofill suggestions * - "Set and forget" - only resolves if user selects from autofill * - userVerification automatically set to "preferred" * - timeout removed (per WebAuthn spec) * - Requires: HTML input with autocomplete="username webauthn" * * **'immediate'** - Frictionless Sign-In Button: * - Shows credential picker if local credentials exist * - Fails fast with NotAllowedError if no local credentials * - Enables intelligent fallback to password forms * - No cross-device/QR code prompts * - Requires: User gesture (button click) * * Usage patterns: * ```typescript * import { detectMediationCapabilities, getClientCapabilities } from './fido2'; * * // Option 1: Simple detection helper * const { conditional, immediate } = await detectMediationCapabilities(); * if (conditional) { * authenticateWithFido2({ * mediation: 'conditional', * statusCb: (status) => console.log(status), * tokensCb: (tokens) => handleSignIn(tokens) * }); * } * * // Option 2: Full capabilities check (advanced) * const capabilities = await getClientCapabilities(); * if (capabilities?.immediateGet) { * try { * await authenticateWithFido2({ mediation: 'immediate' }); * } catch (error) { * if (error.name === 'NotAllowedError') { * // No local credentials - show password form * showPasswordForm(); * } * } * } * * // Option 3: Check multiple capabilities * if (capabilities?.passkeyPlatformAuthenticator) { * // Show biometric icon * } * if (capabilities?.hybridTransport) { * // Offer QR code option * } * ``` * * @see https://passkeys.dev/docs/use-cases/bootstrapping (conditional) * @see https://developer.chrome.com/blog/webauthn-immediate-mediation (immediate) */ mediation?: MediationMode; /** * Optional pre-fetched WebAuthn assertion bundle returned by prepareFido2SignIn(). * When provided, authenticateWithFido2() will skip navigator.credentials.get() * and directly complete the Cognito challenge using this data. */ prepared?: PreparedFido2SignIn; }): { signedIn: Promise; abort: () => void; }; export {};