---
title: Configure an Android app for OATH MFA
description: PingOne Advanced Identity Cloud PingAM Android
component: orchsdks
page_id: orchsdks:journey:use-cases/oath/android/index
canonical_url: https://developer.pingidentity.com/orchsdks/journey/use-cases/oath/android/index.html
revdate: Tue, 25 Mar 2025 11:00:37 +0100
keywords: ["DaVinci", "Flows", "Tutorial", "Source Code", "Integration", "SDK", "Android"]
section_ids:
  step_1_adding_core_dependencies: Step 1. Adding core dependencies
  step_2_initializing_the_oath_client: Step 2. Initializing the OATH Client
  default_oath_client_configuration: Default OATH client configuration
  custom_oath_client_configuration: Custom OATH client Configuration
  step_3_managing_oath_credentials: Step 3. Managing OATH credentials
  creating_oath_credentials: Creating OATH credentials
  getting_oath_credentials: Getting OATH credentials
  updating_oath_credentials: Updating OATH credentials
  deleting_oath_credentials: Deleting OATH credentials
  step_4_generating_oath_based_one_time_passcodes: Step 4. Generating OATH-based one-time passcodes
  generating_hotp_codes: Generating HOTP codes
  generating_totp_codes: Generating TOTP codes
  step_5_closing_the_oath_client: Step 5. Closing the OATH client
  handling_errors: Handling errors
  storage: Customizing credential storage
  customizing_the_default_sqlite_based_storage: Customizing the default SQLite-based storage
  implementing_your_own_storage_mechanism: Implementing your own storage mechanism
---

# Configure an Android app for OATH MFA

[icon: circle-check, set=far]PingOne Advanced Identity Cloud [icon: circle-check, set=far]PingAM [icon: android, set=fab]Android

This page guides you through configuring your Android application to support OATH-based Multi-Factor Authentication (MFA) using the **OATH** module.

It covers dependency setup, OATH client initialization, credential management, passcode generation, and custom storage options.

## Step 1. Adding core dependencies

To add the core dependencies for OATH MFA:

1. In the **Project** tree view of your Android Studio project, open the `build.gradle.kts` file.

2. In the `dependencies` section, add the **OATH** module:

   ```gradle
   implementation("com.pingidentity.sdks:mfa:oath:2.0.0")
   ```

## Step 2. Initializing the OATH Client

To use the **OATH** module you must initialize the OATH client in your application.

You can use the default OATH client configuration, or provide your own configuration using a DSL-style builder.

### Default OATH client configuration

To use the default OATH client configuration, call the `OathClient()` method with no additional parameters.

When using the default configuration you will also need initialize the client, by using the `initialize()` method:

Initializing the OATH client with default config

```kotlin
val oathClient = OathClient()

// Initialize the client
oathClient.initialize()
```

### Custom OATH client Configuration

To customize the OATH client configuration, call the `OathClient()` method and pass the custom configuration as parameters.

When you pass a custom configuration the `OathClient()` also initializes the client, without having to manually call an initialize method:

Initializing the OATH client with custom config

```kotlin
val oathClient = OathClient {
    enableCredentialCache = true
    // Any other configuration options
}
```

The properties you can use to customize OATH client configuration are as follows:

* *enableCredentialCache*

  Whether to enable in-memory caching of credentials.

  By default, this is set to `false` for security reasons, as an attacker could potentially access cached credentials from memory dumps.

* *timeout*

  The timeout for network operations, in seconds.

  Default value is `15` seconds.

