# Build custom TOTP generator (Android)

Build a custom authenticator app for generating instant codes required for [TOTP login](/guides/user/be_auth_totp). This guide describes how to integrate TOTP code generation in your Android app with Mosaic Authentication SDK.

Note
Mosaic TOTP login can work with any authenticator app. Creating a custom authenticator app is optional.

## How it works

The TOTP authentication relies on the static code (seed) shared between the authenticator and authenticator app and other settings required to generate code and prove its validity (e.g., code length or validity period). Below are basic flows for connecting the TOTP authenticator with your custom authenticator app and generating TOTP codes.

### Registration

Suppose a user wants to enable TOTP login for your website (see [Login with TOTP](/guides/user/be_auth_totp)). The website presents a QR code that encodes the TOTP secret (and additional configuration). The user opens your authenticator app on their mobile device and scans the QR code. After initializing the SDK ([Step 3](#step-3-initialize-the-sdk)), the authenticator app registers the secret for the user ([Step 5](#step-5-register-secret-in-auth-app)). The user indicates to the website once the mobile flow is completed.

![](/assets/totp_auth_register.129ebde56b4838f604122446086fdd0236291443a7a532b2aca8b0418e686bd7.2397ab79.png)

### Code generation

A user wants to log in to the website which requires TOTP code for authentication (see [Login with TOTP](/guides/user/be_auth_totp)). To obtain the TOTP code, the user proceeds to the authenticator app to generate the code. After initializing the SDK ([Step 3](#step-3-initialize-the-sdk)), the app generates the TOTP code and displays it on the screen ([Step 6](#step-6-generate-totp-codes)). The user inputs this code on the website page.

![](/assets/totp_auth_gen.f888a19ee69fd11d1715af09588f6422bee8212228f21aef882c11e411316c4b.2397ab79.png)

## Step 1: Configure your app

div
div
Admin portal
To integrate with Mosaic, you'll need to configure an application. From the [Applications](https://portal.transmitsecurity.io/applications) page, [create a new application](/guides/user/create_new_application) or use an existing one. From the application settings:

- For **Client type**, select **native**.
- For **Redirect URI**, enter your website URL. This is a mandatory field, but it isn't used for this flow.
- Obtain your client ID and secret, which are autogenerated upon app creation.


## Step 2:Add SDK to your project

div
div
client
Add the following lines in the shared build.gradle file (**allprojects** scope):


```groovy
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        maven {
            url('https://transmit.jfrog.io/artifactory/transmit-security-gradle-release-local/')
        }
        mavenCentral()
        google()
    }
}
```

Add the following in the module build.gradle file (project scope):


```groovy
dependencies {
    implementation("com.ts.sdk:authentication:1.0.+")
}
```

## Step 3: Initialize the SDK

div
div
client
div
registration
div
code generation
Configure the SDK by calling the `initialize()` SDK method using a snippet like the one below, where `CLIENT_ID` is your client ID (obtained in [Step 1](#step-1-configure-your-app)).


```kotlin
/**
 * Initializes the SDK
 * clientID: The ID of the client obtained in Step 1
 * In order to use SDK with another region, provide the base URL as the third initialization parameter, e.g., `https://api.eu.transmitsecurity.io/`
 */

class MyApplication: Application() {
    override fun onCreate() {
        super.onCreate()
        TSAuthentication.initialize(context, clientID)
    }
}
```

## Step 4: Add permissions

div
div
client
Your app needs to obtain camera permissions to support QR scanning for registration. Make sure to add these permissions to your `AndroidManifest.xml` file located in the app directory of your Android project.

## Step 5: Register secret in auth app

div
div
client
div
registration
The TOTP secret is used for generating TOTP codes for authentication. When registering the TOTP authenticator (see [Login with TOTP](/guides/user/be_auth_totp)), Mosaic returns this secret in a URI that also includes the TOTP configuration (found in the Admin Portal). This URI can be passed as is to the authenticator app to register the secret.

For example, suppose your website encodes the URI in a QR code. The authenticator app can allow the user to scan the code, extract the URI from the QR, and then pass it to the SDK using the `registerTOTP()` call below. You can optionally require users to authenticate using biometrics before generating a code, which is also configured by the SDK upon registration. In this case, the context has to be set to `AppCompatActivity` or `FragmentActivity`.

The call returns registration data that your app should store and use when generating codes in the future (see [Step 6](#step-6-generate-totp-codes)).


```kotlin

/**
 * Registers a secret
 * totpUri: URI provided by Mosaic, embedded in a QR
 * securityType: Can be set to "none" or "biometric"
 **/

interface ITSRegisterTOTPCallback {
    fun onSuccess(registrationResult: TSTOTPRegistrationResult)
    fun onFailed(error: TSTOTPError)
}

enum class TSTOTPSecurityType {
    Biometric, None
}

 TSAuthentication.registerTOTP(this, totpUri, securityType, object :
            ITSRegisterTOTPCallback {
            override fun onSuccess(registrationResult: TSTOTPRegistrationResult) {

            }
            override fun onFailed(error: TSTOTPError) {

            }
        })
        data class TSTOTPRegistrationResult(val issuer: String?, val label: String?, val uuid: String)
```

## Step 6: Generate TOTP codes

div
div
client
div
code generation
Implement a button that generates a TOTP code. When triggered, it should execute the following SDK call by passing the `uuid` parameter obtained in [Step 5](#step-5-register-secret-in-auth-app):


```kotlin
/**
 * Generates a TOTP code
 * uuid: ID obtained in Step 5
 **/

interface ITSTOTPGenerateTOTPCallback {
    fun onSuccess(totpCode: String)
    fun onFailed(error: TSTOTPError)
}
TSAuthentication.generateTOTP(this, uuid, object : ITSTOTPGenerateTOTPCallback{
            override fun onSuccess(code: String) {
                // todo: Handle success
            }
            override fun onFailed(error: TSTOTPError) {
                // todo: Handle failure
            }
        })
```

## Step 7: Handle errors

Handle errors that can occur when registering a secret or generating a TOTP code.


```kotlin

sealed class TSTOTPError(open val errorMsg: String?, open val t: Throwable? = null){

    data class SDKNotInitialized(val message: String) : TSTOTPError(message, null)

    data class ApiNotSupported(override val errorMsg: String?, override val t: Throwable?): TSTOTPError(errorMsg, t)

    data class InternalError(override val errorMsg: String?, override val t: Throwable?): TSTOTPError(errorMsg, t)

    data class LoadKeyFailed(override val errorMsg: String, override val t: Throwable): TSTOTPError(errorMsg, t)

    data class GenerateKeyFailed(override val errorMsg: String, override val t: Throwable): TSTOTPError(errorMsg, t)

    data class UnableToProcess(override val errorMsg: String): TSTOTPError(errorMsg)

    data class TimeOut(override val errorMsg: String): TSTOTPError(errorMsg)

    data class NoSpace(override val errorMsg: String): TSTOTPError(errorMsg)

    data class Canceled(override val errorMsg: String): TSTOTPError(errorMsg)

    data class Lockout(override val errorMsg: String): TSTOTPError(errorMsg)

    data class LockoutPermanent(override val errorMsg: String): TSTOTPError(errorMsg)

    data class UserCanceled(override val errorMsg: String): TSTOTPError(errorMsg)

    data class NegativeButton(override val errorMsg: String): TSTOTPError(errorMsg)

    data class NoMatch(override val errorMsg: String?): TSTOTPError(errorMsg)

    object IncorrectURIFormat: TSTOTPError(null)

    object InvalidAlgorithm: TSTOTPError(null)

    object InvalidDigits: TSTOTPError(null)

    object InvalidPeriod: TSTOTPError(null)

    object InvalidSecret: TSTOTPError(null)

    object NotRegistered: TSTOTPError(null)

    object NativeBiometricsNotAvailable: TSTOTPError(null)

    object BiometricsSecurityContextShouldBeFragmentActivityOrAppCompatActivity: TSTOTPError(null)
}
```

## Reference

Mosaic Authentication SDK accepts the configuration URI comprised of the following parameters, for example:


```js
// Line breaks and spaces were added for readability

otpauth://totp/MyApp:user@myapp.com? // Application and user requesting the code (optional)
  secret=ABCWWLT3JVEDCXQJHY2XWTTDNE5QEXYZ& // Base 32 secret generated by TOTP authenticator
  issuer=MyApp& // Application requesting the code
  algorithm=SHA1& // Algorithm used for code generation such as "sha1", "sha256", or "sha512"
  digits=6& // Code length, between 1 and 9
  period=30 // Validity period, in seconds
```