Skip to main content

Android

Overview

The LoginID Android SDK enables you to add passkey authentication in your native Android application without having to redirect the user to any pages outside your application.

The SDK leverages the Credential Manager API for creating and syncing passkeys with Google Password Manager.

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.

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_PATH with the path to your keystore
  • KEYSTORE_ALIAS with the signing-key alias
  • KEYSTORE_PASSWORD with the keystore password
  • KEY_PASSWORD with the signing-key password

The command output includes the certificate's SHA-256 fingerprint.

Local Development

For local development, you can use the default Android debug keystore with the following values:

  • KEYSTORE_ALIAS: androiddebugkey
  • KEYSTORE_PASSWORD: android
  • KEY_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
└── auth-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/auth-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

import com.loginid.core.models.LoginIDConfig
import com.loginid.mfa.LoginIDAuth

class MyApplication : Application() {
val lid = LoginIDAuth(<LOGINID_BASE_URL>)

override fun onCreate() {
super.onCreate()

// Additional setup...
}
}

Class LoginIDAuth

High-level entry point for LoginID authentication on Android.

This facade composes core SDK services to provide a simple API for:

  • Creating and authenticating with passkeys
  • Confirming transactions (non-repudiation)
  • Requesting, sending, and validating one-time passwords (OTP)
  • Managing passkeys (list, rename, delete)
  • Inspecting and clearing the current session
  • Verifying environment configuration

All public operations are exposed as suspend functions and should be called from a coroutine. Instances are lightweight and can be stored as a singleton in your application layer.

constructor

Initializes a new instance of the LoginIDAuth.

class LoginIDAuth(config: LoginIDConfig)

constructor(config: LoginIDConfig)

ParameterTypeRequiredDescription
configLoginIDConfigYes
config.contextContextYesThe Android application context.
config.baseUrlStringYesThe base URL of the LoginID service. This value is used to resolve the App ID and make API calls.
config.appIdStringNoThe application ID. If not provided, it will be extracted from the baseUrl.
config.useTrustIdBooleanNoA flag to enable or disable the use of Trust ID. Defaults to false.

LoginIDAuth

constructor(context: Context, baseUrl: String)

Creates a new 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.

ParameterTypeRequiredDescription
contextContextYesThe Android application context.
baseUrlStringYesThe LoginID environment base URL (e.g., from your environment configuration).

LoginIDAuth

createPasskey

createPasskey(activity: Activity, username: String, options: CreatePasskeyOptions?)

This method helps to create a passkey. The only required parameter is the username, but additional attributes can be provided in the options parameter. Note: While the authorization token is optional, it must always be used in a production environment. You can skip it during development by adjusting the app configuration in the LoginID dashboard.

A short-lived authorization token is returned, allowing access to protected resources for the given user such as listing, renaming or deleting passkeys.

createPasskey(activity: Activity, username: String, options: CreatePasskeyOptions?)

ParameterTypeRequiredDescription
activityActivityYesThe current activity.
usernameStringYesThe username for which to create the passkey.
optionsCreatePasskeyOptions?NoOptional parameters for passkey creation.
options.authzTokenString?NoAn optional authorization token used for accessing protected resources.
options.usernameTypeUsernameTypeNoThe type of username validation to use. Defaults to UsernameType.OTHER.
options.displayNameString?NoAn optional human-readable name for the user account, displayed in passkeys and authentication prompts.
options.passkeyNameString?NoAn optional custom label or nickname for the passkey, useful for distinguishing between multiple passkeys.
options.deviceIdString?NoAn optional identifier for the device creating the passkey. Used to enable device-specific authentication flows and identify the device during future authentications.

data class AuthResult(
val isAuthenticated: Boolean
val isFallback: Boolean
val fallbackOptions: FallbackMethodsResult?
val token: String?
val userId: String?
val passkeyId: String?
val deviceId: String?
)

createPasskey(activity: Activity, username: String, authzToken: String, options: CreatePasskeyOptions?)

This method helps to create a passkey. The only required parameter is the username, but additional attributes can be provided in the options parameter. Note: While the authorization token is optional, it must always be used in a production environment. You can skip it during development by adjusting the app configuration in the LoginID dashboard.

A short-lived authorization token is returned, allowing access to protected resources for the given user such as listing, renaming or deleting passkeys.

createPasskey(activity: Activity, username: String, authzToken: String, options: CreatePasskeyOptions?)

