---
title: "Embed Account Security Management in Your Android App with Auth0 Universal Native Components"
description: "Learn how to build a production-ready native post-login experience in Android using Auth0 Universal Native Components. "
authors:
  - name: "Juan Quintero"
    url: "https://auth0.com/blog/authors/juan-quintero/"
  - name: "Carla Urrea Stabile"
    url: "https://auth0.com/blog/authors/carla-stabile/"
date: "Aug 10, 2026"
category: "Developers"
tags: ["android", "kotlin"]
url: "https://auth0.com/blog/account-security-management-android-auth0-universal-native-components/"
---

# Embed Account Security Management in Your Android App with Auth0 Universal Native Components

<style>
    
  /* Increases spacing between bullet points */   
    li {padding-bottom: .7em; }

</style>
Post-login account security is often the feature most mobile teams plan to build and keep pushing to the next sprint. Setting up MFA, managing passkeys, generating recovery codes — it matters enormously to your users’ security posture, but the implementation is weeks of work: custom UIs on top of raw APIs, multi-step enrollment flows, step-up authentication, and the ever-present problem of keeping it all consistent with your app’s design system.

[Auth0 Universal Components](https://auth0.com/docs/get-started/universal-components/universal-components-overview) helped solve this for the web. Today, that same capability comes natively to Android.

[**Auth0 Universal Native Components**](https://auth0.com/docs/get-started/universal-components/android/android-overview) for Android is a Jetpack Compose library that lets you drop a production-ready account security experience directly into your Android app. With a single composable, your users can enroll in TOTP, push notifications, SMS/email OTP, and passkeys, manage their enrolled methods, and generate recovery codes — all without leaving your app or seeing a browser redirect.

In this post, you will learn how you can clone a complete sample app, connect it to your Auth0 tenant, and have a fully functioning native account security experience running on your device — no UI code to write, no enrollment flows to implement.

<div class="alert alert-info alert-icon">
  <i class="icon-budicon-487 icon-info"></i>
  <b>Note: Universal Native Components for Android is currently in Beta. APIs may change before general availability.
</b><br> 
</div>

## Auth0 Universal Native Components on Android

The centerpiece of the SDK is a single composable: `AuthenticatorSettingsComponent()`. It can handle the entire account security lifecycle (enrollment, verification, and removal) for the following authentication factor types:

* **TOTP:** Authenticator app with QR code scanning
* **Push notifications:** Secure push-based authentication
* **SMS OTP:** Phone number verification codes
* **Email OTP:** Email verification codes
* **Recovery codes:** Backup codes for account recovery
* **Passkeys:** FIDO2/WebAuthn biometric enrollment (Android 14+)

Internal navigation between flows is managed by the library. There is no `NavHost` to configure, enrollment state machine to build, or step-up auth errors to handle. You drop in the composable and the library handles everything else.

Auth0 Universal Native Components is built entirely in Jetpack Compose — not a web view inside a native container. That distinction matters. Native components respect platform conventions: gesture navigation, system back handling, dark mode, dynamic type scaling, and accessibility all work correctly out of the box.

## Prerequisites

Before you start, you will need:

* An Auth0 account with **My Account APIs enabled** on your tenant.
* A **custom domain** configured on your Auth0 tenant (required for passkeys, see below)
* **Android Studio Meerkat | 2024.3.1** or later
* An Android device or emulator running **Android 11+ (API 30+)**; passkey enrollment requires **Android 14+ (API 34+)**

## Get the Sample App

Clone the sample app and open it in Android Studio:

```bash
git clone https://github.com/auth0-blog/auth0-universal-components-android  
cd auth0-universal-components-android
```
Open the project in Android Studio and let Gradle sync complete.

The app is fully wired up. Auth0 login, session management, and `AuthenticatorSettingsComponent` are all integrated. All you need to do is point it at your Auth0 tenant.

##Configure Auth0
### 1. Get an Auth0 account and tenant

If you do not have an Auth0 account yet, you will need to sign up to automatically generate your first tenant 

1. Go to the Auth0 Sign Up page.   
2. Sign up using your social account (such as Google, GitHub, or Microsoft) or enter your email address and password.   
3. When prompted, choose your Account Type (for example, Personal) and click Next.   
4. Set up your initial Tenant Domain (this name must be unique, contains lowercase letters, numbers, and hyphens, and cannot be changed later).   
5. Select your preferred Region (this determines where your data is stored).   
6. Click Create to finish. You will be redirected straight to your new Auth0 Dashboard. 

<div class="alert alert-info alert-icon">
  <i class="icon-budicon-487 icon-info"></i>
  <b>Note: If you already have an account and want a completely fresh environment, click your tenant name in the top-left corner of the Auth0 Dashboard and click Create Tenant.</b><br> 
</div>

### 2. Set up a custom domain (required for passkeys)

Passkeys use your Auth0 domain as the WebAuthn Relying Party ID (RP ID). Auth0’s default domain (`YOUR_TENANT.auth0.com`) is shared across tenants, which causes passkey association to fail on Android. A custom domain gives your app an isolated RP ID tied exclusively to your domain.

To set up a custom domain, go to **Branding → Custom Domains** in the Auth0 Dashboard and follow the verification steps. Once verified, use your custom domain everywhere in this guide in place of your default Auth0 domain.

For a full walkthrough of custom domain setup, see the [Auth0 Custom Domains documentation](https://auth0.com/docs/customize/custom-domains) or our blog post on [Setting Up Custom Domains with Auth0](https://auth0.com/blog/custom-domains-complete-guide/#Understanding-Domain-Structure)

### 3. Create a native application

In the [Auth0 Dashboard](https://manage.auth0.com), go to **Applications → Create Application**, choose **Native**, and give it a name.

### 4. Set callback URLs

In the application settings, set both **Allowed Callback URLs** and **Allowed Logout URLs** to:

`app://YOUR_CUSTOM_DOMAIN/android/YOUR_ANDROID_PACKAGE_NAME/callback`

Replace `YOUR_CUSTOM_DOMAIN` with your verified custom domain (for example, auth.yourdomain.com) and `YOUR_ANDROID_PACKAGE_NAME` with your Android package name.

### 5. Enable My Account API

My Account APIs power the account security components. Navigate to APIs in the sidebar and you will see an option to activate My Account API, click on it and it will be activated. 

### 6. Allow Offline Access on My Account API

After activating the My Account API, navigate to APIs → My Account API → Settings and enable Allow Offline Access. This allows the `offline_access` scope to be issued for the My Account API audience, which is required for Multi-Resource Refresh Token (MRRT) to work. Without this, the SDK cannot exchange the refresh token for a My Account API access token.

### 7. Grant types

After creating the Native application, go to Applications → [Your App] → Settings → Advanced Settings → Grant Types and ensure the following are enabled:

* Authorization Code  
* Refresh Token  
* Passkeys

### 8. Multi-Resource Refresh Token (MRRT)

MRRT allows a single refresh token to be used to obtain access tokens for multiple different API audiences — without requiring the user to re-authenticate.

By default, a refresh token is bound to the audience it was issued for. With MRRT enabled, Auth0 accepts that same refresh token when your app requests a token for a different audience (such as the My Account API), and issues a new access token scoped to that resource.

Universal Native Components relies on MRRT internally. When a user navigates to a factor enrollment screen, the SDK calls `DefaultTokenProvider.fetchApiCredentials()` to fetch a just-in-time token scoped to the My Account API using the existing refresh token from login. 

Without MRRT enabled on your tenant, this call returns an `invalid_grant` error and the account security screen fails to load.

To enable MRRT:

1. Go to go to Applications → [Your App] → Settings → Multi-Resource Refresh Token → Edit Configuration  
2. Find and toggle ON the Auth0 My Account API  
3. Use the pencil icon button to make sure the following scopes are granted  
  * `read:me:authentication_methods`  
  * `delete:me:authentication_methods`  
  * `update:me:authentication_methods ` 
  * `read:me:factors`  
  * `create:me:authentication_methods`  
4. Save

### 9. Register your app for passkeys

Once your custom domain is verified, Android’s Credential Manager needs to confirm that your app is authorized to create passkeys for that domain. Auth0 handles this by serving a `/.well-known/assetlinks.json` file — but only after you register your app.

Go to **Applications → Your App → Advanced Settings → Device Settings** and add:

* **Package name:** `YOUR_ANDROID_PACKAGE_NAME`
* **SHA-256 fingerprint:** your signing certificate’s SHA-256 fingerprint

To get your debug fingerprint you run it in your Mac's Terminal app, or the built-in terminal in Android Studio:

```bash
keytool -list -v \  
  -keystore ~/.android/debug.keystore \  
  -alias androiddebugkey \  
  -storepass android \  
  -keypass android **|** grep SHA256
```
You can verify Auth0 is serving the file correctly by visiting: `https://YOUR_CUSTOM_DOMAIN/.well-known/assetlinks.json`

Your app’s package name and fingerprint should appear in the response.

### 10. Update your credentials in Android Studio

Open `app/src/main/res/values/strings.xml` and replace the placeholder values with your custom domain and client ID:

```xml
<resources>  
    <string name="app_name">Auth0 Native Components</string>  
    <string name="com_auth0_domain">YOUR_CUSTOM_DOMAIN</string>  
    <string name="com_auth0_client_id">YOUR_CLIENT_ID</string>  
</resources>
```

That is the only code change required. Build and run the app.

## What You Will See in the App

After signing in, tap **Account Security** on the home screen. You now have a fully functional native account security screen:

* All enrolled authentication methods are listed in one place.
* Tapping any factor walks through the enrollment flow — QR code scanning for TOTP, phone number entry for SMS, biometric prompt for passkeys.
* Enrolled methods can be removed directly from the list.
* If a flow requires step-up authentication, the SDK triggers it automatically.
* The back button navigates correctly through internal flows without popping back to your app’s nav stack.

## How Auth0 Universal Native Components Work in the App

Here is how the integration works in the sample app, so you can apply the same pattern to your own project.

### SDK initialization

`Auth0UniversalComponents.initialize()` is called once in `MainApplication.onCreate()`, after Auth0 and `CredentialsManager` are set up:

```kotlin
override fun onCreate() {  
    super.onCreate()

    auth0 = Auth0.getInstance(  
        clientId = getString(R.string.com_auth0_client_id),  
        domain = getString(R.string.com_auth0_domain)  
    )  
    auth0.networkingClient = DefaultClient(enableLogging = true)

    credentialsManager = CredentialsManager(  
        AuthenticationAPIClient(auth0),  
        SharedPreferencesStorage(this)  
    )

    Auth0UniversalComponents.initialize(  
        context = this,  
        account = auth0,  
        tokenProvider = DefaultTokenProvider(credentialsManager),  
        scheme = "app"  
    )  
}
```

`DefaultTokenProvider` bridges your existing `CredentialsManager` to the Universal Components SDK. The SDK requests scoped access tokens just-in-time as users navigate between account security flows. You don’t manage token scoping manually.

If you need custom credential handling (biometric-gated retrieval, hardware-backed key stores, or your own secure storage) implement the `TokenProvider` interface and pass it in place of `DefaultTokenProvider`:

```kotlin
class BiometricTokenProvider(  
    private val credentialsManager: CredentialsManager  
) : TokenProvider {  
    override suspend fun fetchCredentials(): Credentials { /* ... */ }  
    override suspend fun fetchApiCredentials(audience: String, scope: String?): APICredentials { /* ... */ }  
    override suspend fun saveApiCredentials(audience: String, credentials: APICredentials) { /* ... */ }  
}
```

### The component

The entire account security screen is a single composable in `ui/SettingsScreen.kt`:

```kotlin
import com.auth0.universalcomponents.presentation.ui.mfa.AuthenticatorSettingsComponent

@Composable  
**fun** SettingsScreen() {  
    AuthenticatorSettingsComponent()  
}
```

That one call can deliver the full account security lifecycle: enrollment, verification, and removal for all factor types, with internal navigation, step-up auth, and state restoration across configuration changes all handled by the library.

## Customize the Theme with Auth0ThemeConfiguration

The component can adapt automatically to the system’s light/dark mode setting. To override this and force a specific appearance or match your app’s brand, pass an `Auth0ThemeConfiguration`:

```kotlin
@Composable  
fun SettingsScreen() {  
    *// Force light theme regardless of system setting*  
    AuthenticatorSettingsComponent(  
        themeConfiguration \= Auth0ThemeConfiguration(color \= Auth0Color.light())  
    )  
}

@Composable  
fun SettingsScreen() {  
    *// Force dark theme*  
    AuthenticatorSettingsComponent(  
        themeConfiguration \= Auth0ThemeConfiguration(color \= Auth0Color.dark())  
    )  
}
```

Passing nothing, the default, follows the system setting automatically.

## Improving Your Android App’s Security Management with Auth0 Universal Native Components

Connecting a production-ready account security experience to your Android app came down to three things: 
* cloning the sample
* creating an Auth0 application in the dashboard
* adding your custom domain and client ID to strings.xml.

The `AuthenticatorSettingsComponent` does the rest — TOTP, push, SMS/email OTP, passkeys, recovery codes, step-up auth, dark mode, and back navigation, with no flow logic written on your end.

The full source code is available at [GitHub](https://github.com/auth0-blog/auth0-universal-components-android).

Universal Native Components for Android is in Beta and actively expanding. Planned upcoming capabilities include embedded login flows (no browser redirect), connected account management, profile editing, and session management — all following the same “one composable” integration model.

To get started, check out the [documentation](https://auth0.com/docs/get-started/universal-components/android/android-overview). To share feedback during the Beta release, reach out to your Auth0 account team.