> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Step-up authentication

> The React SDK could pop step-up UI inside the widget. In the JavaScript SDK you run the same scope-based check yourself and pass requestedScopes on the verify call.

In the React SDK, `useStepUpAuthentication()` could render the challenge for you: `promptStepUpAuth()` auto-picked a verification method, showed Dynamic's built-in UI, and stored the scoped **elevated access token**. The JavaScript SDK keeps the same scope-based model and the same `checkStepUpAuth()` check — but there's no built-in UI, so you collect the credential yourself and pass `requestedScopes` on the verify call.

<Note>
  Step-up is **scope-based, not MFA**. You gate an action on a [`TokenScope`](/docs/javascript/building-ui/step-up-authentication#available-scopes) such as `wallet:sign`; any credential the user has — OTP, an authenticator app, a passkey, a recovery code, or a connected wallet — can satisfy it. MFA is just one such credential type. Migrating MFA enrollment itself is covered in [Multi-factor authentication](/docs/javascript/migrating-from-react/mfa).
</Note>

## What maps to what

| React SDK (`useStepUpAuthentication`)                                          | JavaScript SDK                                                                                                                          |
| ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `checkStepUpAuth({ scope })`                                                   | `checkStepUpAuth({ scope })` / `useCheckStepUpAuth()` (unchanged)                                                                       |
| `isStepUpRequired({ scope })`                                                  | read `isRequired` from `checkStepUpAuth({ scope })`                                                                                     |
| `promptStepUpAuth()` / `promptMfa()` / `promptReauthenticate()` (Dynamic's UI) | No built-in UI — [build it](/docs/javascript/building-ui/step-up-authentication), then call the verify function below with `requestedScopes` |
| `sendOtp()` / `verifyOtp()`                                                    | `sendEmailOTP()` / `sendSmsOTP()` + `verifyOTP({ …, requestedScopes })`                                                                 |
| `verifyTotpMfa()`                                                              | `authenticateTotpMfaDevice({ deviceId, code, requestedScopes })`                                                                        |
| `verifyPasskeyMfa()`                                                           | `authenticatePasskeyMFA({ requestedScopes })`                                                                                           |
| `verifyRecoveryCode()`                                                         | `authenticateMfaRecoveryCode({ code, requestedScopes })`                                                                                |
| `verifyWallet()`                                                               | `verifyWalletAccount({ walletAccount, requestedScopes })`                                                                               |
| `TokenScope` from `@dynamic-labs/sdk-api-core`                                 | `TokenScope` from `@dynamic-labs-sdk/client`                                                                                            |

## Gating a sensitive action (what the widget did for you)

Where you used to call `promptStepUpAuth()` and let the widget render the challenge, the shape is now yours to run — but it's the same three beats in any JavaScript SDK app, so the full build (every credential type, the scopes table, the connected-wallet and external-JWT paths) lives in [**Step-up authentication** (Building UI)](/docs/javascript/building-ui/step-up-authentication). The migration-specific parts:

* **Check the scope, not the UI.** Call `checkStepUpAuth({ scope })` right before the action and read `isRequired`. It defaults to `isRequired: true` if the check fails, so a network error never silently skips the challenge.
* **`requestedScopes` is what mints the elevated token.** Whatever verify call you run (`verifyOTP`, `authenticateTotpMfaDevice`, `verifyWalletAccount`, …), pass the scope in `requestedScopes`. Any credential the user has satisfies it — swap the verify call per the mapping table above.
* **The action takes no token.** After a successful verify, just perform the action — the SDK consumes the elevated token the verify call just minted; you don't thread a token through.

## See also

* [Step-up authentication](/docs/javascript/building-ui/step-up-authentication) — the full build with every credential type, the scopes table, and the external-JWT path
* [Multi-factor authentication](/docs/javascript/migrating-from-react/mfa) — enroll the devices a challenge can use
* [Transactions & balance](/docs/javascript/migrating-from-react/transactions-and-balance) — the signing action you gate