ParameterTypeRequiredDescription
activityActivityYesThe current activity.
usernameStringYesThe username for which to create the passkey.
authzTokenStringYesAn authorization token from a previous authentication step.
optionsCreatePasskeyOptions?NoOptional parameters for passkey creation.
options.authzTokenString?NoAn optional authorization token used for accessing protected resources.
options.usernameTypeUsernameTypeNoThe type of username validation to use. Defaults to UsernameType.OTHER.
options.displayNameString?NoAn optional human-readable name for the user account, displayed in passkeys and authentication prompts.
options.passkeyNameString?NoAn optional custom label or nickname for the passkey, useful for distinguishing between multiple passkeys.
options.deviceIdString?NoAn optional identifier for the device creating the passkey. Used to enable device-specific authentication flows and identify the device during future authentications.

data class AuthResult(
val isAuthenticated: Boolean
val isFallback: Boolean
val fallbackOptions: FallbackMethodsResult?
val token: String?
val userId: String?
val passkeyId: String?
val deviceId: String?
)

authenticateWithPasskey

authenticateWithPasskey(activity: Activity, username: String, options: AuthenticateWithPasskeyOptions?)

This method authenticates a user with a passkey and may trigger additional browser dialogs to guide the user through the process.

A short-lived authorization token is returned, allowing access to protected resources for the given user such as listing, renaming or deleting passkeys.

authenticateWithPasskey(activity: Activity, username: String, options: AuthenticateWithPasskeyOptions?)

ParameterTypeRequiredDescription
activityActivityYesThe current activity.
usernameStringYesThe username of the user to authenticate.
optionsAuthenticateWithPasskeyOptions?NoOptional parameters for passkey authentication.
options.usernameTypeUsernameTypeNoThe type of username validation to be used. Defaults to [UsernameType.OTHER].
options.autofillBoolean?NoWhen true, enables passkey keyboard autofill suggestions. Username does not need to be set.

data class AuthResult(
val isAuthenticated: Boolean
val isFallback: Boolean
val fallbackOptions: FallbackMethodsResult?
val token: String?
val userId: String?
val passkeyId: String?
val deviceId: String?
)

authenticateWithPasskeyAutofill

authenticateWithPasskeyAutofill(activity: Activity, usernameAnchorView: View, options: AuthenticateWithPasskeyOptions?)

Authenticates a user by utilizing the browser's passkey autofill capabilities.

A short-lived authorization token is returned, allowing access to protected resources for the given user such as listing, renaming or deleting passkeys.

authenticateWithPasskeyAutofill(activity: Activity, usernameAnchorView: View, options: AuthenticateWithPasskeyOptions?)

ParameterTypeRequiredDescription
activityActivityYesThe current activity.
usernameAnchorViewViewYesThe view to which the passkey selection UI should be anchored. This is typically a username input field.
optionsAuthenticateWithPasskeyOptions?NoOptional parameters for passkey authentication.
options.usernameTypeUsernameTypeNoThe type of username validation to be used. Defaults to [UsernameType.OTHER].
options.autofillBoolean?NoWhen true, enables passkey keyboard autofill suggestions. Username does not need to be set.

data class AuthResult(
val isAuthenticated: Boolean
val isFallback: Boolean
val fallbackOptions: FallbackMethodsResult?
val token: String?
val userId: String?
val passkeyId: String?
val deviceId: String?
)

confirmTransaction

confirmTransaction(activity: Activity, username: String, txPayload: String, options: ConfirmTransactionOptions?)

This method initiates a non-repudiation signature process by generating a transaction-specific challenge and then expects the client to provide an assertion response using a passkey.

This method is useful for confirming actions such as payments or changes to sensitive account information, ensuring that the transaction is being authorized by the rightful owner of the passkey.

For a more detailed guide click here.

confirmTransaction(activity: Activity, username: String, txPayload: String, options: ConfirmTransactionOptions?)

ParameterTypeRequiredDescription
activityActivityYesThe current activity.
usernameStringYesThe username of the account holder confirming the transaction.
txPayloadStringYesA string representing the transaction details, such as an amount or action.
optionsConfirmTransactionOptions?NoOptional parameters to customize the transaction, like providing a nonce or specifying the txType.
options.nonceString?NoA unique nonce to ensure the transaction's integrity and prevent replay attacks. If not provided, a new UUID will be generated.
options.txTypeString?NoThe type of transaction payload, such as raw or a custom format. Defaults to raw if not specified.

data class TxConfirmResult(
val token: String
val credentialId: String
val passkey: PasskeyDetails?
)

renamePasskey

renamePasskey(id: String, name: String, options: RenamePasskeyOptions?)

Renames a specified passkey by ID. The user must be fully authorized for this call to succeed.

