Labsco
auth0 logo

auth0-net-android

37

by auth0 · part of auth0/agent-skills

Use when adding Auth0 login or token management to a .NET Android application. Integrates Auth0.OidcClient.AndroidX — use even if the user says "add login to my .NET Android app" or references Xamarin Android.

🧩 One of 7 skills in the auth0/agent-skills package — works on its own, and pairs well with its siblings.

This is the playbook your agent receives when the skill activates — you don't need to read it to use the skill, but it's here to audit before installing.

auth0-net-android Integration

Add Auth0 authentication to .NET Android applications. This skill integrates the Auth0.OidcClient.AndroidX NuGet package which uses Chrome Custom Tabs for secure OIDC-based login and logout flows with PKCE.

Agent instruction: Before providing SDK setup instructions, fetch the latest release version by running:

gh api repos/auth0/auth0-oidc-client-net/releases --jq '[.[] | select(.tag_name | startswith("androidx-")) | .tag_name | ltrimstr("androidx-")] | .[0]'

Use the returned version in all dependency lines instead of any hardcoded version below.

When NOT to Use

Use CaseRecommended Skill
.NET MAUI cross-platform app (iOS + Android + Windows)auth0-maui
.NET iOS-only appauth0-net-ios
Android-only Kotlin appauth0-android
ASP.NET Core server-side web appauth0-aspnetcore-authentication
ASP.NET Core Web API (JWT validation)auth0-aspnetcore-api
React Native mobile appauth0-react-native

WebAuth — How Authentication Works

The SDK uses the WebAuth pattern via Chrome Custom Tabs (the system browser). When LoginAsync() is called, the SDK:

  1. Constructs the /authorize URL with PKCE parameters
  2. Opens Chrome Custom Tabs with the authorization URL
  3. After authentication, Auth0 redirects to the native callback URL
  4. The Android system matches the URL scheme and delivers it to your Activity via OnNewIntent
  5. ActivityMediator completes the token exchange

This is the standard OAuth 2.0 Authorization Code flow with PKCE, recommended for native mobile applications.

Done When

  • Auth0.OidcClient.AndroidX package installed (latest stable version)
  • Auth0Client configured with Domain, ClientId, and Scope = "openid profile email offline_access"
  • IntentFilter configured on Activity with correct DataScheme, DataHost, DataPathPrefix
  • LaunchMode = LaunchMode.SingleTask set on Activity
  • OnNewIntent handled with ActivityMediator.Instance.Send(intent.DataString)
  • Callback URL added to Auth0 Dashboard Allowed Callback URLs and Allowed Logout URLs
  • Tokens stored securely (SecureStorage or EncryptedSharedPreferences)
  • Login/logout flow working
  • Build succeeds with no errors

Detailed Documentation

  • Setup Guide — Auth0 tenant configuration, SDK installation, IntentFilter setup
  • Integration Patterns — Login/logout flows, token access, user profile, error handling
  • API Reference & Testing — Full Auth0ClientOptions reference, claims, testing checklist, troubleshooting

Testing Notes

Agent instruction: Remind the user to test on a physical device in addition to emulators. Some WebAuth behaviors (Chrome Custom Tabs, URL scheme interception) may differ on physical devices vs. emulators. Test the full login → callback → token flow on real hardware before shipping.

Physical Device Testing:

  • Login flow: Chrome Custom Tab opens → authenticate → returns to app
  • Callback: OnNewIntent fires with correct intent data
  • Logout flow: Browser opens → session cleared → returns to app
  • Cancel: User presses back → app handles UserCancel gracefully
  • auth0-maui — .NET MAUI cross-platform apps (iOS + Android + Windows)
  • auth0-net-ios — .NET iOS-only apps
  • auth0-android — Android-native Kotlin apps
  • auth0-aspnetcore-authentication — ASP.NET Core server-side web apps
  • auth0-aspnetcore-api — ASP.NET Core Web API with JWT validation

Quick Reference

using Auth0.OidcClient;

var client = new Auth0Client(new Auth0ClientOptions
{
    Domain = "YOUR_AUTH0_DOMAIN",
    ClientId = "YOUR_AUTH0_CLIENT_ID",
    Scope = "openid profile email offline_access"
}, this);

Login

var loginResult = await client.LoginAsync();

Handle Errors

var loginResult = await client.LoginAsync();

if (loginResult.IsError)
{
    Debug.WriteLine($"An error occurred during login: {loginResult.Error}");
}

Access Tokens

var loginResult = await client.LoginAsync();

if (!loginResult.IsError)
{
    Debug.WriteLine($"Authentication successful.");
}

User Information

if (!loginResult.IsError)
{
    Debug.WriteLine($"name: {loginResult.User.FindFirst(c => c.Type == "name")?.Value}");
    Debug.WriteLine($"email: {loginResult.User.FindFirst(c => c.Type == "email")?.Value}");
}

List All Claims

if (!loginResult.IsError)
{
    foreach (var claim in loginResult.User.Claims)
    {
        Debug.WriteLine($"{claim.Type} = {claim.Value}");
    }
}

Logout

BrowserResultType browserResult = await client.LogoutAsync();

Activity with IntentFilter (Required)

[Activity(Label = "AndroidSample", MainLauncher = true, Icon = "@drawable/icon",
    LaunchMode = LaunchMode.SingleTask)]
[IntentFilter(
    new[] { Intent.ActionView },
    Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
    DataScheme = "YOUR_ANDROID_PACKAGE_NAME",
    DataHost = "YOUR_AUTH0_DOMAIN",
    DataPathPrefix = "/android/YOUR_ANDROID_PACKAGE_NAME/callback")]
public class MainActivity : Activity
{
    // Code omitted
}

Handle Callback in OnNewIntent (Required)

protected override async void OnNewIntent(Intent intent)
{
    base.OnNewIntent(intent);

    Auth0.OidcClient.ActivityMediator.Instance.Send(intent.DataString);
}

References