Skip to main content
The following endpoints apply to this flow:

Prerequisites

  • Server-side SDK installed for your platform or use the API endpoints directly if using a different back end language.
  • Authentication credentials from the Prove Portal configured in your environment.
  • Client-side SDK installed for your platform.

How to implement

To integrate Prove authentication, you must use the client-side SDK.
1

Determine Type of Flow

Decide if the customer is on a mobile or desktop browser using this example. If the isMobile is true, set mobile as the flowType for the Start() function on the server, otherwise you can set desktop:
// Check if the customer is on a mobile or desktop browser.
const authCheck = new proveAuth.AuthenticatorBuilder().build();
let isMobile = authCheck.isMobileWeb()
2

Initialize the Flow

Mobile Auth in the United States doesn’t require a phone number, but all other countries do.
Send a request to your back end server with the phone number and possession type to start the flow.Optional parameters:
  • finalTargetURL: required when flowType=desktop. This should be a URL you support. Once the customer clicks the Instant Link, redirect to this URL. It should instruct the customer to continue the workflow. Maximum length is 128 characters.
  • checkReputation: if true, Prove performs TrustScore verification.
  • clientHumanId: a client-generated unique ID to identify a specific customer across business lines.
  • clientRequestId: a client-generated unique ID for a specific session.
  • smsMessage: optional field to customize the message body sent in the Instant Link or OTP SMS message. Otherwise, you can use Prove defaults.
  • clientCustomerId: a client-generated unique ID for a specific customer. You can link calls related to the same customer, across different requests or sessions. The client defines the format of this ID.
  • deviceId: the unique identifier for the Prove Key on the device.
  • emailAddress: the email address of the customer.
  • ipAddress: the IP address of the customer.
  • proveId: a unique ID to identify a specific customer obtained from a earlier successful authentication.
  • allowOTPRetry: set to true to allow the customer to re-enter the OTP up to three times. Defaults to false.
// Send the Unify request.
rspUnify, err := client.V3.V3UnifyRequest(ctx, &components.V3UnifyRequest{
  PhoneNumber:    "2001004014",
  PossessionType: "mobile",
  ClientRequestID: provesdkservergo.String("client-abc-123"),
  AllowOTPRetry: true,
})
if err != nil {
  t.Fatal(err)
}
The function returns the following fields:
  • authToken: send this to your client-side code to pass into the Authenticate() function - it’s a short lived JSON Web Token (JWT) tied to the current flow and used for the possession checks.
  • correlationId: save this in your current session, then pass it in to the UnifyStatus() function call of the same flow. The correlation ID ties together different system calls for the same Prove flow. It also aids in troubleshooting. The session expires in 15 minutes from when the correlation ID returns from the Unify() call.
  • success: returns pending for this initial call.
Return the authToken in a response to the front end.
3

Authenticate

Once you have the authToken, build the authenticator for both the mobile and desktop flows.
For Android and iOS flows, you either must implement OTP or Instant Link - not both.
For desktop mode, Prove ignores the Prove Key and runs Instant Link.
async function authenticate(isMobileWeb, authToken) {
  // Set up the authenticator for either mobile or desktop flow.
  let builder = new proveAuth.AuthenticatorBuilder();

  if (isMobileWeb) {
    // Set up Mobile Auth and OTP.
    builder = builder
      .withAuthFinishStep((input) => verify(input.authId))
      .withMobileAuthImplementation("fetch")
      .withOtpFallback(otpStart, otpFinish);
  } else {
    // Set up Instant Link.
    builder = builder
      .withAuthFinishStep((input) => verify(input.authId))
      .withInstantLinkFallback(instantLink)
      .withRole("secondary");
  }

  const authenticator = builder.build();

  // Authenticate with the authToken.
  return authenticator.authenticate(authToken);
}

Configure OTP

To use the Resend/Retry/Phone Change features, install the Web SDK version 2.15.1 or later.
To set the One-Time Password (OTP) handler, withOtpFallback(startStep: OtpStartStep | OtpStartStepFn, finishStep: OtpFinishStep | OtpFinishStepFn), requires implementing the OtpStartStep and OtpFinishStep. When returning the phone number in the functions, ensure you return an object with the field phoneNumber to the resolve() function.The OTP session has a two minute timeout from when it’s sent through Short Message Service (SMS) to when the customer can enter in the OTP.
Follow these instructions if you are implementing OTP and you are passing in the phone number on the /v3/start endpoint.Since you passed the phone number in the Start() function, call resolve(null) to communicate to the SDK you have the customer’s agreement to deliver the SMS message. Ensure you return an object to resolve() function.
function otpStartStep(phoneNumberNeeded, phoneValidationError) {
  return new Promise((resolve, reject) => {
    // Since no phone number is needed, don't prompt the user.
    resolve(null);
  });
}
Call the reject('some error message') method to communicate to the SDK any issues while trying to obtain the phone number or the OTP. Report an error if the customer cancels the SMS transaction or presses the back button to leave the screen.In the finish step, call the resolve(result: OtpFinishResult) method to return the collected OTP value in which result variable has OnSuccess value for OtpFinishResultType and the OTP value wrapped in OtpFinishInput.
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');
    }
  });
}
In the desktop flow, a WebSocket opens for 3 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.
If you’re using Content Security Policy headers, ensure you allow wss: device.uat.proveapis.com and wss: device.proveapis.com.
4

