/passwordless/start with a dedicated passwordless connection, you can consolidate onto your existing database connection instead. To use passwordless authentication with Universal Login, read Passwordless Authentication on Database Connections.
The Passwordless OTP grant isn’t available for single-page application (SPA) type applications. If your frontend is a single-page application, make the
/otp/challenge and /oauth/token calls from a back-end application that has the Passwordless OTP grant enabled.POST /otp/challenge— send a one-time code to the user’s email or phone.POST /oauth/token— exchange the code the user entered for tokens.
How it works
- User enters an email address or phone number in your application.
- Your application calls the
POST /otp/challengeendpoint. - The Auth0 Authorization Server sends a one-time code to the user’s email or phone.
- The Auth0 Authorization Server responds with an
auth_sessionvalue. Store this value; no other state is required. - User receives the code and enters it into your application’s UI.
- Your application calls the
POST /oauth/tokenendpoint with theauth_sessionand the user-entered code. - The Auth0 Authorization Server verifies the code against the
auth_sessionand responds with an ID token and access token (and optionally, a refresh token).
auth_session string returned in step 4. Auth0 determines whether the request is a login or a signup, and whether MFA is required — you don’t need to track any of that yourself. To learn more, read How Auth0 determines login vs. signup.
Before you start
- Configure
email_otpand/orphone_otpas authentication methods on your database connection. To learn more, read Passwordless Authentication on Database Connections. - Enable OTP verification for signups if you want users to sign up through the implicit signup flow. To learn more, read Passwordless Authentication on Database Connections.
- Enable the Passwordless OTP grant in Auth0 Dashboard or Management API. To learn more, read Update Grant Types.
- Confidential applications, such as back-end web applications, must send
client_secreton both calls. Public clients, such as native applications, do not. - For voice OTP, enable the Unified Phone Experience so voice can be used as a delivery channel.
Initiate the OTP challenge
Send the user’s identifier. Auth0 generates and delivers the code and returns an opaqueauth_session.
Parameters
The field name (
email vs. phone_number) tells Auth0 which channel to use. You don’t need to send a separate identifier type.
Response
/otp/challenge returns 200 OK whether or not the user exists. This prevents user enumeration. An attacker can’t use the endpoint to discover which identifiers have accounts. Treat auth_session as an opaque string: store it and pass it to the next call unchanged.
Exchange the code for tokens
When the user enters the code, submit it with theauth_session from the previous call.
Parameters
Response
Implicit signup
By default, Authentication API authenticates existing users only withallow_signup: false. You can pass allow_signup: true on POST /otp/challenge to let a successful OTP verification create the account when the user doesn’t yet exist, and signup is enabled on the connection.
allow_signup: false: Auth0 never creates a user. Unknown identifiers fail at token exchange.allow_signup: true: If the user doesn’t exist and the connection allows signup, the account is created when the OTP is verified and tokens are issued in the same step.
How Auth0 determines login vs. signup
Your application always makes the same two calls regardless of whether the user is new or returning. Auth0 resolves the intent at challenge time and records it server-side against theauth_session. At token exchange, Auth0 looks up the session and takes the correct action.
The blocked case returns the same error as a wrong OTP, by design, so the response never reveals whether an account exists.
Multi-factor authentication
If you require MFA,POST /oauth/token returns 403 with an mfa_required error:
mfa_token to call the MFA API to challenge and verify the additional factor. This matches the MFA behavior of all other Auth0 grant types.
Error responses
Both endpoints use the OAuth 2.0 error format based on RFC 6749: anerror code and a human-readable error_description. Parameter-validation failures (400) also include a validation_errors array identifying the specific fields.
POST /otp/challenge
POST /oauth/token
Rate limits
POST /otp/challenge is limited to 50 requests per hour per IP address, in addition to the global Authentication API rate limits. Exceeding the limit returns 429 Too Many Requests.
Rate-limited responses include these headers:
Limitations
- Single-page applications (SPAs) can’t use these endpoints directly because the Passwordless OTP grant can’t be enabled on SPA-type applications. Route the calls through a back-end application with the enabled grant.
- Confidential applications must send
client_secreton both calls. - Authentication API authenticates against database connections with email or phone OTP configured. It doesn’t replace
/passwordless/startfor dedicated email or SMS passwordless connections.