The Authsignal Web SDK can be used to:

  • Launch the pre-built UI to let users set up MFA and complete challenges
  • Sign up and sign in users using passkeys
  • Build custom UIs for authenticating with email OTP, SMS OTP, or authenticator app

Installation

This will add our module to your package.json.

Initialization

Initialize the client with your tenant ID and the base URL for your region.

import { Authsignal } from "@authsignal/browser";

const authsignal = new Authsignal({
  tenantId: "YOUR_TENANT_ID",
  baseUrl: "YOUR_REGION_BASE_URL",
});

You can find your tenantId in the Authsignal Portal.

You must specify the correct baseUrl for your tenant’s region.

RegionBase URL
US (Oregon)https://api.authsignal.com/v1
AU (Sydney)https://au.api.authsignal.com/v1
EU (Dublin)https://eu.api.authsignal.com/v1

Launching the pre-built UI

The Web SDK can be used to launch the pre-built UI.

authsignal.launch(url, options);

Parameters

url
string

The URL obtained on your server by tracking an action.

options
LaunchOptions Object

The options used when launching the pre-built UI.

Response

Promise<TokenPayload>

When mode is set as popup it returns a Promise<TokenPayload> that resolves when the popup closes.

token
string

The token that can be used to verify the outcome of the user action.

For more information on launching the pre-built UI see our detailed guide.

Passkeys

Creating a passkey

Creating a passkey must be authorized by presenting a challenge with an existing method or tracking an action to obtain a short-lived token.

const response = await authsignal.passkey.signUp({
  token: "eyJhbGciOiJ...",
  username: "jane@authsignal.com",
  displayName: "Jane Smith",
});

Parameters

token
string

A short-lived token obtained by tracking an action.

username
string

The primary user identifier associated with the passkey, e.g. the user’s email address.

displayName
string

An optional secondary user identifier which the browser may display in place of or alongside the username, e.g. the user’s full name.

Response

response
AuthsignalResponse<SignUpResponse>

Using a passkey

Calling signIn will present the passkey sign-in prompt. If the user successfully authenticates with their passkey, send the result token to your server to validate the challenge.

const response = await authsignal.passkey.signIn({ action: "signInWithPasskey" });

if (response.token) {
  // Send token to your server to validate the result
}

Passkeys represent a new paradigm when compared with traditional authentication methods. To learn more about how to create an optimal sign-in experience for users, refer to our documentation on best practices for passkeys in web browsers.

Parameters

action
string

A string which determines how the action associated with the passkey sign-in attempt will be named in the Authsignal Portal. Values are validated with the following regex: ^[a-zA-Z0-9_-]{(1, 64)}$.

Response

response
AuthsignalResponse<SignInResponse>

Using passkey autofill

This feature requires rendering a text input with the attribute autocomplete="username webauthn":

<input type="text" id="username" autocomplete="username webauthn" />

Then when the page loads you should initialize the input for passkey autofill by running the following code.

authsignal.passkey
  .signIn({
    action: "signInWithPasskeyAutofill",
    autofill: true,
  })
  .then((token) => {
    if (token) {
      // The user has focused your text input and authenticated with an existing passkey
      // Send the token to your server to validate the result of the challenge
    }
  });

Passkey error handling

When any of the underlying native browser WebAuthn APIs fail, the SDK will throw a WebAuthnError.

Most of these errors are benign and can be safely ignored. However, if you wish to handle them, you can do so by catching the error in a try/catch block.

Common errors you will encounter during passkey authentication are:

  • ERROR_CEREMONY_ABORTED - The user cancelled the passkey ceremony. We recommend ignoring this error as it’s a normal part of the user experience.
  • ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED - The user already has a passkey registered for this authenticator (exclusive to signUp). For example, the user is trying to create an iCloud Keychain passkey but already has one registered in iCloud Keychain.

During development, you may also encounter ERROR_INVALID_RP_ID which occurs when the relying party ID is invalid for the domain.

import { WebAuthnError } from "@authsignal/browser";

try {
  const response = await authsignal.passkey.signUp({
    token: "eyJhbGciOiJ...",
    username: "jane@authsignal.com",
    displayName: "Jane Smith",
  });
} catch (error) {
  if (error instanceof WebAuthnError) {
    if (error.code === "ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED") {
      // The user already has a passkey registered for this authenticator
      // You can choose to handle this however you see fit
    }
  }
}

Email OTP

All email OTP SDK methods require you to set a token first.

Enroll email

Start enrollment for a new email OTP authenticator by sending the user an email containing an OTP code.

This method is typically used when you’ve not yet verified the user’s email address.