Verify Mobile Number

In the AuthFinishStep, specify a function to call once the possession checks complete on the mobile phone. This endpoint on your back end server calls the UnifyStatus() function to validate the phone number. The AuthFinishStep then completes.
rspUnifyStatus, err := client.V3.V3UnifyStatusRequest(context.TODO(), &components.V3UnifyStatusRequest{
CorrelationID: rspUnify.V3UnifyResponse.CorrelationID,
})
if err != nil {
return fmt.Errorf("error on UnifyStatus(): %w", err)
}
If you’re using Content Security Policy headers, ensure you allow wss: device.uat.proveapis.com and wss: device.proveapis.com.
Prove Key persistence enhancementUsing Prove Key in web applications can be affected by strict browser privacy policies aimed at preventing cross-site tracking. For example, Safari completely disables third-party cookies and limits the lifetime of all script-writable website data. Prove Auth uses script-writable website data (localStorage and IndexedDB) for storing Prove Auth deviceId, crypto key material, and other critical metadata for subsequent device re-authentication.If the browser deletes this script-writable data, Prove Auth is no longer able to recognize the device and perform authentication. To mitigate this limitation and avoid repeating the device registration process, follow these steps to enable Device Context.
The device context feature is not enabled by default. Contact Prove to enable this add-on feature.
Web app setupFollow these steps to add Prove Key persistence in your web app:
1

Install the Device Context Module

Install the Device Context integration module and add activation code to your app:
NPM
npm install @prove-identity/prove-auth-device-context
Then activate it in your app:
import * as dcMod from "@prove-identity/prove-auth-device-context";
dcMod.activate();
2

Configure the Authenticator Builder

When configuring authenticatorBuilder for any flow, add the withDeviceContext() method to enable device context data collection:
// Prove supports integration within the US and EU regions for device context data collection
// The public API Key for each build config will be provided by Prove
const publicApiKey = "apiKeyAssignedForThisBuildConfig";
const buildConfig = BuildConfig.US_UAT;
const options = {
  publicApiKey: publicApiKey,
  buildConfig: buildConfig,
};

// Enable device context data with builder method
let builder = new proveAuth.AuthenticatorBuilder();
builder = builder
  .withAuthFinishStep((input) => verify(input.authId))
  .withMobileAuthImplementation("fetch")
  .withOtpFallback(otpStart, otpFinish)
  .withDeviceContext(options);

const authenticator = builder.build();
Call authenticatorBuilder.build() immediately after the web app loads. This enables the Web SDK to load components for device context collection and collect signals before authentication begins, which helps decrease latency.
3

Enable Cookies for Auth Requests

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

// Enable cookies for AuthFinish
axios.post(backendUrl + '/authFinish', data, { withCredentials: true });
Handling multiple device registrationsIf a user registers their device multiple times before using Device Context, Prove Auth may have multiple registration candidates matching the same visitor ID. To improve recovery accuracy:
  1. Store the deviceId returned from successful authentications in your backend (database or web cookie)
  2. Pass the stored deviceId with the /unify request to specify which registration to restore
// Send the Unify request with deviceId for registration recovery
rspUnify, err := client.V3.V3UnifyRequest(ctx, &components.V3UnifyRequest{
  PhoneNumber:    "2001004014",
  PossessionType: "mobile",
  DeviceId:       provesdkservergo.String("stored-device-id-from-previous-auth"),
})
The function returns the following fields:
  • success: either true if the mobile number validation was successful, or false if it failed.
  • phoneNumber: the phone number associated with the possession check.
  • clientHumanId: if provided in the request.
  • clientRequestId: if provided in the request.
  • deviceId: the unique identifier for the Prove Key on the device.
  • evaluation: the evaluation result for the Global Fraud Policy.
  • proveId: a unique ID to identify a specific customer obtained from a successful possession check.
You can then respond to the front end with the results of the authentication.
If you send a different phone number to /unify than the one registered to the Prove key, success=false returns when calling /unify-status. This is because the Prove Key is bound to a different number. Run the flow again with rebind=true in the /unify endpoint. This forces a full possession check and then, if valid, rebinds the Prove Key to the new phone number.

Error handling

If authentication was not successful, the evaluation field returned by UnifyStatus() has failure reasons explaining what went wrong according to the Global Fraud Policy.

Possession failure reasons

CodeDescription
9100Phone possession incomplete.
9101Phone number doesn’t match Prove Key. Rebind required.

Error code 9100 - Phone possession incomplete

For Prove Possession - Desktop and Prove Possession - Mobile, error code 9100 indicates that authentication was not successful.

Error code 9101 - Phone number doesn’t match Prove Key

For Prove Possession - Mobile and Customer-Supplied Possession, error code 9101 indicates that someone attempted authentication using a phone number that doesn’t match the phone number registered to the Prove Key. How to resolve: To rebind the Prove Key to the new phone number, restart the flow with rebind=true in the call to /unify:
rspUnify, err := client.V3.V3UnifyRequest(ctx, &components.V3UnifyRequest{
  PhoneNumber:    "2001004014",
  PossessionType: "mobile",
  Rebind:         provesdkservergo.Bool(true),
})
When you set rebind=true:
  1. Prove initiates a new authentication check.
  2. If the authentication is successful, the Prove Key is rebound to the new phone number passed into the request.
  3. Future authentications with this phone number succeed without requiring rebind.