Skip to main content
Sign up for an Auth0 account if you don’t have one

Get Started

1

Create a new Android project

Create a new Android project for this quickstart.In Android Studio:
  1. FileNewNew Project
  2. Select Phone and TabletEmpty Activity template
  3. Configure your project:
    • Name: Auth0-Android-Sample
    • Package name: com.auth0.samples.android
    • Language: Kotlin
    • Minimum SDK: API 24 (Android 7.0)
    • Build configuration language: Kotlin DSL
  4. Click Finish
This creates a modern Android app with Kotlin and Gradle Kotlin DSL, following current Android development best practices.
2

Add Auth0 SDK via Gradle

Add the Auth0 Android SDK to your project using Gradle.Update your app-level build.gradle.kts file:
app/build.gradle.kts
android {
    defaultConfig {
        // Auth0 configuration
        manifestPlaceholders["auth0Domain"] = "@string/com_auth0_domain"
        manifestPlaceholders["auth0Scheme"] = "@string/com_auth0_scheme"
    }
}
dependencies {   
    // Auth0 SDK
    implementation("com.auth0.android:auth0:3.10.0")
}
Add Internet permission to AndroidManifest.xml:
app/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>
The Auth0 SDK automatically handles dependency resolution and includes secure token storage capabilities. Manifest placeholders will be configured with your Auth0 credentials in the next step.
3

Setup your Auth0 App

Next up, you need to create a new app on your Auth0 tenant and add the configuration to your Android project.First, prepare your app/src/main/res/values/strings.xml file with placeholder values:
app/src/main/res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Auth0 Android Sample</string>
    <string name="app_title">Auth0 Android Sample</string>
    <!-- Auth0 Domain and Client Id -->
    <string name="com_auth0_domain">YOUR_AUTH0_DOMAIN</string>
    <string name="com_auth0_client_id">YOUR_AUTH0_CLIENT_ID</string>
    <string name="com_auth0_scheme">https</string>
    <string name="welcome_unauthenticated">Get started by signing in to your account</string>
    <string name="welcome_authenticated">Welcome to Auth0 Android!</string>
    <string name="log_in">Log In</string>
    <string name="log_out">Log Out</string>
</resources>
  1. Head to the Auth0 Dashboard
  2. Click on Applications > Applications > Create Application
  3. In the popup, enter a name for your app, select Native as the app type and click Create
  4. Switch to the Settings tab on the Application Details page
  5. Replace YOUR_AUTH0_DOMAIN and YOUR_AUTH0_CLIENT_ID in the strings.xml file with the Domain and Client ID values from the dashboard
Finally, on the Settings tab of your Application Details page, set Allowed Callback URLs and Allowed Logout URLs to:
https://YOUR_AUTH0_DOMAIN/android/com.auth0.samples.android/callback
Replace YOUR_AUTH0_DOMAIN with your actual Auth0 domain (e.g., dev-abc123.us.auth0.com).
Allowed Callback URLs are a critical security measure to ensure users are safely returned to your application after authentication. Without a matching URL, the login process will fail, and users will be blocked by an Auth0 error page instead of accessing your app.Allowed Logout URLs are essential for providing a seamless user experience upon signing out. Without a matching URL, users will not be redirected back to your application after logout and will instead be left on a generic Auth0 page.The URL scheme includes your package name (com.auth0.samples.android) to ensure the callback is routed to your specific app.
Important: Ensure the package name in your callback URLs matches your applicationId in build.gradle.kts. If authentication fails, verify these values are identical.
4

Create the Authentication Service

Create a centralized service to handle all authentication logic.Add a new Kotlin file:
  1. Right-click your package → NewKotlin Class/FileFile
  2. Name it AuthenticationManager
  3. Replace its contents with:
AuthenticationManager.kt
package com.auth0.samples.android

