Skip to main content

Prerequisites

Installation

The Prove Platform Web SDK has an unpacked size of 324 KB, and a single dependency: @prove-identity/mobile-auth. Install the client-side SDK of your choice by running a command in your terminal, or by using a dependency management tool specific to your project.
# Run this command to install the package (ensure you have the latest version).
npm install @prove-identity/prove-auth@3.4.2
If you’re including the file from jsDelivr and using Content Security Policy headers, ensure you add https://cdn.jsdelivr.net/npm/@prove-identity/ to script-src, plus corresponding sha256-... or nonce-....

Find the type of flow: mobile or desktop

You can find if the customer is on a mobile or desktop browser using this example. If the isMobile is true, pass mobile to the Start() function on the server, otherwise you can pass desktop:
// Check if the customer is on a mobile or desktop browser.
const authCheck = new proveAuth.AuthenticatorBuilder().build();
let isMobile = authCheck.isMobileWeb()
In a mobile flow, the mobile phone validates the one-time password (OTP). In a desktop flow, Instant Link sends a text message to the mobile phone for verification. In the mobile flow, once the OTP validation completes, the AuthFinishStep function finishes. In the desktop flow, a WebSocket opens for 5 minutes on the desktop browser while waiting for the customer to select the link in the text message. Once clicked, the WebSocket closes and the AuthFinishStep function finishes.

Authenticate()

The SDK requires an authToken as a parameter for the Authenticate() function. This token returns from the Start() call of the server-side SDK. The token is session specific, limiting it to a single flow. It also expires after 15 minutes.

Retrieve authToken

Send a request to your back end server with the possession type, and an optional phone number if you are using the Prove possession check.
async function initialize(phoneNumber, possessionType) {
  const response = await fetch(backendUrl + "/initialize", {
    method: "POST",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      phoneNumber: phoneNumber,
      possessionType: possessionType,
    }),
  });

  const rsp = await response.json();
  const authToken = rsp.authToken;

  return authToken;
}

Setup authenticator

Once you have the authToken, build the authenticator for both the mobile and desktop flows.
Mobile Auth Implementations OnlyIf your app uses Content Security Policy headers, you must configure them to allow WebSocket connections to Prove’s authentication services:Sandbox Environment
  • https://device.uat.proveapis.com:4443
  • https://device.uat.proveapis.com
  • http://device.uat.proveapis.com:4443
  • http://device.uat.proveapis.com
Production Environment
  • https://device.proveapis.com:4443
  • https://device.proveapis.com
  • http://device.proveapis.com:4443
  • http://device.proveapis.com
  • https://auth.svcs.verizon.com:22790
Failure to configure these settings prevents Mobile Auth capability from working correctly in web flows.
const isMobileWeb = flowType.value === "mobile";
const isDesktop = flowType.value === "desktop";

if (isMobileWeb) {
  // Set up the authenticator for either mobile or desktop flow.
  let builder = new proveAuth.AuthenticatorBuilder();
  // Set up Mobile Auth and OTP.
  builder = builder
    .withAuthFinishStep(() => clientFinished())
    .withMobileAuthImplementation("fetch")
    .withOtpFallback(otpStart, otpFinish);
} else if (isDesktop){
  // Set up Instant Link.
  builder = builder
    .withAuthFinishStep(() => clientFinished())
    .withInstantLinkFallback(instantLink)
    .withRole("secondary");
} else {
  // Customer provided possession.
  builder = builder
    .withAuthFinishStep(() => clientFinished());
  authenticator.authenticate(authToken);
}

Validate the mobile phone

In the AuthFinishStep, you’ll specify a function to call once the possession checks complete on the mobile phone. This endpoint on your back end server calls the Unify-Status() function to validate the phone number. The AuthFinishStep then completes. If the user cancels, the server makes a call to the Unify-Status() function and returns success=false.
// Send a verify request.
async function verify() {
  const response = await fetch(backendUrl + "/verify", {
    method: "POST",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({}),
  });

  const results = await response.json();
  const rsp = JSON.stringify(results);

  return null;
}

Configure OTP

Use this section to configure SMS OTP fallback in the Web SDK: wire OtpStartStep and OtpFinishStep so the SDK can send the code, collect the PIN, and optionally support resend, OTP retry, or phone-number change.

Prerequisites

  • After Prove sends the SMS, the customer has about two minutes to enter the OTP before the session times out.
  • When building the authenticator, call withOtpFallback(startStep: OtpStartStep | OtpStartStepFn, finishStep: OtpFinishStep | OtpFinishStepFn) and implement both OtpStartStep and OtpFinishStep. Return the phone number from your start step as an object with a phoneNumber field passed to resolve(...); use reject('message') when collection fails. The Prove client SDK orchestrates when each step runs—do not duplicate that orchestration in app code (see Invalid OTP and step orchestration below).
Invalid OTP and step orchestrationWhen the customer enters an invalid OTP, the Prove client SDK detects it and may surface activity related to AuthFinishStep that looks unexpected. This behavior is expected.Do not add your own extra invocation of the OTP finish step to pass the error in otpError. The SDK runs your OtpFinishStep when retry or error UI is needed.Implement the required step functions, but let the Prove client SDK orchestrate when each step runs.

Configure the client

1

Implement start and finish for your use case

