UNPKG

@joinmeow/cognito-passwordless-auth

Version:

Passwordless authentication with Amazon Cognito: FIDO2 (WebAuthn, support for Passkeys)

244 lines (243 loc) 11.9 kB
import { StoredCredential } from "../fido2.js"; import { TokensFromStorage } from "../storage.js"; import { TokensFromRefresh, TokensFromSignIn } from "../model.js"; import { CognitoAccessTokenPayload, CognitoIdTokenPayload } from "../jwt-model.js"; import React from "react"; /** React hook that provides convenient access to the Passwordless lib's features */ export declare function usePasswordless(): { /** The (raw) tokens: ID token, Access token and Refresh Token */ tokens: TokensFromStorage | undefined; /** The JSON parsed ID and Access token */ tokensParsed: { idToken: CognitoIdTokenPayload; accessToken: CognitoAccessTokenPayload; expireAt: Date; } | undefined; /** Is the UI currently refreshing tokens? */ isRefreshingTokens: boolean | undefined; /** Execute (and reschedule) token refresh */ refreshTokens: (abort?: AbortSignal | undefined) => Promise<TokensFromRefresh>; /** Force an immediate token refresh regardless of current token state */ forceRefreshTokens: (abort?: AbortSignal | undefined) => Promise<TokensFromRefresh>; /** Mark the user as active to potentially trigger token refresh */ markUserActive: () => void; /** Last error that occured */ lastError: Error | undefined; /** The status of the most recent sign-in attempt */ signingInStatus: "STARTING_SIGN_IN_WITH_FIDO2" | "COMPLETING_SIGN_IN_WITH_FIDO2" | "SIGNING_IN_WITH_PASSWORD" | "SIGNING_IN_WITH_OTP" | "SIGNING_OUT" | "AUTHENTICATING_WITH_DEVICE" | "STARTING_SIGN_IN_WITH_REDIRECT" | "SIGNED_OUT" | "SIGNED_IN_WITH_FIDO2" | "SIGNED_IN_WITH_PASSWORD" | "SIGNED_IN_WITH_SRP_PASSWORD" | "SIGNED_IN_WITH_PLAINTEXT_PASSWORD" | "SIGNED_IN_WITH_OTP" | "FIDO2_SIGNIN_FAILED" | "SIGNIN_WITH_OTP_FAILED" | "PASSWORD_SIGNIN_FAILED" | "SIGNED_IN_WITH_REDIRECT" | "SIGNIN_WITH_REDIRECT_FAILED"; /** Are we currently busy signing in or out? */ busy: boolean; /** * The overall auth status, e.g. is the user signed in or not? * Use this field to show the relevant UI, e.g. render a sign-in page, * if the status equals "NOT_SIGNED_IN" */ signInStatus: string; /** Is a user verifying platform authenticator available? E.g. Face ID or Touch */ userVerifyingPlatformAuthenticatorAvailable: boolean | undefined; /** The user's registered FIDO2 credentials. Each credential provides `update` and `delete` methods */ fido2Credentials: Fido2Credential[] | undefined; /** Are we currently creating a FIDO2 credential? */ creatingCredential: boolean; /** The device key for remembered device authentication */ deviceKey: string | null; /** * Confirm a device for trusted device authentication. * The device key must be available from a recent authentication response. */ confirmDevice: (deviceName: string) => Promise<{ UserConfirmationNecessary?: boolean | undefined; }>; /** * Update the status of a device (remembered or not_remembered). * Use this after getting userConfirmationNecessary=true in tokens * to set the device as remembered based on user choice. */ updateDeviceStatus: ({ deviceKey, deviceRememberedStatus, }: { deviceKey: string; deviceRememberedStatus: "remembered" | "not_remembered"; }) => Promise<void>; /** * Forget a device to stop using it for trusted device authentication * Note that this is different from just clearing the local device key * as it also removes the device from the user's account on the server */ forgetDevice: (deviceKeyToForget?: string) => Promise<void>; /** * Clear the stored device key locally without removing it from the server */ clearDeviceKey: () => void; /** Register a FIDO2 credential with the Relying Party */ fido2CreateCredential: (args_0: { friendlyName: string | (() => string | Promise<string>); }) => Promise<StoredCredential>; /** Sign out */ signOut: (options?: { skipTokenRevocation?: boolean | undefined; } | undefined) => { signedOut: Promise<void>; abort: () => void; }; /** Sign in with FIDO2 (e.g. Face ID or Touch) */ authenticateWithFido2: ({ username, credentials, clientMetadata, }?: { /** Username, alias (e-mail, phone number) */ username?: string | undefined; credentials?: { id: string; transports?: AuthenticatorTransport[] | undefined; }[] | undefined; clientMetadata?: Record<string, string> | undefined; }) => { signedIn: Promise<TokensFromSignIn>; abort: () => void; }; /** Sign in with username and password (using SRP: Secure Remote Password, where the password isn't sent over the wire) */ authenticateWithSRP: ({ username, password, smsMfaCode, otpMfaCode, newPassword, clientMetadata, rememberDevice, }: { /** * Username, or alias (e-mail, phone number) */ username: string; password: string; smsMfaCode?: (() => Promise<string>) | undefined; otpMfaCode?: (() => Promise<string>) | undefined; /** * Provide a callback that resolves with a new password **when Cognito returns the * `NEW_PASSWORD_REQUIRED` challenge**. Returning a promise lets you prompt the user * only when necessary and keeps the authentication flow fully encapsulated. */ newPassword?: (() => Promise<string>) | undefined; clientMetadata?: Record<string, string> | undefined; /** * Provide a callback that resolves to "true" if the user elected to remember * this device (e.g. after entering the MFA code). The function is only invoked * **after** Cognito tells us `UserConfirmationNecessary === true`. * Similar to `otpMfaCode`, returning a promise lets you prompt the user * during the authentication flow. */ rememberDevice?: (() => Promise<boolean>) | undefined; }) => { signedIn: Promise<TokensFromSignIn>; abort: () => void; }; /** Sign in with username and password (the password is sent in plaintext over the wire) */ authenticateWithPlaintextPassword: ({ username, password, smsMfaCode, otpMfaCode, clientMetadata, rememberDevice, }: { /** * Username, or alias (e-mail, phone number) */ username: string; password: string; smsMfaCode?: (() => Promise<string>) | undefined; otpMfaCode?: (() => Promise<string>) | undefined; clientMetadata?: Record<string, string> | undefined; rememberDevice?: (() => Promise<boolean>) | undefined; }) => { signedIn: Promise<TokensFromSignIn>; abort: () => void; }; /** The current status of TOTP MFA for the user */ totpMfaStatus: { enabled: boolean; preferred: boolean; availableMfaTypes: string[]; }; /** Refresh the TOTP MFA status - use this after enabling/disabling MFA */ refreshTotpMfaStatus: () => Promise<void>; /** Milliseconds since the last user activity (mousemove, keydown, scroll, touch) */ timeSinceLastActivityMs: number | null; /** Seconds (rounded) since the last user activity */ timeSinceLastActivitySeconds: number | null; /** Sign in via Cognito Hosted UI (redirect, e.g. Google) */ signInWithRedirect: ({ provider, customState, oauthParams, }?: { provider?: string | undefined; customState?: string | undefined; oauthParams?: Record<string, string> | undefined; }) => void; /** The current authentication method used for these tokens */ authMethod: "SRP" | "FIDO2" | "PLAINTEXT" | "REDIRECT" | undefined; }; /** React hook that stores and gives access to the last 10 signed in users (from your configured storage) */ export declare function useLocalUserCache(): { /** The current signed-in user */ currentUser: StoredUser | undefined; /** Update the current user's FIDO2 preference */ updateFidoPreference: ({ useFido }: { useFido: "YES" | "NO"; }) => void; /** The list of the 10 last signed-in users in your configured storage (e.g. localStorage) */ lastSignedInUsers: StoredUser[] | undefined; /** Clear the last signed in users from your configured storage (e.g. localStorage) */ clearLastSignedInUsers: () => void; /** The status of the most recent sign-in attempt */ signingInStatus: "STARTING_SIGN_IN_WITH_FIDO2" | "COMPLETING_SIGN_IN_WITH_FIDO2" | "SIGNING_IN_WITH_PASSWORD" | "SIGNING_IN_WITH_OTP" | "SIGNING_OUT" | "AUTHENTICATING_WITH_DEVICE" | "STARTING_SIGN_IN_WITH_REDIRECT" | "SIGNED_OUT" | "SIGNED_IN_WITH_FIDO2" | "SIGNED_IN_WITH_PASSWORD" | "SIGNED_IN_WITH_SRP_PASSWORD" | "SIGNED_IN_WITH_PLAINTEXT_PASSWORD" | "SIGNED_IN_WITH_OTP" | "FIDO2_SIGNIN_FAILED" | "SIGNIN_WITH_OTP_FAILED" | "PASSWORD_SIGNIN_FAILED" | "SIGNED_IN_WITH_REDIRECT" | "SIGNIN_WITH_REDIRECT_FAILED"; /** The current authentication method */ authMethod: "SRP" | "FIDO2" | "PLAINTEXT" | "REDIRECT" | undefined; }; export declare const PasswordlessContextProvider: (props: { children: React.ReactNode; enableLocalUserCache?: boolean; errorFallback?: React.ReactNode; }) => import("react/jsx-runtime").JSX.Element; /** A FIDO2 credential (e.g. Face ID or Touch), with convenient methods for updating and deleting */ type Fido2Credential = StoredCredential & { /** Update the friendly name of the credential */ update: (update: { friendlyName: string; }) => Promise<void>; /** Delete the credential */ delete: () => Promise<void>; /** The credential is currently being updated or deleted */ busy: boolean; }; /** User Details stored in your configured storage (e.g. localStorage) */ type StoredUser = { username: string; email?: string; useFido?: "YES" | "NO" | "ASK"; credentials?: { id: string; transports?: AuthenticatorTransport[]; }[]; /** Last authentication method used by this user */ authMethod?: "SRP" | "FIDO2" | "PLAINTEXT" | "REDIRECT"; }; /** React hook to turn state (or any variable) into a promise that can be awaited */ export declare function useAwaitableState<T>(state: T): { /** Call to get the current awaitable (promise) */ awaitable: () => Promise<T>; /** Resolve the current awaitable (promise) with the current value of state */ resolve: () => void; /** Reject the current awaitable (promise) */ reject: (reason: Error) => void; /** That value of awaitable (promise) once it resolves. This is undefined if (1) awaitable is not yet resolved or (2) the state has changed since awaitable was resolved */ awaited: { value: T; } | undefined; }; /** React hook to manage TOTP MFA setup and verification for a user */ export declare function useTotpMfa(): { /** Current status of the TOTP MFA setup process */ setupStatus: "IDLE" | "GENERATING" | "READY" | "VERIFYING" | "VERIFIED" | "ERROR"; /** Secret code generated for TOTP setup (to display to user) */ secretCode: string | undefined; /** QR code URL that can be turned into a QR code for scanning */ qrCodeUrl: string | undefined; /** Error message if something went wrong */ errorMessage: string | undefined; /** Start the TOTP MFA setup process */ beginSetup: () => Promise<{ SecretCode: string; } | null>; /** Verify the TOTP code to complete setup */ verifySetup: (code: string, deviceName?: string) => Promise<{ Status: string; }>; /** Reset the setup state */ resetSetup: () => void; /** Current status of TOTP MFA configuration for the user */ totpMfaStatus: { enabled: boolean; preferred: boolean; availableMfaTypes: string[]; }; }; export {};