* *storage*

  The storage implementation to use for OATH credentials.

  If `null`, the default `SQLOathStorage` is used.

  Learn more in [Customizing credential storage](#storage).

* *policyEvaluator*

  The policy evaluator to use for credential policy validation.

  If `null`, the default `MfaPolicyEvaluator` is used.

* *logger*

  The logger instance used for logging messages.

  Defaults to the global logger instance.

  Learn more in [Logging](../../../customization/logging/index.html).

## Step 3. Managing OATH credentials

The **OATH** module relies on a set of credentials, that you can create, retrieve, update, and delete.

The credentials contain details such as the service and user they relate to, and details about how to generate the HOTP or TOTP key.

### Creating OATH credentials

The OATH module lets the user register their device for OATH-based multi-factor authentication (MFA).

The information required to register a device is contained in a specially-encoded URI, which your client application decodes to create the credentials.

This URI is often delivered by QR codes that the client can scan, or directly in the callback output by the [OATH Registration node](https://docs.pingidentity.com/auth-node-ref/latest/oath-registration.html).

Use the `addCredentialFromUri()` method to create OATH credentials and register an MFA device:

* onSuccess

* getOrThrow

* getOrNull

Creating OATH credentials using onSuccess

```kotlin
// Obtain OATH URI from journey callback or QR code
val uri = "otpauth://totp/Example:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Example&algorithm=SHA1&digits=6&period=30"

// Create OATH credentials using onSuccess
oathClient.addCredentialFromUri(uri).onSuccess { credential ->
    // Handle the successfully created credential
    println("Created credential: ${credential.issuer}")
}.onFailure { exception ->
    // Handle error
    println("Failed to add credential: ${exception.message}")
}
```

Creating OATH credentials using getOrThrow

```kotlin
// Obtain OATH URI from journey callback or QR code
val uri = "otpauth://totp/Example:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Example&algorithm=SHA1&digits=6&period=30"

// Create OATH credentials using getOrThrow
try {
    val credential = oathClient.addCredentialFromUri(uri).getOrThrow()
    // Use credential
} catch (e: Exception) {
    // Handle exception
}
```

Creating OATH credentials using getOrNull

```kotlin
// Obtain OATH URI from journey callback or QR code
val uri = "otpauth://totp/Example:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Example&algorithm=SHA1&digits=6&period=30"

// Create OATH credentials using getOrNull
val credential = oathClient.addCredentialFromUri(uri).getOrNull()
if (credential != null) {
    // Use credential
} else {
    // Handle null case
}
```

### Getting OATH credentials

You can get a list of all the registered OATH credentials, or get an individual credential, by passing the credential ID as a parameter.

* All OATH credentials

* Specific OATH credential

Getting all OATH credentials

```kotlin
oathClient.getCredentials().onSuccess { credentials ->
    if (credentials.isEmpty()) {
        showMessage("No credentials found")
    } else {
        displayCredentials(credentials)
    }
}
```

Getting a specific OATH credential

```kotlin
oathClient.getCredential(credentialId).onSuccess { credential ->
    if (credential != null) {
        // Credential found, use it
        displayCredential(credential)
    } else {
        // Credential not found
        showMessage("Credential not found")
    }
}
```

### Updating OATH credentials

You can update the properties of a stored credential with new values, by using the `saveCredential()` method. Pass the updated credential object into the method as a parameter:

Updating an OATH credential

```kotlin
// Change display properties
credential.displayAccountName = "Babs Jensen"
credential.displayIssuer = "Example.com Checking Account"

oathClient.saveCredential(credential).onSuccess { updatedCredential ->
    // Handle successful update
    showMessage("Credential updated")
}.onFailure { exception ->
    // Handle failure
    showError("Failed to update credential: ${exception.message}")
}
```

### Deleting OATH credentials

Use the `deleteCredential()` method to remove individual credentials from the client device. Pass the credential ID into the method as a parameter:

Deleting an OATH credential

```kotlin
// Remove a credential by ID
oathClient.deleteCredential(credentialId).onSuccess { isDeleted ->
    if (isDeleted) {
        showMessage("Credential deleted")
    } else {
        showMessage("Credential not found")
    }
}.onFailure { exception ->
    showError("Failed to delete credential: ${exception.message}")
}
```

## Step 4. Generating OATH-based one-time passcodes

To perform OATH-based multi-factor authentication the user needs to enter the correct one-time passcode.

Your client app needs to generate these one-time passcodes and display them to the user.

### Generating HOTP codes

Use the `generateCode` method to create an HOTP code using the details within the specified credential:

Generating an HOTP for an OATH credential

```kotlin
// Generate code for a credential by its ID
oathClient.generateCode(credentialId).onSuccess { code ->
    // Implement displaying the generated code
    displayCode(code)
}.onFailure { exception ->
    // Handle error
    showError("Failed to generate code: ${exception.message}")
}
```

### Generating TOTP codes

For TOTP codes, the `code` object you generate contains timing and progress information that you can use to customize the user interface:

Generating a TOTP with timing and progress information

```kotlin
// Generate code with timing info for a credential
oathClient.generateCodeWithValidity(credentialId).onSuccess { codeInfo ->
    // Implement displaying the generated code
    displayCode(codeInfo.code)
    // Implement showing how long the code has been valid for
    updateProgressBar(codeInfo.progress)
    // Implement a countdown before generating a new code
    startCountdown(codeInfo.timeRemaining)
}.onFailure { exception ->
    // Handle error
    showError("Failed to generate code: ${exception.message}")
}
```

## Step 5. Closing the OATH client

You can close the client, clean up any temporary files, and regain the memory used by calling the `close()` method:

Closing an OATH client

```kotlin
// Close the OATH client and clean up
oathClient.close()
```

## Handling errors

The **OATH** module uses Kotlin's `Result` API for error handling, which provides a functional approach to error handling:

Handling errors using the Result API

```kotlin
// Using onSuccess/onFailure
oathClient.addCredentialFromUri(uri)
    .onSuccess { credential ->
        // Success path
    }
    .onFailure { exception ->
        when (exception) {
            is IllegalArgumentException -> // Handle invalid URI format
            is MfaException -> // Handle general MFA errors
            else -> // Handle other exceptions
        }
    }

// Using fold for combined handling
oathClient.addCredentialFromUri(uri).fold(
    onSuccess = { credential ->
        // Handle success
    },
    onFailure = { exception ->
        // Handle failure
    }
)

// Using runCatching for additional operations
runCatching {
    oathClient.addCredentialFromUri(uri).getOrThrow()
}.onSuccess { credential ->
    // Do something with credential
}.onFailure { exception ->
    // Handle error
}
```

## Customizing credential storage

The **OATH** module needs to store the credentials it uses on the client device.

By default, it uses an SQLite-based implementation, which you can customize.

You can also provide your own storage mechanism, by implementing the `OathStorage` interface.

### Customizing the default SQLite-based storage

The **OATH** module uses the `SQLOathStorage` implementation for storing OATH credentials by default.

You can customize this SQLite-based default as follows:

Customizing the `SQLOathStorage` implementation

```kotlin
// Create a custom storage instance with specific parameters
val customStorage = SQLOathStorage {
    context = applicationContext
    databaseName = "my_custom_oath_db.db"
    passphraseProvider = NonePassphraseProvider()
}

// Create the client with the custom storage
val oathClient = OathClient {
    storage = customStorage
    enableCredentialCache = true
}
```

The properties you can customize are as follows:

* `context`

  The Android application context is a required property.

* `databaseName`

  Optionally, rename the SQLite database.

* `databaseVersion`

  Customize the database version.

  The default is `1`.

* `passphraseProvider`

  Specify a custom passphrase provider for encrypting the SQLite database.

  * Use `KeyStorePassphraseProvider()` for encrypted storage using the Android KeyStore

  * Use `NonePassphraseProvider()` when you do not require the SQLite database to be encrypted.

  We recommend you encrypt the credential whenever possible.

### Implementing your own storage mechanism

You can implement a custom storage solution as alternative to the default `SQLOathStorage` by implementing the `OathStorage` interface:

Implementing custom OATH credential storage

```kotlin
class MyCustomStorage : OathStorage {
    override fun initialize() {
        // Initialize your custom storage
    }

    override fun close() {
        // Close storage
    }

    override fun clear() {
        // Remove all data
    }

    override fun storeOathCredential(credential: OathCredential) {
        // Store credential data
    }

    override fun retrieveOathCredential(credentialId: String): OathCredential? {
        // Retrieve credential data
        return null
    }

    override fun getAllOathCredentials(): List<OathCredential> {
        // Retrieve all credentials of a type
        return emptyList()
    }

    override fun removeOathCredential(credentialId: String): Boolean {
        // Delete credential data
        return true
    }

    override fun clearOathCredentials() {
        // Clear all credentials of a type
    }
}
```

For an example implementation that uses Android's SharedPreferences for storage, refer to [`SharedPrefsOathStorage`](https://github.com/ForgeRock/ping-android-sdk/blob/develop/mfa/oath/src/androidTest/kotlin/com/pingidentity/mfa/oath/storage/SharedPrefsOathStorage.kt) in the **ping-android-sdk** repo.

|   |                                                                                                                                                                         |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | The `SharedPrefsOathStorage` implementation is for demonstration purposes only, and should not be used for storing potentially sensitive data such as OATH credentials. |
