Wallet SDK (Android)
Overview
The Wallet SDK for Android enables secure identity verification and transaction authorization during checkout. It is optimized for native Kotlin apps and leverages multi-factor authentication (MFA) with passkeys.
This SDK allows your wallet app to:
- Initiate an MFA session tied to a transaction.
- Guide users through passkey authentication, passkey creation, or fallback login.
- Streamline checkout flows directly within a native Android experience.
Use this SDK when building wallet apps that require frictionless and secure checkout with passkeys.
Requirements
- Android 9+ (API level 28+)
- Android Studio
- Kotlin
Prerequisites
- Create an application to obtain a base URL. The SDK uses this base URL to interact with the LoginID authentication service.
- Create an API key with at least the external:verify scope. You’ll need this to request authorization tokens from your backend.
Before installing the SDK, configure the association between your Android application and your website using a Digital Asset Links file.
Configure Digital Asset Links
Android uses a Digital Asset Links file named assetlinks.json to verify the association between your application and your website.
Find Your Package Name
You can find your application's package name in the app module's build.gradle.kts file under defaultConfig:
android {
defaultConfig {
applicationId = "<PACKAGE_NAME>"
}
}
Generate the SHA-256 Certificate Fingerprint
Use the keytool utility included with the Java Development Kit to retrieve the SHA-256 fingerprint of your application's signing certificate:
keytool -list -v \
-keystore KEYSTORE_PATH \
-alias KEYSTORE_ALIAS \
-storepass KEYSTORE_PASSWORD \
-keypass KEY_PASSWORD
Replace the following values:
KEYSTORE_PATHwith the path to your keystoreKEYSTORE_ALIASwith the signing-key aliasKEYSTORE_PASSWORDwith the keystore passwordKEY_PASSWORDwith the signing-key password
The command output includes the certificate's SHA-256 fingerprint.
For local development, you can use the default Android debug keystore with the following values:
KEYSTORE_ALIAS:androiddebugkeyKEYSTORE_PASSWORD:androidKEY_PASSWORD:android
Use a dedicated signing key for production applications. For applications distributed through Google Play, you can find the app-signing certificate fingerprint in the Google Play Console.
Register the Fingerprint
Register your application's SHA-256 certificate fingerprint in your LoginID application's FIDO2 section before continuing. For instructions, see Adding Android Fingerprint.
Host the assetlinks.json File
Create an assetlinks.json file containing your application's package name and SHA-256 certificate fingerprint:
[
{
"relation": [
"delegate_permission/common.get_login_creds"
],
"target": {
"namespace": "android_app",
"package_name": "<PACKAGE_NAME>",
"sha256_cert_fingerprints": [
"<SHA256_FINGERPRINT>"
]
}
}
]
Replace <PACKAGE_NAME> and <SHA256_FINGERPRINT> with your application's values.
Host the file at the following location:
https://<WEBSITE_DOMAIN>/.well-known/assetlinks.json
The file must be publicly accessible over HTTPS.
Declare the Association in Your Android Application
Add an asset_statements resource to res/values/strings.xml:
<resources>
<string name="asset_statements" translatable="false">
[{
\"include\": \"https://<WEBSITE_DOMAIN>/.well-known/assetlinks.json\"
}]
</string>
</resources>
Then add the corresponding <meta-data> element inside the <application> element of your AndroidManifest.xml file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<meta-data
android:name="asset_statements"
android:resource="@string/asset_statements" />
</application>
</manifest>
Set Up the SDK
Download the SDK
After creating your LoginID application, open the Android section of the Get Started guide and download the latest version of the SDK.
The SDK is distributed as Android Archive (.aar) files.
Add the SDK to Your Project
Copy the LoginID SDK artifacts into your app module's libs directory:
app/
└── libs/
├── api.jar
├── core-release.aar
└── mfa-release.aar
Add the SDK artifacts and required dependencies to your app module's build.gradle.kts:
dependencies {
// LoginID SDK
implementation(files("libs/api.jar"))
implementation(files("libs/core-release.aar"))
implementation(files("libs/mfa-release.aar"))
// Required dependencies
implementation("com.squareup.okhttp3:okhttp:5.1.0")
implementation("com.squareup.moshi:moshi:1.15.2")
implementation("com.squareup.moshi:moshi-adapters:1.15.2")
ksp("com.squareup.moshi:moshi-kotlin-codegen:1.15.2")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
implementation("androidx.credentials:credentials-play-services-auth:1.6.0")
implementation("androidx.security:security-crypto:1.1.0")
}
Initialize the SDK
- Kotlin
import com.loginid.core.models.LoginIDConfig
import com.loginid.mfa.LoginIDCheckoutMFA
class MyApplication : Application() {
val lid = LoginIDCheckoutMFA(<LOGINID_BASE_URL>)
override fun onCreate() {
super.onCreate()
// Additional setup...
}
}
Class LoginIDCheckoutMFA
A specialized authentication helper built on top of LoginID's MFA flow, designed for checkout scenarios where you need both authentication and identity trust.
This helps orchestrate the MFA flow tied to a transaction (e.g., confirming a purchase) using passkeys.
constructor
Initializes a new instance of the LoginIDCheckoutMFA.
class LoginIDCheckoutMFA
constructor(context: Context, baseUrl: String)
Creates a new wallet authentication helper using a base URL.
Use this initializer when you only have the environment base URL and want sensible defaults for the underlying SDK configuration.
| Parameter | Type | Required | Description |
|---|---|---|---|
| context | Context | Yes | The Android application context. |
| baseUrl | String | Yes | The LoginID environment base URL (e.g., from your environment configuration). |
LoginIDCheckoutMFA
constructor(config: LoginIDConfig)
Creates a new wallet authentication helper with an explicit LoginIDConfig.
Use this when you already have a fully-formed LoginIDConfig and want more control.
| Parameter | Type | Required | Description |
|---|---|---|---|
| config | LoginIDConfig | Yes | The complete configuration used to initialize the underlying LoginID SDK. |
| config.context | Context | Yes | The Android application context. |
| config.baseUrl | String | Yes | The base URL of the LoginID service. This value is used to resolve the App ID and make API calls. |
| config.appId | String | No | The application ID. If not provided, it will be extracted from the baseUrl. |
| config.useTrustId | Boolean | No | A flag to enable or disable the use of Trust ID. Defaults to false. |
LoginIDCheckoutMFA
beginFlow
beginFlow(txPayload: String, username: String, options: BeginFlowOptions?)
Begins the MFA authentication flow for a checkout session.
This starts an MFA session bound to a specific transaction payload and optional identifiers
such as merchant checkoutId.
beginFlow(txPayload: String, username: String, options: BeginFlowOptions?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| txPayload | String | Yes | The transaction payload to be confirmed/authorized. |
| username | String | No | The username of the user initiating MFA. Defaults to an empty string. |
| options | BeginFlowOptions? | No | Optional parameters for beginning the flow. If options.txPayload is provided, it takes precedence over the txPayload parameter. |
| options.displayName | String? | No | A human-palatable name for the user account, intended only for display on your passkeys and modals. |
| options.usernameType | UsernameType | No | The type of username validation to be used. Defaults to [UsernameType.OTHER]. |
| options.txPayload | String? | No | A string representing transaction details for confirmation during MFA. This can be plain text or a JSON-formatted string for structured details. |
| options.merchantTrustId | String? | No | Merchant-generated identifier for the current checkout session. Used as a key to retrieve associated trust information and link the session with wallet-issued identity data. |
| options.traceId | String? | No | A unique identifier used to trace and correlate all events associated with a single MFA interaction. If you don’t provide this, the server may generate one automatically. |
| options.deviceId | String? | No | An identifier for the device used in the authentication process. This property helps determine if supported authentications can be proceeded, allowing future authentications to identify the device correctly. Overrides the stored device identifier. If not provided, the SDK uses the stored value. |
data class MFASessionResult(
val flow: MfaNext.Flow?
val remainingFactors: List<RemainingAction>
val username: String?
val isComplete: Boolean
val session: String?
val idToken: String?
val accessToken: String?
val refreshToken: String?
val payloadSignature: String?
val merchantTrustId: String?
val walletTrustId: String?
val passkeyInfo: PasskeyInfo?
val deviceId: String?
val nextAction: ActionName?
)
performAction
performAction(action: ActionName, options: PerformActionOptions?)
Performs an MFA action using the provided factor and optional payload.
In a checkout context, this method commonly covers:
- Passkey Registration (
PASSKEY_REG): Register a new passkey. - Passkey Authentication (
PASSKEY_AUTH): Sign into a wallet account using a passkey. - Passkey Transaction Confirmation (
PASSKEY_TX): Confirm a specific transaction using a passkey. - External Authentication (
EXTERNAL): Sign in with a third-party authenticator.
performAction(action: ActionName, options: PerformActionOptions?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| action | PASSKEY_REGPASSKEY_AUTHPASSKEY_TXOTP_SMSOTP_EMAILOTP_VERIFYEXTERNAL | Yes | The MFA factor/action to execute. |
| options | PerformActionOptions? | No | Action options such as payload, displayName, or an updated txPayload. |
| options.session | String? | No | The MFA state session. This should be obtained from a previous MFA request or initiation step. |
| options.payload | String? | No | The payload required for completing the authentication factor. This typically contains user input or challenge-response data. |
| options.displayName | String? | No | A human-palatable name for the user account, intended only for display on your passkeys. |
| options.txPayload | String? | No | An updated transaction payload generated by the merchant to represent the purchase or operation being confirmed. This updates the initial txPayload used in the beginFlow method. |
| options.activity | Activity? | No | An optional Activity required for passkey operations. |
| options.usernameAnchorView | View? | No | An optional View to anchor the credential manager UI for passkey autofill. |
data class MFASessionResult(
val flow: MfaNext.Flow?
val remainingFactors: List<RemainingAction>
val username: String?
val isComplete: Boolean
val session: String?
val idToken: String?
val accessToken: String?
val refreshToken: String?
val payloadSignature: String?
val merchantTrustId: String?
val walletTrustId: String?
val passkeyInfo: PasskeyInfo?
val deviceId: String?
val nextAction: ActionName?
)
performAction(action: ActionName, activity: Activity, options: PerformActionOptions?)
Performs a passkey-based MFA action.
This is a convenience method for passkey operations that require an Activity.
performAction(action: ActionName, activity: Activity, options: PerformActionOptions?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| action | PASSKEY_REGPASSKEY_AUTHPASSKEY_TXOTP_SMSOTP_EMAILOTP_VERIFYEXTERNAL | Yes | The MFA factor to perform. Must be one of PASSKEY_REG, PASSKEY_AUTH, or PASSKEY_TX. |
| activity | Activity | Yes | The Activity required for passkey operations. |
| options | PerformActionOptions? | No | Optional parameters for the action. |
| options.session | String? | No | The MFA state session. This should be obtained from a previous MFA request or initiation step. |
| options.payload | String? | No | The payload required for completing the authentication factor. This typically contains user input or challenge-response data. |
| options.displayName | String? | No | A human-palatable name for the user account, intended only for display on your passkeys. |
| options.txPayload | String? | No | An updated transaction payload generated by the merchant to represent the purchase or operation being confirmed. This updates the initial txPayload used in the beginFlow method. |
| options.activity | Activity? | No | An optional Activity required for passkey operations. |
| options.usernameAnchorView | View? | No | An optional View to anchor the credential manager UI for passkey autofill. |
data class MFASessionResult(
val flow: MfaNext.Flow?
val remainingFactors: List<RemainingAction>
val username: String?
val isComplete: Boolean
val session: String?
val idToken: String?
val accessToken: String?
val refreshToken: String?
val payloadSignature: String?
val merchantTrustId: String?
val walletTrustId: String?
val passkeyInfo: PasskeyInfo?
val deviceId: String?
val nextAction: ActionName?
)
Errors
LoginIDError
Can occur during the authentication process. It is designed to encapsulate detailed information about login-related errors, making it easier to handle and debug issues related to user authentication.
| Field | Type | Details |
|---|---|---|
| msgCode | string | The error code associated with the login error. Defaults to unknown_error. |
| msg | string | The detailed message or description of the error. Defaults to unknown error. |
| messgage | string | The detailed message or description of the error. Defaults to unknown error. |
...
...
} catch (error: Exception) {
if (error is LoginIDError) {
print("Failed with error: ${error.msg}")
print("Failed with error code: ${error.msgCode}")
}
}