UNPKG

@auth0/auth0-spa-js

Version:

Auth0 SDK for Single Page Applications using Authorization Code Grant Flow with PKCE

226 lines (225 loc) 8.71 kB
import { Auth0Client } from '../Auth0Client'; import type { TokenEndpointResponse } from '../global'; import type { Authenticator, EnrollParams, EnrollmentResponse, ChallengeAuthenticatorParams, ChallengeResponse, VerifyParams, EnrollmentFactor } from './types'; import { MfaClient as Auth0AuthJsMfaClient } from '@auth0/auth0-auth-js'; import { MfaRequirements } from '../errors'; /** * Client for Auth0 MFA API operations * * Manages multi-factor authentication including: * - Listing enrolled authenticators * - Enrolling new authenticators (OTP, SMS, Voice, Push, Email) * - Initiating MFA challenges * - Verifying MFA challenges * * This is a wrapper around auth0-auth-js MfaClient that maintains * backward compatibility with the existing spa-js API. * * MFA context (scope, audience) is stored internally keyed by mfaToken, * enabling concurrent MFA flows without state conflicts. * * @example * ```typescript * try { * await auth0.getTokenSilently({ authorizationParams: { audience: 'https://api.example.com' } }); * } catch (e) { * if (e instanceof MfaRequiredError) { * // SDK automatically stores context for this mfaToken * const authenticators = await auth0.mfa.getAuthenticators({ mfaToken: e.mfa_token }); * // ... complete MFA flow * } * } * ``` */ export declare class MfaApiClient { private authJsMfaClient; private auth0Client; private contextManager; /** * @internal * Do not instantiate directly. Use Auth0Client.mfa instead. */ constructor(authJsMfaClient: Auth0AuthJsMfaClient, auth0Client: Auth0Client); /** * @internal * Stores authentication details (scope, audience, and MFA requirements) for MFA token verification. * This is automatically called by Auth0Client when an mfa_required error occurs. * * The context is stored keyed by the MFA token, enabling concurrent MFA flows. * * @param mfaToken - The MFA token from the mfa_required error response * @param scope - The OAuth scope from the original request (optional) * @param audience - The API audience from the original request (optional) * @param mfaRequirements - The MFA requirements from the mfa_required error (optional) */ setMFAAuthDetails(mfaToken: string, scope?: string, audience?: string, mfaRequirements?: MfaRequirements): void; /** * Gets enrolled MFA authenticators filtered by challenge types from context. * * Challenge types are automatically resolved from the stored MFA context * (set when mfa_required error occurred). * * @param mfaToken - MFA token from mfa_required error * @returns Array of enrolled authenticators matching the challenge types * @throws {MfaListAuthenticatorsError} If the request fails or context not found * * @example Basic usage * ```typescript * try { * await auth0.getTokenSilently(); * } catch (e) { * if (e instanceof MfaRequiredError) { * // SDK automatically uses challenge types from error context * const authenticators = await auth0.mfa.getAuthenticators(e.mfa_token); * } * } * ``` */ getAuthenticators(mfaToken: string): Promise<Authenticator[]>; /** * Enrolls a new MFA authenticator * * Requires MFA access token with 'enroll' scope * * @param params - Enrollment parameters including mfaToken and factorType * @returns Enrollment response with authenticator details * @throws {MfaEnrollmentError} If enrollment fails * * @example OTP enrollment * ```typescript * const enrollment = await mfa.enroll({ * mfaToken: mfaToken, * factorType: 'otp' * }); * console.log(enrollment.secret); // Base32 secret * console.log(enrollment.barcodeUri); // QR code URI * ``` * * @example SMS enrollment * ```typescript * const enrollment = await mfa.enroll({ * mfaToken: mfaToken, * factorType: 'sms', * phoneNumber: '+12025551234' * }); * ``` */ enroll(params: EnrollParams): Promise<EnrollmentResponse>; /** * Initiates an MFA challenge * * Sends OTP via SMS, initiates push notification, or prepares for OTP entry * * @param params - Challenge parameters including mfaToken * @returns Challenge response with oobCode if applicable * @throws {MfaChallengeError} If challenge initiation fails * * @example OTP challenge * ```typescript * const challenge = await mfa.challenge({ * mfaToken: mfaTokenFromLogin, * challengeType: 'otp', * authenticatorId: 'otp|dev_xxx' * }); * // User enters OTP from their authenticator app * ``` * * @example SMS challenge * ```typescript * const challenge = await mfa.challenge({ * mfaToken: mfaTokenFromLogin, * challengeType: 'oob', * authenticatorId: 'sms|dev_xxx' * }); * console.log(challenge.oobCode); // Use for verification * ``` */ challenge(params: ChallengeAuthenticatorParams): Promise<ChallengeResponse>; /** * Gets available MFA enrollment factors from the stored context. * * This method exposes the enrollment options from the mfa_required error's * mfaRequirements.enroll array, eliminating the need for manual parsing. * * @param mfaToken - MFA token from mfa_required error * @returns Array of enrollment factors available for the user (empty array if no enrollment required) * @throws {MfaEnrollmentFactorsError} If MFA context not found * * @example Basic usage * ```typescript * try { * await auth0.getTokenSilently(); * } catch (error) { * if (error.error === 'mfa_required') { * // Get enrollment options from SDK * const enrollOptions = await auth0.mfa.getEnrollmentFactors(error.mfa_token); * // [{ type: 'otp' }, { type: 'phone' }, { type: 'push-notification' }] * * showEnrollmentOptions(enrollOptions); * } * } * ``` * * @example Check if enrollment is required * ```typescript * try { * const factors = await auth0.mfa.getEnrollmentFactors(mfaToken); * if (factors.length > 0) { * // User needs to enroll in MFA * renderEnrollmentUI(factors); * } else { * // No enrollment required, proceed with challenge * } * } catch (error) { * if (error instanceof MfaEnrollmentFactorsError) { * console.error('Context not found:', error.error_description); * } * } * ``` */ getEnrollmentFactors(mfaToken: string): Promise<EnrollmentFactor[]>; /** * Verifies an MFA challenge and completes authentication * * The scope and audience are retrieved from the stored context (set when the * mfa_required error occurred). The grant_type is automatically inferred from * which verification field is provided (otp, oobCode, or recoveryCode). * * @param params - Verification parameters with OTP, OOB code, or recovery code * @returns Token response with access_token, id_token, refresh_token * @throws {MfaVerifyError} If verification fails (invalid code, expired, rate limited) * @throws {MfaVerifyError} If MFA context not found * @throws {MfaVerifyError} If grant_type cannot be inferred * * Rate limits: * - 10 verification attempts allowed * - Refreshes at 1 attempt per 6 minutes * * @example OTP verification (grant_type inferred from otp field) * ```typescript * const tokens = await mfa.verify({ * mfaToken: mfaTokenFromLogin, * otp: '123456' * }); * console.log(tokens.access_token); * ``` * * @example OOB verification (grant_type inferred from oobCode field) * ```typescript * const tokens = await mfa.verify({ * mfaToken: mfaTokenFromLogin, * oobCode: challenge.oobCode, * bindingCode: '123456' // Code user received via SMS * }); * ``` * * @example Recovery code verification (grant_type inferred from recoveryCode field) * ```typescript * const tokens = await mfa.verify({ * mfaToken: mfaTokenFromLogin, * recoveryCode: 'XXXX-XXXX-XXXX' * }); * ``` */ verify(params: VerifyParams): Promise<TokenEndpointResponse>; }