Open the tab that matches how the phone number is collected and which OTP options you need.
Use this path when the server already has the phone number (for example from POST /v3/start or your server Start wrapper) and the browser must not prompt for it again.Call resolve(null) (or the equivalent in your snippet) so the SDK knows the customer agreed to receive the SMS. Follow the sample for the exact resolve shape your SDK version expects.
function otpStartStep(phoneNumberNeeded, phoneValidationError) {
  return new Promise((resolve, reject) => {
    // Since no phone number is needed, don't prompt the user.
    resolve(null);
  });
}
Call reject('some error message') if something prevents sending the SMS or completing the flow (for example the customer cancels or leaves the UI with the back button).In the finish step, return the OTP through resolve(result: OtpFinishResult) with the OnSuccess result type and the value wrapped in OtpFinishInput, as in the snippet below.
function otpFinishStep(otpError) {
  return new Promise((resolve, reject) => {
    // If error message is found, handle it.
    if (otpError) {
      // Set to a variable and display it in a field.
      // In this example, we don't do anything with the error.
      var someErrorMessage = otpError.message;
    }

    // Prompt the user for whether they received the SMS.
    // Typically, this is a page that shows the OTP already. We are simplifying
    // it by requiring an input.
    var input = confirm('Did you receive a text message?');
    if (!input) {
      // Close the modal if a text message was not received.
      return;
    }

    // Prompt the user for the OTP.
    var otp = prompt('Enter OTP code:');
    if (otp) {
      // If the input is valid and the user clicked `OK`, return the OTP.
      resolve({
        input: { otp }, // OTP value
        resultType: 0, // OnSuccess enum type = 0
      });
    } else {
      // Else, exit the flow.
      reject('phone invalid or user cancelled');
    }
  });
}
2

Verify the integration

In Sandbox, walk each shipped path (default, prompt, resend, retry if enabled, phone change if enabled). Confirm SMS delivery, OTP entry within the timeout, and that you never stack extra OtpFinishStep invocations on top of the SDK’s invalid-OTP handling—the SDK should remain the single orchestrator for retries and errors.
Use this section to configure the Web SDK so Instant Link SMS can be sent from the browser flow and optional resend or phone-number change behaves as expected.
Instant Link for mobile web isn’t supported.
Custom or vanity Instant Links aren’t supported. You can’t substitute a custom link for the default Instant Link.

Prerequisites

  • Integrate on desktop (or other supported) web; see the callout above for mobile web.
When building the authenticator, use withInstantLinkFallback(startStep: InstantLinkStartStep | InstantLinkStartStepFn, retryStep?: InstantLinkRetryStep | InstantLinkRetryStepFn). Implement InstantLinkStartStep in every flow. Add InstantLinkRetryStep only if you support Resend or Phone Number Change (see those tabs). Return the phone number from your step as an object with a phoneNumber field passed to resolve(...); use reject('message') when collection fails.

Configure the client

1

Implement the Instant Link start and optional retry

Open the tab that matches how the phone number is collected and sent to Prove.
Use this path when the server already has the phone number (for example from POST /v3/start or your server Start wrapper) and the browser must not prompt again.Call resolve(null) (or the equivalent in your snippet) so the SDK knows the customer agreed to receive the SMS. Follow the sample for the exact resolve shape your SDK version expects.
function instantLinkStartStep(phoneNumberNeeded, phoneValidationError) {
  return new Promise((resolve, reject) => {
    // Since no phone number is needed, don't prompt the user.
    resolve(null);
  });
}
2

Verify the integration

In Sandbox, run through each path you ship (default, prompt, and any retry flows). Confirm the SMS sends, the customer can complete the link within the timeout window, and resolve / reject match the UX you expect when the customer cancels or retries.

Prove Key validity and expiration

The Prove Key does not expire on a fixed calendar date. Prove may deactivate the key on our servers after 12 months of device inactivity; each new authentication resets that period. On iOS, the Prove Key remains on the device after uninstall and reinstall. Device Context is available for the Web SDK only—not the native Android SDK. To force a full possession check, pass rebind on /v3/unify. See Unified Authentication Overview for the full description.

Prove Key persistence enhancement

Browser privacy policies can affect Prove Key persistence by deleting script-writable data (localStorage and IndexedDB). To recover device registration when the Prove Key is lost, enable the Device Context feature.
Contact Prove to enable this add-on feature and receive your public API keys.

Installation

Install the device context module:
NPM
npm install @prove-identity/prove-auth-device-context

Activation

Activate the module in your app:
import * as dcMod from "@prove-identity/prove-auth-device-context";
dcMod.activate();
If you’re using Content Security Policy headers, ensure you allow access to the following common resources:
  • script-src https://fpnpmcdn.net https://*.prove-auth.proveapis.com,
  • connect-src https://api.fpjs.io https://*.api.fpjs.io https://*.prove-auth.proveapis.com
  • worker-src blob:
Additionally, f you’re loading the file from jsDelivr, add https://cdn.jsdelivr.net/npm/@prove-identity/ to script-src, plus corresponding sha256-... or nonce-....

Configure authenticator with device context

Add withDeviceContext() to your authenticator builder:
// Public API Key provided by Prove for your environment
const publicApiKey = "apiKeyAssignedForThisBuildConfig";
const buildConfig = BuildConfig.US_UAT; // or BuildConfig.US_PROD, BuildConfig.EU_UAT, etc.
const options = {
  publicApiKey: publicApiKey,
  buildConfig: buildConfig,
};

let builder = new proveAuth.AuthenticatorBuilder();
builder = builder
  .withAuthFinishStep((input) => verify(input.authId))
  .withMobileAuthImplementation("fetch")
  .withOtpFallback(otpStart, otpFinish)
  .withDeviceContext(options);

const authenticator = builder.build();
Call builder.build() after the web app loads to enable early signal collection and reduce authentication latency.

Enable cookies for auth requests

Ensure cookies are enabled when making AuthStart and AuthFinish calls:
axios.post(backendUrl + '/authStart', data, { withCredentials: true });
axios.post(backendUrl + '/authFinish', data, { withCredentials: true });