@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
TypeScript
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>;
}