renamePasskey(id: String, name: String, options: RenamePasskeyOptions?)

ParameterTypeRequiredDescription
idStringYesThe unique identifier of the passkey to rename.
nameStringYesThe new name for the passkey.
optionsRenamePasskeyOptions?NoOptions for the request, including an optional authorization token.
options.authzTokenStringYesAn authorization token from a previous authentication step.

renamePasskey(id: String, name: String, authzToken: String)

Renames a specified passkey by ID. The user must be fully authorized for this call to succeed.

renamePasskey(id: String, name: String, authzToken: String)

ParameterTypeRequiredDescription
idStringYesThe unique identifier of the passkey to rename.
nameStringYesThe new name for the passkey.
authzTokenStringYesAuthorization token.

deletePasskey

deletePasskey(id: String, options: DeletePasskeyOptions?)

Delete a specified passkey by ID from LoginID. The user must be fully authorized for this call to succeed.

deletePasskey(id: String, options: DeletePasskeyOptions?)

ParameterTypeRequiredDescription
idStringYesThe unique identifier of the passkey to delete.
optionsDeletePasskeyOptions?NoOptions for the request, including an optional authorization token.
options.authzTokenStringYesAn authorization token from a previous authentication step.

deletePasskey(id: String, authzToken: String)

Delete a specified passkey by ID from LoginID. The user must be fully authorized for this call to succeed.

deletePasskey(id: String, authzToken: String)

ParameterTypeRequiredDescription
idStringYesThe unique identifier of the passkey to delete.
authzTokenStringYesAuthorization token.

requestOtp

requestOtp(options: RequestOtpOptions?)

This method returns a one-time OTP to be displayed on the current device. The user must be authenticated on this device. The OTP is meant for cross-authentication, where the user reads the OTP from the screen and enters it on the target device.

requestOtp(options: RequestOtpOptions?)

ParameterTypeRequiredDescription
optionsRequestOtpOptions?NoOptions for the request, including an optional authorization token.
options.authzTokenString?NoAn optional authorization token for the request. If not provided, the SDK will use a stored token if available.

data class OTPResult(
val code: String
val expiresAt: String
)

validateOtp

validateOtp(username: String, otp: String, options: ValidateOtpOptions?)

This method verifies the OTP and returns an authorization token, which can be used with the createPasskey() method to create a new passkey. The authorization token has a short validity period and should be used immediately.

validateOtp(username: String, otp: String, options: ValidateOtpOptions?)

ParameterTypeRequiredDescription
usernameStringYesThe username of the account being authenticated.
otpStringYesThe one-time password entered by the user.
optionsValidateOtpOptions?NoOptional parameters to customize the request, such as usernameType.
options.usernameTypeUsernameTypeNoThe type of username validation to be used. Defaults to .OTHER.

data class AuthResult(
val isAuthenticated: Boolean
val isFallback: Boolean
val fallbackOptions: FallbackMethodsResult?
val token: String?
val userId: String?
val passkeyId: String?
val deviceId: String?
)

requestAndSendOtp

requestAndSendOtp(username: String, method: MessageMethod, options: RequestAndSendOtpOptions?)

This method requests an OTP from the backend to be sent via the selected method. The method of delivery should be based on the user's choice from the list of available options. This can be found in the result of authenticateWithPasskey method as fallbackOptions.

requestAndSendOtp(username: String, method: MessageMethod, options: RequestAndSendOtpOptions?)

ParameterTypeRequiredDescription
usernameStringYesThe username to send the OTP to.
methodEMAIL
SMS
NoThe delivery channel, either EMAIL or SMS. Defaults to EMAIL.
optionsRequestAndSendOtpOptions?NoOptional parameters to customize the request, such as usernameType.
options.usernameTypeUsernameTypeNoThe type of username validation to be used. Defaults to .OTHER.

verifyConfigSettings

verifyConfigSettings()

Validates the application's configuration settings and provides a suggested correction if any issues are detected.

verifyConfigSettings()

data class LoginIDConfigResult(
val solution: String
val code: String
val errorMessage: String
)

getSessionInfo

getSessionInfo()

Check whether the user of the current session is authenticated and returns user info. This info is retrieved locally and no requests to backend are made.

getSessionInfo()

data class SessionInfo(
val username: String
val id: String
val rpId: String
)

logout

logout()

Clears current user session. This method deletes the authorization token locally.

logout()

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.

FieldTypeDetails
msgCodestringThe error code associated with the login error. Defaults to unknown_error.
msgstringThe detailed message or description of the error. Defaults to unknown error.
messgagestringThe 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}")
}
}