Skip to main content

Prerequisites

  • Server integration — Your backend must support the flows this SDK expects—for example issuing an authToken from your server SDK’s start/initialize call, plus HTTP endpoints your app invokes from finish steps (such as validate, verify, or complete). Use your product’s implementation guide together with this page.
  • Prove credentials — Sandbox or Production access from the Prove Portal, configured for your application.
  • Phone-based flow — A customer phone number where your flow requires it. For Mobile Auth, end users may need to disable VPN or Private Relay (see per-platform warnings below).

Installation

The Android SDK is a set of lightweight libraries. The libraries deliver as Android Archive Repository, .aar, files. The minimum supported version of Android is v7, level 24.Prove manages a maven repository with Android binaries to enable integration with Gradle.Update the dependencies object in the build.gradle file:
dependencies {
    // Existing dependencies are here.

    // Add the Prove Link dependencies:
    implementation 'com.prove.sdk:proveauth:6.10.7'
}
Point to the repository by updating your settings.gradle file with the Maven repository:
dependencyResolutionManagement {
    // Existing repository settings are here.

    repositories {
        // Existing repositories are here.

        // Add the Prove Link Maven repository:
        maven {
            url = "https://prove.jfrog.io/artifactory/libs-public-maven/"
        }
    }
}
The following needs added to the build.gradle file to also download dependency libraries:
dependencies {
    implementation fileTree('libs')
}
If you receive an error message on the application@fullBackupContent value, you can resolve it by adding this line of code to your application AndroidManifest.xml file inside the <application>...</application> node. Add it as an attribute to the opening application tag:
<application
...
tools:replace="android:fullBackupContent"
...>
</application>

Permissions

The Prove Auth SDK and its children SDKs merge the following permissions into the main app:
<!-- Required to perform authentication -->
<uses-permission android:name="android.permission.INTERNET" />

<!-- Required to access information about networks -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- Required for ConnectivityManager.requestNetwork -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

Send the type of flow: mobile

Unlike the Web SDK, when using the Android SDK, use the mobile flow. Pass mobile to the Start() function on the server. In a mobile flow, Mobile Auth℠ executes first and if that fails, performs OTP validation on the mobile phone.In the mobile flow, once either Mobile Auth or the OTP validation is complete, the AuthFinishStep function executes.
Mobile AuthMobile Auth requires the customer to disable any VPN.

Authenticate()

The SDK requires an authToken as a parameter for the Authenticate() function. This token returns from the Start() call of the server 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 backend server with the phone number, flow type, and an optional challenge of either the date of birth or social security number.
String initialize(String phoneNumber, String ssn, String flowType) {
    YourBackendClient backend = new YourBackendClient(); // Backend API client

    // TODO: Build your InitializeRequest object
    InitializeRequest initializeRequest = new InitializeRequest(phoneNumber, ssn, flowType);

    // Send an initialize request to your backend server to get authToken
    InitializeResponse response = backend.initialize(initializeRequest);

    // TODO: define your own InitializeResponse object to parse authToken string
    return response.getAuthToken();
}

Setup authenticator

Once you have the authToken, build the authenticator for the mobile flow.
// Object implementing AuthFinishStep interface
AuthFinishStep authFinishStep = new AuthFinishStep() {
    ...
};

// Objects implementing OtpStartStep/OtpFinishStep interfaces
OtpStartStep otpStartStep = new OtpStartStep() {
    ...
};

OtpFinishStep otpFinishStep = new OtpFinishStep() {
    ...
};

ProveAuth proveAuth = ProveAuth.builder()
    .withAuthFinishStep(authId -> verify(authId)) // verify(authId) call defined in #Validate the Mobile Phone section
    .withOtpFallback(otpStartStep, otpFinishStep)
    .withContext(this)
    .build();
The mobile data connection can sometimes be unavailable during testing. The Builder class offers a withTestMode(boolean testMode) method, which permits simulated successful session results while connected to a Wi-Fi network only. Testing using a Wi-Fi connection is useful in the Sandbox environment.
ProveAuth proveAuth = ProveAuth.builder()
    .withAuthFinishStep(authId -> verify(authId))
    .withOtpFallback(otpStartStep, otpFinishStep)
    .withContext(this)
    .withTestMode(true) // Test mode flag
    .build();

Performing the authentication

The ProveAuth object is thread safe. You can use it as a singleton. Most Prove Auth methods are blocking and therefore can’t execute in the main app thread. The app employs an executor service with a minimum of two threads to manage threads due to the ability to process concurrent blocking requests.
public class MyAuthenticator {
    private final MyBackendClient backend = new MyBackendClient(); // Backend API client
    private ExecutorService executor = Executors.newCachedThreadPool();
    private final AuthFinishStep authFinishStep = new AuthFinishStep() {
        @Override
        void execute(String authId) {
            try {
                AuthFinishResponse response = backend.authFinish("My App", authId);
                ... // Check the authentication status returned in the response
            } catch (IOException e) {
                String failureCause = e.getCause() != null ? e.getCause().getMessage() : "Failed to request authentication results";
                // Authentication failed due to request failure
            }
        }
    };

    private ProveAuth proveAuth;

    public MyAuthenticator(Context context) {
        proveAuth = ProveAuth.builder()
            .withAuthFinishStep(authFinishStep)
                .withOtpFallback(otpStartStep, otpFinishStep)
            .withContext(context)
            .build();
    }

