Skip to main content
Push authentication

A push authentication request displayed on a mobile device.

Push verification allows users to authenticate in a web browser by sending an authentication request to a mobile app. Push notifications are used to improve the UX by prompting users to open their app but they are not required for the method to work. The authentication mechanism is based on public key cryptography where private keys are securely stored on the user’s mobile device and are used to sign messages which can be verified with the public key. The Mobile SDK is used in push verification for two key steps:
  1. Enrolling a user for push verification by adding a credential in the mobile app. This step creates a new public/private key pair.
  2. Responding to an authentication challenge in the mobile app by approving or denying it. This step uses the mobile device’s private key to sign a message which is verified on the server using the public key.

Sequence diagram

The diagram below illustrates the sequence for a push verification challenge.

Portal setup

Enable the device credential authentication method for your tenant and configure a webhook for sending push notifications.

SDK setup

Server SDK

Initialize the SDK using your secret key from the API keys page and the API URL for your region.
import { Authsignal } from "@authsignal/node";

const authsignal = new Authsignal({
  apiSecretKey: "YOUR_SECRET_KEY",
  apiUrl: "YOUR_API_URL",
});

Web and Mobile SDKs

Initialize the Web SDK and Mobile SDK using your tenant ID from the API keys page and your API URL.
import { Authsignal } from "@authsignal/browser";

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

Enrollment

Scenario - Enroll users for push verification in your mobile app so it can be used later as a method for adaptive MFA.

1. Generate enrollment token

In your backend, track an action for a user (e.g. “addAuthenticator”) to generate a short-lived token.
const request = {
  userId: "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
  action: "addAuthenticator",
  attributes: {
    scope: "add:authenticators",
  },
};

const response = await authsignal.track(request);

const token = response.token;
This token will be used to authorize enrolling a new push authentication method on their mobile device. The add:authenticators scope is required to enroll a new authentication factor for an existing user. This scope should only be used when the user is in an already authenticated state. For more information on using scopes safely refer to our documentation on authenticator binding.

2. Add credential

Use the token obtained in step 1 to enroll a new device credential for the user in the mobile app.
await authsignal.device.addCredential(token: "eyJhbGciOiJ...")
For more information on when in your app to add credentials refer to our documentation on the enrollment lifecycle for app verification.

Adaptive MFA

Scenario - Strongly authenticate users in a web browser with push verification and use rules to decide when and where to trigger the authentication.

1. Track action

When a user performs an action that requires push verification, your backend should track an action (e.g. “signIn”) using our Server SDK.
  • Custom UI
  • Pre-built UI
const request = {
  userId: "dc58c6dc-a1fd-4a4f-8e2f-846636dd4833",
  action: "signIn",
};

const response = await authsignal.track(request);

if (response.state === "CHALLENGE_REQUIRED") {
  // Obtain token to present challenge
  const token = response.token;
}

2. Initiate challenge in browser

In the browser, use our Web SDK to initiate a push challenge. This will trigger a call to your webhook with the push event schema so that it can send the user a push notification.
  • Custom UI
  • Pre-built UI
// Set the token obtained from the track response
authsignal.setToken(token);

// Initiate the push challenge
const response = await authsignal.push.challenge();

// Obtain a challenge ID to poll for the result in the next step
const challengeId = response.data?.challengeId;
Then you can immediately start polling for the challenge result.
// Poll for the challenge result
const { data, error } = await authsignal.push.verify({ challengeId });

if (error || !data) {
  // Handle error
} else if (!data.isConsumed) {
  // The challenge has not yet been consumed
  // Continue polling
} else {
  // The challenge has been consumed
  // Stop polling and check if approved or rejected
  if (data.isVerified) {
    // Challenge has been approved
    // Obtain new token to send to backend to validate action
    const validationToken = data.token;
  } else {
    // Challenge has been rejected
  }
}

3. Check for pending challenge in mobile app

Use the mobile SDK’s Get Challenge method to check if there is a pending challenge for the device.
let response = await authsignal.device.getChallenge()

if let error = result.error {
    // The credential stored on the device is invalid
} else if let challenge = result.data {
    // A pending challenge request is available
    // Present the user with a prompt to approve or deny the request
    let challengeId = challenge.challengeId
} else {
    // No pending challenge request
}
This check should be done when launching or foregrounding the app - either from a push notification or when opened manually - as well as when the app receives a push notification while it is already foregrounded.

4. Present challenge in mobile app

If there is a pending challenge, present a dialog to allow the user to approve or reject the challenge. To approve or reject the challenge, use the mobile SDK’s Update Challenge method.
await authsignal.device.updateChallenge(
    challengeId: challengeId,
    approved: true
)

5. Complete authentication in browser

Once the challenge is approved, the polling request initiated in the web browser in step 2 will return a token that should be passed to your web browser app’s backend to validate the action in order to complete the authentication flow.
const response = await authsignal.validateChallenge({
  action: "signIn",
  token: "eyJhbGciOiJIUzI....",
});

if (response.state === "CHALLENGE_SUCCEEDED") {
  // User completed challenge successfully
}

Next steps

  • Adaptive MFA - Set up smart rules to trigger authentication based on risk
  • QR code - Implement QR code authentication
  • Trusted device - Implement trusted device authentication
  • Passkeys - Offer the most secure and user-friendly passwordless authentication
I