nOTP (WhatsApp) Authentication with Client SDKs
This guide is meant for developers that are NOT using Descope Flows to design login screens and authentication methods.
If you would like to use Descope Flows, Quick Start should be your starting point.
nOTP allows users to log in via WhatsApp with just a single click, eliminating the need for codes, usernames, and typing. Unlike traditional OTP methods, nOTP doesn't require the company to connect to email servers or SMS providers, which can significantly reduce costs as it scales with the number of users.
To get started with authentication using nOTP (WhatsApp), refer to our nOTP Documentation. Continue reading to learn how to integrate nOTP authentication into your application using our Client SDKs.
The notp methods are exposed by the core Descope JavaScript SDK and are available through the Descope client SDKs: React, Next.js, Vue, Angular, WebJS, and plain HTML via the WebJS UMD bundle. The main differences are how you obtain the SDK instance, and that the Angular SDK wraps promise-returning SDK methods, including notp methods, as RxJS Observables, so Angular examples use .subscribe() instead of await.
Client SDK
For information on how to install and initialize the Descope Client SDK, please refer to the Client SDK Installation Guide.
User Sign-Up
To implement nOTP (WhatsApp) authentication, the first step is user sign-up using the nOTP (WhatsApp) authentication method. Use the signUp function to create a new user via WhatsApp. The Login ID should ideally be a phone number or can be left empty, in which case the phone number from WhatsApp will be used as the Login ID during verification. After calling the sign-up function, you will receive a response that includes a redirect URL or a QR code image. Present this to the user, who will then use WhatsApp to scan the QR code or follow the link to begin the authentication process.
import { useDescope } from '@descope/react-sdk';
// Args:
// loginId: phone - becomes the unique ID for the user from here on (or leave empty to use the WhatsApp phone number).
const loginId = "+15555555555"
// user: Optional user object to populate new user information.
const user = { "name": "Joe Person", "phone": "+15555555555", "email": "email@company.com"}
const descopeSdk = useDescope();
const resp = await descopeSdk.notp.signUp(loginId, user);
if (!resp.ok) {
console.log("Failed to initialize NOTP signup")
console.log("Status Code: " + resp.code)
console.log("Error Code: " + resp.error.errorCode)
console.log("Error Description: " + resp.error.errorDescription)
console.log("Error Message: " + resp.error.errorMessage)
}
else {
console.log("Successfully initialized NOTP signup.")
// resp.data contains { pendingRef, redirectUrl, image }
// Present the QR `image` or send the user to `redirectUrl` to complete auth
console.log(resp.data)
}User Sign-In
To sign in a user with nOTP (WhatsApp) authentication, use the signIn function with the nOTP (WhatsApp) authentication method. The Login ID should be a phone number or can be left empty. If left empty, the phone number from WhatsApp will be used as the login ID during the verification process. Upon calling the sign-in function, the response will include a redirect URL and/or a QR code image. Present this information to the user; they should scan the QR code or follow the link in WhatsApp to start the authentication flow.
import { useDescope } from '@descope/react-sdk';
// Args:
// loginId: phone - must be same as provided at the time of signup (or leave empty to use the WhatsApp phone number).
const loginId = "+15555555555"
// loginOptions (LoginOptions): this allows you to configure behavior during the authentication process.
const loginOptions = {
"stepup": false,
"mfa": false,
"customClaims": {"claim": "Value1"},
"templateOptions": {"option": "Value1"}
}
const descopeSdk = useDescope();
const resp = await descopeSdk.notp.signIn(loginId, loginOptions);
if (!resp.ok) {
console.log("Failed to initialize NOTP Sign-In")
console.log("Status Code: " + resp.code)
console.log("Error Code: " + resp.error.errorCode)
console.log("Error Description: " + resp.error.errorDescription)
console.log("Error Message: " + resp.error.errorMessage)
}
else {
console.log("Successfully initialized NOTP Sign-In.")
// resp.data contains { pendingRef, redirectUrl, image }
// Present the QR `image` or send the user to `redirectUrl` to complete sign-in
console.log(resp.data)
}User Sign-Up-or-In
Use the signUpOrIn function to authenticate a user with nOTP (WhatsApp). If the user does not exist, signUpOrIn will create a new user automatically. The Login ID should be a phone number or can be left empty. If left empty, the WhatsApp phone number will be used as the login ID during verification. After calling signUpOrIn, the response will contain a redirect URL and/or a QR code image. Present the QR code or URL to the user, who should scan the QR code or follow the link in WhatsApp to start the authentication flow.
import { useDescope } from '@descope/react-sdk';
// Args:
// loginId: phone - becomes the unique ID for the user from here on (or leave empty to use the WhatsApp phone number).
const loginId = "+15555555555"
// signUpOptions (SignUpOptions): this allows you to configure behavior during the authentication process.
const signUpOptions = {
"customClaims": {"claim": "Value1"},
"templateOptions": {"option": "Value1"}
}
const descopeSdk = useDescope();
const resp = await descopeSdk.notp.signUpOrIn(loginId, signUpOptions);
if (!resp.ok) {
console.log("Failed to initialize NOTP Sign-Up or Sign-In")
console.log("Status Code: " + resp.code)
console.log("Error Code: " + resp.error.errorCode)
console.log("Error Description: " + resp.error.errorDescription)
console.log("Error Message: " + resp.error.errorMessage)
}
else {
console.log("Successfully initialized NOTP Sign-Up or Sign-In.")
// resp.data contains { pendingRef, redirectUrl, image }
// Present the QR `image` or send the user to `redirectUrl` to complete authentication
console.log(resp.data)
}Get Session
To complete the WhatsApp nOTP flow, after the user completes verification in WhatsApp, retrieve their JWT by invoking the waitForSession function and passing in the pendingRef from your signIn / signUp / signUpOrIn call.
The function polls Descope until the user finishes verifying in WhatsApp, then returns the session and refresh tokens (and, with persistTokens enabled, persists them for you). By default, polling runs every 1 second and times out after 10 minutes.
import { useDescope } from '@descope/react-sdk';
// Args:
// pendingRef: the reference string returned from notp.signIn / signUp / signUpOrIn.
const pendingRef = resp.data.pendingRef
// config (optional WaitForSessionConfig): tune how long and how often to poll.
const config = {
"timeoutMs": 120000, // give up after 2 minutes (default applies if omitted)
"pollingIntervalMs": 1000 // poll once per second (default applies if omitted)
}
const descopeSdk = useDescope();
const sessionResp = await descopeSdk.notp.waitForSession(pendingRef, config);
if (!sessionResp.ok) {
// Note: a timeout does NOT throw - it resolves with ok: false, so check it here.
console.log("Failed to complete NOTP authentication")
console.log("Status Code: " + sessionResp.code)
console.log("Error Code: " + sessionResp.error.errorCode)
console.log("Error Description: " + sessionResp.error.errorDescription)
console.log("Error Message: " + sessionResp.error.errorMessage)
}
else {
console.log("Successfully authenticated via NOTP. " + JSON.stringify(sessionResp.data))
// sessionResp.data is a JWTResponse containing sessionJwt, refreshJwt, etc.
}Checkpoint
Your application is now integrated with Descope. Please test with sign-up or sign-in use case.