import android.content.Context
import androidx.fragment.app.FragmentActivity
import com.auth0.android.Auth0
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import com.auth0.android.authentication.AuthenticationAPIClient
import com.auth0.android.authentication.AuthenticationException
import com.auth0.android.authentication.storage.CredentialsManagerException
import com.auth0.android.authentication.storage.SecureCredentialsManager
import com.auth0.android.authentication.storage.SharedPreferencesStorage
import com.auth0.android.callback.Callback
import com.auth0.android.provider.WebAuthProvider
import com.auth0.android.result.Credentials
import com.auth0.android.result.UserProfile

class AuthenticationManager(private val context: Context) {

private val auth0 = Auth0.getInstance(context)
private val credentialsManager: SecureCredentialsManager

private val _isAuthenticated = MutableStateFlow(false)
val isAuthenticated: StateFlow<Boolean> = _isAuthenticated.asStateFlow()

init {
    val authentication = AuthenticationAPIClient(auth0)
    val storage = SharedPreferencesStorage(context)
    credentialsManager = SecureCredentialsManager(context, auth0, storage)
}


fun login() {

    WebAuthProvider.login(auth0)
        .withScheme("https")
        .withScope("openid profile email offline_access")
        .start(context as FragmentActivity, object : Callback<Credentials, AuthenticationException> {
            override fun onSuccess(credentials: Credentials) {
                //Save the credentials
                credentialsManager.saveCredentials(credentials)
                _isAuthenticated.value = true
            }

            override fun onFailure(exception: AuthenticationException) {
                //Handle error cases
            }
        })
}

fun logout() {

    WebAuthProvider.logout(auth0)
        .withScheme("https")
        .start(context as FragmentActivity, object : Callback<Void?, AuthenticationException> {
            override fun onSuccess(result: Void?) {
                credentialsManager.clearCredentials()
                _isAuthenticated.value = false
            }

            override fun onFailure(exception: AuthenticationException) {
            }
        })
}
}
6

Create the layout and styling

Create a modern Android layout with Material Design components.Update your activity_main.xml layout file:
app/src/main/res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background_color"
tools:context=".MainActivity">

<ImageView
    android:id="@+id/authStatusIcon"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:layout_marginTop="32dp"
    android:src="@drawable/ic_shield"
    app:tint="@color/auth0_blue"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/appTitle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="24dp"
    android:text="@string/app_name"
    android:textColor="@color/text_primary"
    android:textSize="28sp"
    android:textStyle="bold"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/authStatusIcon" />

<TextView
    android:id="@+id/welcomeText"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginTop="16dp"
    android:gravity="center"
    android:text="@string/welcome_unauthenticated"
    android:textColor="@color/text_secondary"
    android:textSize="16sp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/appTitle" />

<com.google.android.material.button.MaterialButton
    android:id="@+id/loginButton"
    android:layout_width="0dp"
    android:layout_height="56dp"
    android:layout_marginTop="32dp"
    android:text="@string/log_in"
    android:textSize="16sp"
    android:textStyle="bold"
    app:cornerRadius="8dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/welcomeText" />

<com.google.android.material.button.MaterialButton
    android:id="@+id/logoutButton"
    android:layout_width="0dp"
    android:layout_height="56dp"
    android:layout_marginTop="32dp"
    android:backgroundTint="@color/logout_red"
    android:text="@string/log_out"
    android:textSize="16sp"
    android:textStyle="bold"
    android:visibility="gone"
    app:cornerRadius="8dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/welcomeText" />

</androidx.constraintlayout.widget.ConstraintLayout>
Add drawable resources: Create app/src/main/res/drawable/ic_shield.xml:
app/src/main/res/drawable/ic_shield.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="@android:color/black"
        android:pathData="M12,1L3,5V11C3,16.55 6.84,21.74 12,23C17.16,21.74 21,16.55 21,11V5L12,1M10,17L6,13L7.41,11.59L10,14.17L16.59,7.58L18,9L10,17Z" />
</vector>
7

Run your app

Build and run your Android application.In Android Studio:
# Sync project with Gradle files (or use Android Studio's "Sync Now")
./gradlew clean build

