Integrating with the account verification feature

This page explains how to integrate with the account verification feature.

Account verification is a feature that allows you to verify that your users own the email address or phone number that is associated with their account. It can help protect your users against credential stuffing attacks. This feature allows you to send a verification code by email and SMS and provides an input screen to validate the user's response. You can retrieve the verification results on the risk assessment.

The integration of the account verification feature is done in a few steps:

  1. Instrument the critical flow (login, signup, etc.) on the client, before requesting the assessment.
  2. Request and interpret the account verification information in the assessment.
  3. Trigger an account verification challenge on the client.
  4. Request a new assessment to make sure that the user's email address or phone number was successfully verified.

Before you begin

The account verification feature is allowlist-only for now. Please reach out to our sales team to onboard your site to this feature.

Make sure to complete the steps in the Quickstart to gain access to the API. Depending on the platforms for which you want to enable account verification, you will also need to follow the client-specific integration guides:

Instrumenting the critical flow on the client

This section explains how to pass the necessary information to reCAPTCHA Enterprise for use in the risk assessment.

On Android

Add the username to the RecaptchaAction which will be used in execute calls. This can be done as follows:

Bundle bundle = new Bundle();
bundle.putString("username", "foo@bar.com");
RecaptchaAction action =
  new RecaptchaAction(
    new RecaptchaActionType(RecaptchaActionType.LOGIN), bundle));

On iOS

You will need to provide the username argument. For example:

recaptchaClient.execute(
   RecaptchaAction(
      action: .login,
      extraParameters: ["username": "foo@bar.com"])
).then { token in
   // Do something with the token
}.catch { error in
   // Act on the error.
}

On Web

You will need to append an additional username parameter to your execute call, for example:

grecaptcha.enterprise.execute({
  action: 'login',
  username: 'foo@bar.com'
}).then(token => {
  /// Handle the generated token.
});

Note that execute returns a promise that is resolved upon token generation.

Requesting an assessment

Regardless of the platform that created the token, you can follow the instructions to create an assessment using that token.

You must supply the username and the endpoint to verify in the Assessment. You can provide multiple endpoints, for example an email address and a phone number:

{
  "event": {
    "token": "token",
    "siteKey": "key"
  },
  "accountVerification": {
    "username": "foo@bar.com",
    "endpoints: [{
      "emailAddress": "foo@bar.com",
    },
    {
      "phoneNumber": "+11111111111",
    }]
  }
}

If the integration with the feature is successful, the assessment should contain more information related to account verification specifically. For example:

{
  [...],
  "accountVerification": {
    "username": "foo@bar.com",
    "endpoints: [{
      "emailAddress": "foo@bar.com",
      "requestToken": "tplIUFvvJUIpLaOH0hIVj2H71t5Z9mDK2RhB1SAGSIUOgOIsBv",
      "lastVerificationTime": "",
    },
    {
      "phoneNumber": "+11111111111",
      "requestToken": "fwdgk0kcg1W0mbpetYlgTZKyrp4IHKzjgRkb6vLNZeBQhWdR3a",
      "lastVerificationTime": "",
    }],
    "latestVerificationResult": "RESULT_UNSPECIFIED"
  }
}

The assessment will contain the date and time of the latest successful verification for the given endpoints on the device that issued the token, if any. It will also contain one requestToken field per endpoint, which contains an opaque blob that you will need to send back to the client, if you decide to trigger an account verification challenge for that endpoint.

Triggering an account verification challenge on the client

If you have have decided to challenge the user based on the information contained in the assessment, then you must send the account verification request token for the endpoint you want to verify from the assessment back to the client. This request token will be needed to trigger the account verification challenge.

On Android

The account verification challenge is sent with a call to challengeAccount from an Context in your app.

Recaptcha.getClient(this)
   .challengeAccount(recaptchaHandle, requestToken)
   .addOnSuccessListener(
       this,
       new OnSuccessListener<VerificationHandle>() {
         @Override
         public void onSuccess(VerificationHandle handle) {
           VerificationHandle verificationHandle = handle;
           // Handle success ...
         }
       })
   .addOnFailureListener(
       this,
       new OnFailureListener() {
         @Override
         public void onFailure(@NonNull Exception e) {
           if (e instanceof ApiException) {
              ApiException apiException = (ApiException) e;
              Status apiErrorStatus = apiException.getStatusCode();
              // Handle api errors ...
           } else {
              // Handle other failures ...
           }

         }
       });

Once you obtain the PIN from the user, you must call verifyAccount from an Activity in your app to verify that the entered PIN was correct.

Recaptcha.getClient(this)
   .verifyAccount("userProvidedPIN", recaptchaHandle)
   .addOnSuccessListener(
       this,
       new OnSuccessListener<VerificationResult>() {
         @Override
         public void onSuccess(VerificationResult result) {
           if (result.getVerificationStatus().isSuccess()) {
             String recaptchaToken = result.recaptchaToken().orNull()
             // Handle success ...
           } else {
             VerificationHandle verificationHandle =
                              result.verificationHandle().orNull();
             Status errorStatus = result.getVerificationStatus();
             // Handle retries ...
           }
         }
       })
   .addOnFailureListener(
       this,
       new OnFailureListener() {
         @Override
         public void onFailure(@NonNull Exception e) {
           if (e instanceof ApiException) {
              ApiException apiException = (ApiException) e;
              Status apiErrorStatus = apiException.getStatusCode();
              // Handle api errors ...
           } else {
              // Handle other failures ...
           }
         }
       });

On iOS

The challenge is triggered with a call to challengeAccount.

recaptchaClient.challengeAccount(withRequestToken: "Request Token").then { verificationHandler in
  // Show your UI and retrieve the pin from the user.
}.catch { error in
  // Handle error.
}

Then once you get the PIN from the user you can use the verifyPin of the verificationHandler to finish the verification.

handler.verifyPin("pin") { recaptchaToken, recaptchaError in
  // Handle token/error.
}

On Web

The challenge is triggered with a single function call:

grecaptcha.enterprise.challengeAccount({
  'account-token': requestTokenFromCreateAssessment,
  'container': containerHTMLComponentID
}).then(newToken => {
  // Handle the new token.
});

where containerHTMLComponentID is the ID of an HTML component in which the verification challenge should be rendered. If you do not specify this parameter, then the challenge will be rendered in an overlay on top of the page.

The challengeAccount function returns a promise that is resolved once the challenge is completed, or rejected in case of error or timeout. Upon completion, the resolver is given a new generated token that contains updated information to be retrieved by requesting a new assessment.

Requesting a new assessment

You must request a new Assessment, once again including the username and endpoints fields.

Once the flow has been completed on the client, you should have received a new token that you can use to get the verdict of the verification you triggered. The assessment should contain a very recent timestamp regarding the latest successful verification, along with a success result status. For example, if you decided to verify an email endpoint:

{
  [...],
  "accountVerification": {
    "username": "foo@bar.com",
    "endpoints: [{
      "emailAddress": "foo@bar.com",
      "requestToken": "tplIUFvvJUIpLaOH0hIVj2H71t5Z9mDK2RhB1SAGSIUOgOIsBv",
      "lastVerificationTime": "2020-03-23 08:27:12 PST",
    }],
    "latestVerificationResult": "SUCCESS_USER_VERIFIED"
  }
}

The field latestVerificationResult can also show a different status, including:

  • ERROR_USER_NOT_VERIFIED if the user failed the verification challenge
  • ERROR_SITE_ONBOARDING_INCOMPLETE if your site is not properly onboarded to the feature
  • ERROR_CRITICAL_INTERNAL if the verification could not be completed due to an internal error in our systems.