Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5424aa5

Browse files
committed
docs: restore comprehensive MFA client API section accidentally removed
1 parent 40f24ce commit 5424aa5

1 file changed

Lines changed: 263 additions & 0 deletions

File tree

EXAMPLES.md

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,16 @@
153153
- [Run custom code before Auth Handlers](#run-custom-code-before-auth-handlers)
154154
- [Run code after callback](#run-code-after-callback)
155155
- [Next.js 16 Compatibility](#nextjs-16-compatibility)
156+
- [Multi-Factor Authentication (MFA)](#multi-factor-authentication-mfa-1)
157+
- [Setup & Configuration](#setup--configuration)
158+
- [Handling MfaRequiredError](#handling-mfarequirederror-1)
159+
- [Accessing the MFA API](#accessing-the-mfa-api)
160+
- [Getting Authenticators](#getting-authenticators)
161+
- [Enrollment](#enrollment)
162+
- [Challenge](#challenge)
163+
- [Verify](#verify)
164+
- [MFA Tenant Configuration](#mfa-tenant-configuration-1)
165+
- [MFA Error Handling](#mfa-error-handling)
156166
- [Multiple Custom Domains (MCD)](#multiple-custom-domains-mcd)
157167
- [Overview](#overview-1)
158168
- [Static Mode (Default)](#static-mode-default)
@@ -3758,6 +3768,259 @@ For more details, see the official Next.js documentation:
37583768
➡️ [Upgrading to Next 16 Middleware](https://nextjs.org/docs/app/api-reference/file-conventions/proxy#upgrading-to-nextjs-16)
37593769
➡️ [Proxy.ts Conventions](https://nextjs.org/docs/app/api-reference/file-conventions/proxy)
37603770
3771+
## Multi-Factor Authentication (MFA)
3772+
3773+
> [!NOTE]
3774+
> Multi Factor Authentication support via SDKs is currently in Early Access.
3775+
3776+
The SDK provides comprehensive MFA client APIs to manage multi-factor authentication for your users. The MFA client is accessible via the `mfa` property on both server and client Auth0 instances.
3777+
3778+
### Setup & Configuration
3779+
3780+
Before using MFA APIs, configure your Auth0 tenant:
3781+
3782+
1. **Enable MFA** in [Auth0 Dashboard > Security > Multi-factor Auth](https://manage.auth0.com/#/security/multi-factor-authentication)
3783+
2. **Configure Factors**: Enable OTP, SMS, Email, or Push Notification
3784+
3. **Set Tenant Policy** to "Adaptive" or "Never" (see [MFA Tenant Configuration](#mfa-tenant-configuration))
3785+
4. **Configure MFA Actions** to conditionally enforce MFA for specific resources
3786+
3787+
### Configuration
3788+
3789+
Configure MFA token TTL via options or environment variable:
3790+
3791+
```typescript
3792+
// lib/auth0.ts
3793+
import { Auth0Client } from "@auth0/nextjs-auth0/server";
3794+
3795+
export const auth0 = new Auth0Client({
3796+
mfaContextTtl: 600 // 10 minutes in seconds
3797+
});
3798+
```
3799+
3800+
```bash
3801+
# .env.local
3802+
AUTH0_MFA_CONTEXT_TTL=600
3803+
```
3804+
3805+
Default TTL is 300 seconds (5 minutes), matching Auth0's mfa_token expiration.
3806+
3807+
### Handling MfaRequiredError
3808+
3809+
When you request an Access Token for a resource that requires MFA, Auth0 will return a `403 Forbidden`. The SDK automatically catches this and throws an `MfaRequiredError` containing the `mfaToken` needed to resolve the challenge.
3810+
3811+
**`mfa_required` Response:**
3812+
```json
3813+
{
3814+
"error": "mfa_required",
3815+
"error_description": "Multifactor authentication required",
3816+
"mfa_token": "Fe26...encoded_token"
3817+
}
3818+
```
3819+
3820+
Add a catch handler for `MfaRequiredError` around `getAccessToken` call:
3821+
```js
3822+
try {
3823+
const { token } = await getAccessToken({ audience: "https://api.example.com" });
3824+
} catch (error) {
3825+
if (error instanceof MfaRequiredError) {
3826+
// MFA logic here
3827+
// You can pass the `error.mfa_token` to SDK MFA methods
3828+
// Example, redirect to MFA challenge page that contains MFA handling logic
3829+
redirect(`/mfa?token=${error.mfa_token}`);
3830+
}
3831+
throw error;
3832+
}
3833+
```
3834+
3835+
### Accessing the MFA API
3836+
3837+
The MFA API is accessible on both the server and the client to manage authenticators and perform verification.
3838+
3839+
**On the Server:**
3840+
3841+
The MFA API is available via the `mfa` property of your `Auth0Client` instance.
3842+
3843+
```ts
3844+
// lib/auth0.ts
3845+
import { Auth0Client } from "@auth0/nextjs-auth0/server";
3846+
3847+
export const auth0 = new Auth0Client();
3848+
3849+
// Usage in Route Handler or Server Action
3850+
const authenticators = await auth0.mfa.getAuthenticators({ mfaToken });
3851+
```
3852+
3853+
**On the Client:**
3854+
3855+
The MFA API is available as a named export `mfa` from the client entry point.
3856+
3857+
```ts
3858+
// components/mfa-form.tsx
3859+
import { mfa } from "@auth0/nextjs-auth0/client";
3860+
3861+
// Usage in client component
3862+
await mfa.verify({ mfaToken, otp });
3863+
```
3864+
3865+
### Getting Authenticators
3866+
3867+
List all enrolled authenticators for the current user:
3868+
3869+
```ts
3870+
const authenticators = await auth0.mfa.getAuthenticators({ mfaToken });
3871+
```
3872+
3873+
### Enrollment
3874+
3875+
Enroll new authenticators for MFA. Support includes OTP (TOTP apps), SMS, Email, and Push Notification.
3876+
3877+
**OTP (Authenticator App)**
3878+
3879+
```ts
3880+
// Returns secret, barcodeUri for QR code
3881+
const enrollment = await auth0.mfa.enroll({
3882+
mfaToken,
3883+
authenticatorTypes: ["otp"]
3884+
});
3885+
```
3886+
3887+
**SMS**
3888+
3889+
```ts
3890+
const enrollment = await auth0.mfa.enroll({
3891+
mfaToken,
3892+
authenticatorTypes: ["oob"],
3893+
oobChannels: ["sms"],
3894+
phoneNumber: "+15555555555"
3895+
});
3896+
```
3897+
3898+
**Email**
3899+
3900+
```ts
3901+
const enrollment = await auth0.mfa.enroll({
3902+
mfaToken,
3903+
authenticatorTypes: ["oob"],
3904+
oobChannels: ["email"],
3905+
3906+
});
3907+
```
3908+
3909+
**Push Notification**
3910+
3911+
```ts
3912+
const enrollment = await auth0.mfa.enroll({
3913+
mfaToken,
3914+
authenticatorTypes: ["oob"],
3915+
oobChannels: ["auth0"]
3916+
});
3917+
```
3918+
3919+
### Challenge
3920+
3921+
Initiate an MFA challenge for OOB authenticators (SMS/Email/Push). OTP authenticators do not require explicit challenge.
3922+
3923+
```ts
3924+
// Returns oobCode and bindingMethod
3925+
const challenge = await auth0.mfa.challenge({
3926+
mfaToken,
3927+
challengeType: "oob",
3928+
authenticatorId: "sms|..."
3929+
});
3930+
```
3931+
3932+
### Verify
3933+
3934+
Verify MFA with OTP code, OOB code, or recovery code.
3935+
3936+
**OTP Verification**
3937+
3938+
```ts
3939+
await auth0.mfa.verify({
3940+
mfaToken,
3941+
otp: "123456"
3942+
});
3943+
```
3944+
3945+
**OOB Verification (SMS/Email/Push)**
3946+
3947+
```ts
3948+
await auth0.mfa.verify({
3949+
mfaToken,
3950+
oobCode: challenge.oobCode,
3951+
bindingCode: "123456" // User input
3952+
});
3953+
```
3954+
3955+
**Recovery Code Verification**
3956+
3957+
```ts
3958+
await auth0.mfa.verify({
3959+
mfaToken,
3960+
recoveryCode: "ABCD-EFGH-IJKL-MNOP"
3961+
});
3962+
```
3963+
3964+
### Complete Flow Examples
3965+
3966+
For complete implementation guides and best practices, refer to the official Auth0 documentation:
3967+
3968+
- [Explore multi-factor authentication](https://auth0.com/docs/secure/multi-factor-authentication)
3969+
- [Customize Multi-Factor Authentication Pages](https://auth0.com/docs/brand-and-customize/universal-login-pages/customize-mfa-pages)
3970+
3971+
### MFA Tenant Configuration
3972+
3973+
The SDK relies on background token refreshes to maintain user sessions. For these non-interactive requests to succeed, configure your MFA policies to allow `refresh_token` exchanges without immediate user challenge.
3974+
3975+
> [!NOTE]
3976+
> Enforcing **"Always"** or **"All Applications"** in your global Tenant MFA Policy will block background token refreshes, as they cannot satisfy an interactive MFA challenge.
3977+
3978+
**Recommended Configuration:**
3979+
Set Tenant MFA Policy to **"Adaptive"** or **"Never"**.
3980+
3981+
**Example Action Code:**
3982+
```javascript
3983+
exports.onExecutePostLogin = async (event, api) => {
3984+
// Only trigger on refresh_token grant (step-up)
3985+
if (event.request?.body?.grant_type == "refresh_token") {
3986+
3987+
if (event.user.enrolledFactors.length) {
3988+
// User has factors enrolled - challenge
3989+
api.authentication.challengeWithAny([
3990+
{ type: 'otp' },
3991+
{ type: 'phone' },
3992+
{ type: 'push-notification' },
3993+
{ type: 'email' },
3994+
{ type: 'recovery-code' }
3995+
]);
3996+
} else {
3997+
// No factors enrolled - prompt enrollment
3998+
api.authentication.enrollWithAny([
3999+
{ type: 'otp'},
4000+
{ type: 'phone'},
4001+
{ type: 'push-notification' }
4002+
]);
4003+
}
4004+
}
4005+
};
4006+
```
4007+
4008+
### MFA Error Handling
4009+
4010+
The SDK provides typed error classes for all MFA operations:
4011+
4012+
| Error Class | Code | When Thrown | Example |
4013+
|-------------|------|-------------|---------|
4014+
| `MfaRequiredError` | `mfa_required` | Token refresh requires MFA step-up | Accessing protected API |
4015+
| `MfaGetAuthenticatorsError` | Various | Failed to list authenticators | Invalid/expired token |
4016+
| `MfaEnrollmentError` | Various | Enrollment failed | Unsupported factor type |
4017+
| `MfaDeleteAuthenticatorError` | Various | Delete failed | Authenticator not found |
4018+
| `MfaChallengeError` | Various | Challenge failed | Invalid authenticator ID |
4019+
| `MfaVerifyError` | `invalid_grant` | Verification failed | Invalid OTP code |
4020+
| `MfaTokenNotFoundError` | `mfa_token_not_found` | No MFA context for token | Token not in session |
4021+
| `MfaTokenExpiredError` | `mfa_token_expired` | Token TTL exceeded | Context expired |
4022+
| `MfaTokenInvalidError` | `mfa_token_invalid` | Token tampered or wrong secret | Decryption failed |
4023+
37614024
## Reactive MFA Step-Up (Popup)
37624025
37634026
### Overview

0 commit comments

Comments
 (0)