    public void authenticate() throws IOException, ProveAuthException {
        AuthStartResponse response = backend.authStart("My Prove Auth App");

        proveAuth.authenticate(response.getAuthToken());
    }
}

public void authenticate() throws IOException, ProveAuthException {
        // NOTE: blocking method proveAuth.authenticate() should be run in background thread
        executor.submit(() -> {
            AuthStartResponse response = backend.authStart("My Prove Auth App");
            proveAuth.authenticate(response.getAuthToken());
        }
}

Validate the mobile phone

In the AuthFinishStep, specify a function to call once the possession checks are complete on the mobile phone. This endpoint on your back end server calls the Validate() function to check phone number validation. If it was successful, the server returns the results from the Challenge() function, including customer information.
// Send a verify request to get return customer information.
void verify(String: authId) {
    YourBackendClient backend = new YourBackendClient(); // Backend API client

    // Build your VerifyRequest object
    VerifyRequest verifyRequest = new VerifyRequest(authId, ...);

    // Send a verify request to your backend server to get return customer information.
    VerifyResponse response = backend.verify(verifyRequest);

    // TODO: define your VerifyResponse object to parse customer information from the response
    String firstName = response.getFirstName();
    String lastName = response.getLastName();

    // Pre-fill customer information to your Android App UI, for example:
    firstNameEditText.setText(firstName);
    lastNameEditText.setText(lastName);
}

Configure OTP

Use this section to configure SMS OTP fallback on Android: 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(otpStart: OtpStartStep, otpFinish: OtpFinishStep) and implement both OtpStartStep and OtpFinishStep. The Prove client SDK orchestrates when each step runs—implement the interfaces, but 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. Typical signs include a validation or reported error such as code 10001 with a message that the PIN doesn’t match. You may also see flow activity related to AuthFinishStep, such as ProveAuth.builder().withAuthFinishStep(…), that looks like an unexpected redirect.This behavior is expected. Do not add your own follow-up call to OtpFinishStep.execute to pass the error in otpException. The SDK invokes OtpFinishStep.execute when a retry or error UI is needed.Your app should implement the required step interfaces, but the Prove client SDK orchestrates when each step runs. Don’t duplicate that orchestration in application code.

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 client must not prompt for it again.Call OtpStartStepCallback.onSuccess(OtpStartInput) with an OtpStartInput instance that reflects “number already known”—typically an empty string or null for the phone value, as in the snippet—so the SDK knows the customer agreed to receive the SMS.
Java
import com.prove.sdk.proveauth.OtpStartInput;
import com.prove.sdk.proveauth.OtpStartStep;
import com.prove.sdk.proveauth.OtpStartStepCallback;
import com.prove.sdk.proveauth.ProveAuthException;

public class NoPromptStart implements OtpStartStep {
    @Override
    public void execute(boolean phoneNumberNeeded, ProveAuthException otpException,
            OtpStartStepCallback callback) {
        // No phone number needed, no need to ask end user for input.
        callback.onSuccess(new OtpStartInput(""));
    }

}
Call OtpStartStepCallback.onError() if something prevents sending the SMS (for example the customer cancels or leaves the flow with the back button).In the finish step, call OtpFinishStepCallback.onSuccess(OtpFinishInput) with the OTP the customer entered, wrapped in OtpFinishInput.
Java
import com.prove.sdk.proveauth.OtpFinishInput;
import com.prove.sdk.proveauth.OtpFinishStep;
import com.prove.sdk.proveauth.OtpFinishStepCallback;
import com.prove.sdk.proveauth.OtpValidationException;
import com.prove.sdk.proveauth.ProveAuthException;

public class NoPromptFinish implements OtpFinishStep {
    @Override
    public void execute(@Nullable ProveAuthException otpException,
            OtpFinishStepCallback otpFinishStepCallback) {
        // If error message is found, handle it.
        if (otpException instanceof OtpValidationException) {
            // Set to a variable and display it in a field.
            // In this example, we don't do anything with the error.
            String errorMsg = otpException.getMessage();
        }

        try {
            // Prompt the user for OTP delivered by SMS. You can build UI to provide
            // best UX based on your application and business logic, here we simplify to a
            // generic function named promptForOtpCode which gives us the OTP code.
            String otpCode = promptForOtpCode();
            otpFinishStepCallback.onSuccess(new OtpFinishInput(otpCode));
        } catch (Exception e) {
            // if any issue with the OTP collection from the end user or the user wants to cancel
            // then call onError to exit the flow. In this example we simplify it as catching
            // an exception.
            otpFinishStepCallback.onError();
        }
    }

}
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 manually chain OtpFinishStep.execute on top of the SDK’s invalid-OTP handling—the SDK should remain the single orchestrator for retries and errors.

Verify the Customer Information

Once the customer has made any edits to their pre-fill information, you should submit that information to the backend server so the Complete() call can then verify the customer information.
// Send request to the backend to verify customer information.
SendInfoResponse sendInfo(String firstName, String lastName) {
    YourBackendClient backend = new YourBackendClient(); // Backend API client

    // TODO: Build your SendInfoRequest object
    SendInfoRequest sendInfoRequest = new SendInfoRequest(firstName, lastName, ...);

    // Send a sendInfoRequest to your backend server to get return customer information.
    SendInfoResponse response = backend.verify(sendInfoRequest);

    // TODO: define your own SendInfoResponse object to parse the response
    return response;
}