# Build and install on connected device or emulator
./gradlew installDebug

# Or run directly from Android Studio
# Click the "Run" button or press Shift+F10
Expected flow:
  1. App launches with “Log In” button and shield icon
  2. Tap “Log In” → Chrome Custom Tab opens → Complete login
  3. Returns to app automatically
  4. Success!!
Android will show a browser selection dialog if multiple browsers are installed. Chrome Custom Tabs provide the best user experience for Auth0 authentication.
CheckpointYou should now have a fully functional Auth0 login experience running on your Android device or emulator. The app uses Chrome Custom Tabs for secure authentication and automatically stores credentials.

Troubleshooting & Advanced

Chrome Custom Tab doesn’t redirect back to app

Solutions:
  1. Check Allowed Callback URLs in Auth0 Dashboard match your applicationId exactly
  2. Verify manifest placeholders in build.gradle.kts are correct
  3. Ensure both HTTPS and custom scheme URLs are configured
  4. Clean and rebuild: BuildClean ProjectRebuild Project

App crashes: ‘Auth0 domain not found’

Fix:
  1. Check com_auth0_domain and com_auth0_client_id values are correct
  2. Ensure no typos in domain format (should not include https://)

Build errors with dependencies

Fix:
  1. Update to latest Android Gradle Plugin in build.gradle (project level)
  2. Sync project: FileSync Project with Gradle Files
  3. Clean build: ./gradlew clean build

Authentication cancelled by user

Handle gracefully in your error callback:
override fun onFailure(exception: AuthenticationException) {
    when {
        exception.isAuthenticationCanceled -> 
            showMessage("Login was cancelled")
        exception.isBrowserAppNotAvailable -> 
            showMessage("No browser available")
        else -> 
            showMessage("Login failed: ${exception.getDescription()}")
    }
}

No compatible browser error

  • Install Chrome or another modern browser on your device/emulator
  • Enable Chrome Custom Tabs for better user experience
  • Test on real device with Chrome installed

App Store Preparation

  • Configure Android App Links for seamless authentication
  • Test on multiple Android versions and screen sizes
  • Implement proper error handling for network failures
  • Add ProGuard rules for Auth0 SDK if using code obfuscation
  • Follow Google Play Store policies for authentication flows

Security Considerations

  • Use SecureCredentialsManager for production credential storage
  • Implement certificate pinning for additional API security
  • Consider Android Keystore for enhanced credential protection
  • Enable biometric authentication for sensitive operations

Enhanced Credential Security

Implement biometric authentication for credential access:
AuthenticationManager.kt
class AuthenticationManager(private val context: Context) {
    
    private val credentialsManager: SecureCredentialsManager
    
    init {
        val authentication = AuthenticationAPIClient(auth0)
        val storage = SharedPreferencesStorage(context)
        credentialsManager = SecureCredentialsManager(context, authentication, storage)
        
        // Enable biometric authentication
        credentialsManager.requireAuthentication(
            context as FragmentActivity,
            REQUEST_CODE_BIOMETRIC,
            "Biometric Authentication",
            "Please authenticate to access your account"
        )
    }
    
    companion object {
        private const val REQUEST_CODE_BIOMETRIC = 321
    }
}

Custom Scopes and Audience

Request specific scopes and audience for your API:
AuthenticationManager.kt
fun login() {
    WebAuthProvider.login(auth0)
        .withScheme("https")
        .withScope("openid profile email offline_access read:posts")
        .withAudience("https://myapi.example.com")
        .withParameter("prompt", "login")
        .start(context as MainActivity, loginCallback)
}

Network Configuration

Handle network security and certificate pinning:
app/src/main/res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">your-auth0-domain.auth0.com</domain>
        <pin-set>
            <pin digest="SHA-256">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</pin>
        </pin-set>
    </domain-config>
</network-security-config>
Add to AndroidManifest.xml:
<application
    android:networkSecurityConfig="@xml/network_security_config"
    ... />