Skip to main content
Possession requires both a client-side SDK (Web, iOS, or Android) and these platform APIs:

Prerequisites

  • Access token — Obtain a bearer token using Prove OAuth (Authentication). Use the same token for POST /v3/unify, POST /v3/unify-status, and POST /v3/unify-bind.
  • Server — Use a Prove server SDK or call those endpoints directly. Use the reference pages for full request bodies, optional fields, and responses.
  • Client SDK — Install the Web, Android, or iOS SDK for possession checks and the Prove Key. For the browser flow, see Identity Web SDK.

How to implement

This authentication type only applies to mobile channels.
1

Initialize the Flow

Send a request to your back end server with the phone number and possessionType=none to start the flow. See POST /v3/unify for optional fields (for example rebind, deviceId, proveId) and the full response.
// Send the Unify request.
rspUnify, err := client.V3.V3UnifyRequest(ctx, &components.V3UnifyRequest{
  PhoneNumber:    "2001004014",
  PossessionType: "none",
})
if err != nil {
  t.Fatal(err)
}
Return the authToken to the client for Authenticate(). Persist correlationId for UnifyStatus(). See POST /v3/unify for all response fields, JWT behavior, and session timing.
2

Authenticate

Initialize the client-side SDK to place a Prove Key on the device or to check whether a Prove Key is bound.
async function authenticate(isMobileWeb, authToken) {
  // Set up the authenticator for the mobile flow.
  let builder = new proveAuth.AuthenticatorBuilder();

  builder = builder
    .withAuthFinishStep((input) => verify(input.authId));
  
  const authenticator = builder.build();

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

Verify Mobile Number

In the AuthFinishStep of the client SDK, have the function make a call to an endpoint on your back end server. Your backend server should then call 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)
}
Use success (for example possession_required) to decide whether to run the possession step and POST /v3/unify-bind. See POST /v3/unify-status for the full response schema. Interpret evaluation using the Global Fraud Policy.
4

Perform Possession Check

Your app must perform a customer-supplied possession check such as SMS OTP. Only proceed to the next step if the possession check passes.
5

Call the Bind Endpoint

Call UnifyBind() after UnifyStatus() returns success=possession_required. Call this endpoint if and only if the possession check has passed. This binds the phone number to the Prove Key for future authentications.This function requires correlationId and phoneNumber. See the /v3/unify-bind reference for the full schema. You can also send optional fields such as clientRequestId for session tracking.
rspUnifyBind, err := client.V3.V3UnifyBindRequest(context.TODO(), &components.V3UnifyBindRequest{
  CorrelationID: rspUnify.V3UnifyResponse.CorrelationID,
  PhoneNumber:   "2001004018",
})
if err != nil {
  return fmt.Errorf("error on UnifyBind(): %w", err)
}
Return the binding outcome to the client. See POST /v3/unify-bind for all response fields. Interpret evaluation using the Global Fraud Policy.

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
9101Phone number doesn’t match Prove Key. Rebind required.

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

For 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.
/v3/unify accepts a correctly formatted phone number as valid regardless of landline or mobile. If SMS or Mobile Auth cannot finish the possession step, expect the issue to surface on /v3/unify-status as success=false or success=possession_required, depending on the flow.