> ## Documentation Index
> Fetch the complete documentation index at: https://docs-staging-quickstart-revamp.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Add Login to Your Android Application

<Tip>
  [**Sign up**](https://auth0.com/signup?utm_source=android_quickstart) **for an Auth0 account if you don't have one**
</Tip>

## Get Started

<Steps>
  <Step title="Create a new Android project" stepNumber={1}>
    Create a new Android project for this quickstart.

    **In Android Studio:**

    1. **File** → **New** → **New Project**
    2. Select **Phone and Tablet** → **Empty 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**

    <Tip>
      This creates a modern Android app with Kotlin and Gradle Kotlin DSL, following current Android development best practices.
    </Tip>
  </Step>

  <Step title="Add Auth0 SDK via Gradle" stepNumber={2}>
    Add the Auth0 Android SDK to your project using Gradle.

    **Update your app-level `build.gradle.kts` file:**

    ```kotlin app/build.gradle.kts lines
    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`:**

    ```xml app/src/main/AndroidManifest.xml lines
    <?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>
    ```

    <Tip>
      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.
    </Tip>
  </Step>

  <Step title="Setup your Auth0 App" stepNumber={3}>
    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:

    ```xml 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](https://manage.auth0.com/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`).

    <Info>
      **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.
    </Info>

    <Warning>
      **Important**: Ensure the package name in your callback URLs matches your `applicationId` in `build.gradle.kts`. If authentication fails, verify these values are identical.
    </Warning>
  </Step>

  <Step title="Create the Authentication Service" stepNumber={4}>
    Create a centralized service to handle all authentication logic.

    **Add a new Kotlin file:**

    1. Right-click your package → **New** → **Kotlin Class/File** → **File**
    2. Name it `AuthenticationManager`
    3. Replace its contents with:

    ```kotlin AuthenticationManager.kt expandable lines
    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) {
                }
            })
    }
    }
    ```
  </Step>

  <Step title="Create the layout and styling" stepNumber={6}>
    Create a modern Android layout with Material Design components.

    **Update your `activity_main.xml` layout file:**

    ```xml app/src/main/res/layout/activity_main.xml expandable lines
    <?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`:

    ```xml app/src/main/res/drawable/ic_shield.xml expandable lines
    <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>
    ```
  </Step>

  <Step title="Run your app" stepNumber={7}>
    Build and run your Android application.

    **In Android Studio:**

    ```shellscript
    # 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!!

    <Warning>
      Android will show a browser selection dialog if multiple browsers are installed. Chrome Custom Tabs provide the best user experience for Auth0 authentication.
    </Warning>
  </Step>
</Steps>

<Check>
  **Checkpoint**

  You 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.
</Check>

***

## Troubleshooting & Advanced

<Accordion title="Common Issues & Solutions">
  ### 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: **Build** → **Clean Project** → **Rebuild 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: **File** → **Sync Project with Gradle Files**
  3. Clean build: `./gradlew clean build`

  ### Authentication cancelled by user

  Handle gracefully in your error callback:

  ```kotlin {3,4,5,6} expandable
  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
</Accordion>

<Accordion title="Production Deployment">
  ### 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
</Accordion>

<Accordion title="Advanced Android Integration">
  ### Enhanced Credential Security

  Implement biometric authentication for credential access:

  ```kotlin AuthenticationManager.kt expandable lines
  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:

  ```kotlin AuthenticationManager.kt expandable lines
  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:

  ```xml app/src/main/res/xml/network_security_config.xml expandable lines
  <?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`:

  ```xml
  <application
      android:networkSecurityConfig="@xml/network_security_config"
      ... />
  ```
</Accordion>