const response = await authsignal.email.enroll({ email: "jane@authsignal.com" });

If you’ve already verified a user’s email address independently of Authsignal, you can alternatively use a Server SDK to enroll the user programmatically.

Parameters

email
string

The user’s email address.

Response

response
AuthsignalResponse<EnrollResponse>

Challenge email

Start re-authentication for an existing email OTP authenticator by sending the user an email containing an OTP code.

This method is typically used when you’ve already verified the user’s email address.

const response = await authsignal.email.challenge();

Response

response
AuthsignalResponse<ChallengeResponse>

Verify email

Finish enrolling or re-authenticating a new or existing email OTP authenticator by verifying the code submitted by the user.

const response = await authsignal.email.verify({ code: "123456" });

Parameters

code
string

The OTP code inputted by the user.

Response

response
AuthsignalResponse<VerifyResponse>
data
VerifyResponse

All email magic link SDK methods require you to set a token first.

Start enrollment for a new email magic link authenticator by sending the user an email containing a verification link.

This method is typically used when you’ve not yet verified the user’s email address.

const response = await authsignal.emailML.enroll({ email: "jane@authsignal.com" });

If you’ve already verified a user’s email address independently of Authsignal, you can alternatively use a Server SDK to enroll the user programmatically.

Parameters

email
string

The user’s email address.

Response

response
AuthsignalResponse<EnrollResponse>

Start re-authentication for an existing email magic link authenticator by sending the user an email containing a verification link.

This method is typically used when you’ve already verified the user’s email address.

const response = await authsignal.emailML.challenge();

Response

response
AuthsignalResponse<ChallengeResponse>

Check the verification status of an email magic link authenticator. When the user clicks a valid magic link, the promise will resolve.

const response = await authsignal.emailML.checkVerificationStatus();

Response

response
AuthsignalResponse<VerifyResponse>
data
VerifyResponse

SMS OTP

All SMS OTP SDK methods require you to set a token first.

Enroll SMS

Start enrollment for a new SMS OTP authenticator by sending the user an SMS containing an OTP code.

This method is typically used when you’ve not yet verified the user’s phone number.

const response = await authsignal.sms.enroll({ phoneNumber: ""+64271234567"" });

If you’ve already verified a user’s phone number independently of Authsignal, you can alternatively use a Server SDK to enroll the user programmatically.

Parameters

phoneNumber
string

The user’s phone number in E.164 format e.g. +14155552671.

Response

response
AuthsignalResponse<EnrollResponse>

Challenge SMS

Start re-authentication for an existing SMS authenticator by sending the user an SMS containing an OTP code.

This method is typically used when you’ve already verified the user’s phone number.

const response = await authsignal.sms.challenge();

Response

response
AuthsignalResponse<ChallengeResponse>

Verify SMS

Finish enrolling or re-authenticating a new or existing SMS OTP authenticator by verifying the code submitted by the user.

const response = await authsignal.sms.verify({ code: "123456" });

Parameters

code
string

The OTP code inputted by the user.

Response

response
AuthsignalResponse<VerifyResponse>
data
VerifyResponse

Authenticator app (TOTP)

All authenticator app SDK methods require you to set a token first.

Enroll TOTP

Start enrollment for a new TOTP authenticator by generating a QR code to display to the user.

const response = await authsignal.totp.enroll();

Response

response
AuthsignalResponse<EnrollTotpResponse>
data
EnrollTotpResponse

Verify TOTP

Finish enrolling or re-authenticating a TOTP authenticator by verifying the code submitted by the user.

const response = await authsignal.totp.verify({ code: "123456" });

Parameters

code
string

The OTP code inputted by the user.

Response

response
AuthsignalResponse<VerifyResponse>
data
VerifyResponse

Setting a token

When using web SDK methods for email OTP, SMS OTP or authenticator app (TOTP) you must first track an action using a Server SDK or the Server API to generate a time-limited token (valid for 10 minutes by default).

For enrollment flows, you must also specify the scope add:authenticators when tracking the action if the user already has an existing authenticator. For more detail refer to our guide on how to ensure a strong binding when adding authenticators.

Then you can use the SDK’s setToken method. You must use the same token for the initial enroll/challenge call and the subsequent verify call.

authsignal.setToken("eyJhbGciOiJ...");

// Send the user an email OTP code
// You can call this multiple times via a 'resend' button
await authsignal.email.challenge();

// Verify the inputted code matches the original code
const response = await authsignal.email.verify({ code: "123456" });

Extras

The SDK client exposes an anonymousId property which can be used as the deviceId when tracking an action.

authsignal.anonymousId;

Was this page helpful?