auth0-net-android
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseauth0-net-android Integration
auth0-net-android集成
Add Auth0 authentication to .NET Android applications. This skill integrates the NuGet package which uses Chrome Custom Tabs for secure OIDC-based login and logout flows with PKCE.
Auth0.OidcClient.AndroidXAgent instruction: Before providing SDK setup instructions, fetch the latest release version by running:bashgh 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.
为.NET Android应用添加Auth0认证功能。此技能集成 NuGet包,该包使用Chrome Custom Tabs实现基于OIDC的安全登录和登出流程,并采用PKCE机制。
Auth0.OidcClient.AndroidXAgent指令: 在提供SDK设置说明之前,运行以下命令获取最新版本:bashgh api repos/auth0/auth0-oidc-client-net/releases --jq '[.[] | select(.tag_name | startswith("androidx-")) | .tag_name | ltrimstr("androidx-")] | .[0]'在所有依赖项代码行中使用返回的版本,而非下方任何硬编码版本。
Prerequisites
前置条件
- .NET 8.0 SDK or later
- Visual Studio 2022 (17.8+) with .NET Android workload, or JetBrains Rider
- Android SDK API 21+ (minimum), API 34+ recommended for net9.0-android
- Auth0 account with a Native application configured
- Node.js 20+ (for Auth0 CLI automated setup)
- .NET 8.0 SDK或更高版本
- 安装了.NET Android工作负载的Visual Studio 2022(17.8+),或JetBrains Rider
- Android SDK API 21+(最低要求),net9.0-android推荐使用API 34+
- 已配置Native应用的Auth0账户
- Node.js 20+(用于Auth0 CLI自动化设置)
When NOT to Use
不适用于以下场景
| Use Case | Recommended Skill |
|---|---|
| .NET MAUI cross-platform app (iOS + Android + Windows) | |
| .NET iOS-only app | |
| Android-only Kotlin app | |
| ASP.NET Core server-side web app | |
| ASP.NET Core Web API (JWT validation) | |
| React Native mobile app | |
| 使用场景 | 推荐技能 |
|---|---|
| .NET MAUI跨平台应用(iOS + Android + Windows) | |
| 仅.NET iOS应用 | |
| 仅Android Kotlin应用 | |
| ASP.NET Core服务器端Web应用 | |
| ASP.NET Core Web API(JWT验证) | |
| React Native移动应用 | |
Quick Start Workflow
快速开始流程
Agent instruction: Before starting, examine the user's project:
- Identify the .NET version from the
file (.csproj)TargetFramework- Check for existing authentication implementations — search for existing login/logout handlers and hook into them if found (reuse existing UI elements like login buttons rather than creating duplicates)
- Note the project's namespace and package name from the
or.csprojAndroidManifest.xml- Look for existing
orAuth0Clientusage to avoid duplicate configurationAuth0ClientOptions
- Install SDK:
dotnet add package Auth0.OidcClient.AndroidX - Configure Auth0: See Setup Guide for automatic or manual configuration.
- Integrate authentication: Add instantiation, configure the
Auth0Clienton your Activity, and wire login/logout to UI actions.IntentFilter - Handle callback: Override and call
OnNewIntentto complete the authentication flow.ActivityMediator.Instance.Send(intent.DataString) - Build and verify:
dotnet build
Agent instruction: When writing the Auth0Client configuration:
- Pass
(the Activity) as the second argument tothisconstructor.Auth0Client- Always set
— theScope = "openid profile email offline_access"scope is required to receive refresh tokens, enabling silent token renewal without re-prompting the user.offline_access- The callback URL format is
— all lowercase.YOUR_ANDROID_PACKAGE_NAME://YOUR_AUTH0_DOMAIN/android/YOUR_ANDROID_PACKAGE_NAME/callback- The
in theDataSchememust be lowercase or Android will not receive callbacks.IntentFilter- Set
on the Activity to prevent duplicate instances. Do NOT useLaunchMode = LaunchMode.SingleTask— it does not correctly handle the callback redirect and will create duplicate Activity instances.SingleTop- The Activity should either extend
OR manually overrideAuth0ClientActivityand callOnNewIntent.ActivityMediator.Instance.Send(intent.DataString)- Store tokens securely: After successful login, persist
andAccessTokenusingRefreshToken(MAUI/Essentials) orSecureStorage(AndroidX Security — requiresEncryptedSharedPreferences). Never store tokens in plaindotnet add package Xamarin.AndroidX.Security.SecurityCryptoor in-memory variables only.SharedPreferencesAfter writing configuration and code, verify the build succeeds:bashdotnet buildIf the build fails, attempt to fix the issue. After 5-6 failed attempts, ask the user for help.
Agent指令: 开始前,请检查用户项目:
- 从
文件的.csproj字段识别.NET版本TargetFramework- 检查现有认证实现——搜索已有的登录/登出处理程序,若存在则接入(重用现有UI元素如登录按钮,避免创建重复元素)
- 记录
或.csproj中的项目命名空间和包名AndroidManifest.xml- 查找是否已有
或Auth0Client的使用,避免重复配置Auth0ClientOptions
- 安装SDK:
dotnet add package Auth0.OidcClient.AndroidX - 配置Auth0:参考设置指南进行自动或手动配置。
- 集成认证功能:实例化,在Activity上配置
Auth0Client,并将登录/登出操作关联到UI事件。IntentFilter - 处理回调:重写并调用
OnNewIntent以完成认证流程。ActivityMediator.Instance.Send(intent.DataString) - 构建并验证:
dotnet build
Agent指令: 编写Auth0Client配置时:
- 将
(当前Activity)作为this构造函数的第二个参数传入。Auth0Client- 务必设置
——Scope = "openid profile email offline_access"作用域是获取刷新令牌的必要条件,支持无需重新提示用户即可静默更新令牌。offline_access- 回调URL格式为
——全部小写。YOUR_ANDROID_PACKAGE_NAME://YOUR_AUTH0_DOMAIN/android/YOUR_ANDROID_PACKAGE_NAME/callback 中的IntentFilter必须为小写,否则Android无法接收回调。DataScheme- 在Activity上设置
以避免重复实例。请勿使用LaunchMode = LaunchMode.SingleTask——它无法正确处理回调重定向,会创建重复的Activity实例。SingleTop- Activity应继承
,或手动重写Auth0ClientActivity并调用OnNewIntent。ActivityMediator.Instance.Send(intent.DataString)- 安全存储令牌:登录成功后,使用
(MAUI/Essentials)或SecureStorage(AndroidX Security——需安装EncryptedSharedPreferences)持久化存储dotnet add package Xamarin.AndroidX.Security.SecurityCrypto和AccessToken。绝不要将令牌存储在明文RefreshToken或仅存于内存变量中。SharedPreferences编写完配置和代码后,验证构建是否成功:bashdotnet build若构建失败,尝试修复问题。经过5-6次失败尝试后,请向用户寻求帮助。
WebAuth — How Authentication Works
WebAuth——认证工作原理
The SDK uses the WebAuth pattern via Chrome Custom Tabs (the system browser). When is called, the SDK:
LoginAsync()- Constructs the URL with PKCE parameters
/authorize - Opens Chrome Custom Tabs with the authorization URL
- After authentication, Auth0 redirects to the native callback URL
- The Android system matches the URL scheme and delivers it to your Activity via
OnNewIntent - completes the token exchange
ActivityMediator
This is the standard OAuth 2.0 Authorization Code flow with PKCE, recommended for native mobile applications.
SDK通过Chrome Custom Tabs(系统浏览器)采用WebAuth模式。调用时,SDK会:
LoginAsync()- 构造包含PKCE参数的URL
/authorize - 使用授权URL打开Chrome Custom Tabs
- 认证完成后,Auth0重定向到原生回调URL
- Android系统匹配URL scheme并通过将其传递给你的Activity
OnNewIntent - 完成令牌交换
ActivityMediator
这是适用于原生移动应用的标准OAuth 2.0授权码流程(带PKCE)。
Callback URL Configuration
回调URL配置
The native callback URL for .NET Android uses the package name as the scheme. The format is:
text
YOUR_ANDROID_PACKAGE_NAME://YOUR_AUTH0_DOMAIN/android/YOUR_ANDROID_PACKAGE_NAME/callbackWhere is the Package Name for your application, such as . For example: .
YOUR_ANDROID_PACKAGE_NAMEcom.mycompany.myapplicationcom.mycompany.myapp://tenant.us.auth0.com/android/com.mycompany.myapp/callbackNote: Some Auth0 native SDKs useas the callback URL format. The .NET Android SDK uses the package name as the URL scheme instead.https://{domain}/android/{package}/callback
Ensure that the Callback URL is in lowercase.
This URL must be:
- Registered in Auth0 Dashboard under Allowed Callback URLs and Allowed Logout URLs
- Matched by the attributes (
IntentFilter,DataScheme,DataHost) on your ActivityDataPathPrefix
.NET Android的原生回调URL使用包名作为scheme,格式如下:
text
YOUR_ANDROID_PACKAGE_NAME://YOUR_AUTH0_DOMAIN/android/YOUR_ANDROID_PACKAGE_NAME/callback其中是你的应用包名,例如。示例:。
YOUR_ANDROID_PACKAGE_NAMEcom.mycompany.myapplicationcom.mycompany.myapp://tenant.us.auth0.com/android/com.mycompany.myapp/callback注意: 部分Auth0原生SDK使用作为回调URL格式。而.NET Android SDK使用包名作为URL scheme。https://{domain}/android/{package}/callback
确保回调URL为小写。
此URL必须:
- 在Auth0控制台的允许回调URL和允许登出URL中注册
- 与Activity上的属性(
IntentFilter、DataScheme、DataHost)匹配DataPathPrefix
Done When
完成标准
- package installed (latest stable version)
Auth0.OidcClient.AndroidX - configured with Domain, ClientId, and
Auth0ClientScope = "openid profile email offline_access" - configured on Activity with correct DataScheme, DataHost, DataPathPrefix
IntentFilter - set on Activity
LaunchMode = LaunchMode.SingleTask - handled with
OnNewIntentActivityMediator.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
- 已安装包(最新稳定版本)
Auth0.OidcClient.AndroidX - 已配置Domain、ClientId,且
Auth0ClientScope = "openid profile email offline_access" - Activity上已配置,且
IntentFilter、DataScheme、DataHost正确DataPathPrefix - Activity已设置
LaunchMode = LaunchMode.SingleTask - 已处理并调用
OnNewIntentActivityMediator.Instance.Send(intent.DataString) - 回调URL已添加到Auth0控制台的允许回调URL和允许登出URL
- 令牌已安全存储(使用SecureStorage或EncryptedSharedPreferences)
- 登录/登出流程可正常工作
- 构建无错误
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 reference, claims, testing checklist, troubleshooting
Auth0ClientOptions
- 设置指南 —— Auth0租户配置、SDK安装、IntentFilter设置
- 集成模式 —— 登录/登出流程、令牌访问、用户信息、错误处理
- API参考与测试 —— 完整参考、声明、测试清单、故障排除
Auth0ClientOptions
Common Mistakes
常见错误
| Mistake | Fix |
|---|---|
| App type not set to Native in Auth0 Dashboard | Change application type to "Native" in Dashboard settings |
| Missing callback URL in Auth0 Dashboard | Add |
| Android requires the scheme to be lowercase — use lowercase package name |
Missing | Set |
Not handling | Override |
Using | Domain should be hostname only (e.g., |
| Not passing Activity context to Auth0Client | Pass |
| IntentFilter DataHost/DataPathPrefix mismatch | Ensure DataHost matches your Auth0 domain and DataPathPrefix is |
Missing | Always include |
Using | Must use |
| Storing tokens in plain SharedPreferences | Use |
| 错误 | 修复方案 |
|---|---|
| Auth0控制台中应用类型未设置为Native | 在控制台设置中将应用类型更改为“Native” |
| Auth0控制台中缺少回调URL | 将 |
| Android要求scheme为小写——使用小写包名 |
缺少 | 在Activity上设置 |
未处理 | 重写 |
Domain使用 | Domain应仅为主机名(例如 |
| 未将Activity上下文传递给Auth0Client | 将 |
| IntentFilter的DataHost/DataPathPrefix不匹配 | 确保DataHost与你的Auth0域名匹配,DataPathPrefix为 |
缺少 | 务必在Scope中包含 |
使用 | 必须使用 |
| 将令牌存储在明文SharedPreferences中 | 使用AndroidX Security库的 |
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: fires with correct intent data
OnNewIntent - Logout flow: Browser opens → session cleared → returns to app
- Cancel: User presses back → app handles gracefully
UserCancel
Agent指令: 提醒用户除模拟器外,还需在物理设备上测试。部分WebAuth行为(Chrome Custom Tabs、URL scheme拦截)在物理设备和模拟器上可能存在差异。发布前请在真实硬件上测试完整的登录→回调→令牌流程。
物理设备测试:
- 登录流程:Chrome Custom Tab打开→认证→返回应用
- 回调:触发并携带正确的intent数据
OnNewIntent - 登出流程:浏览器打开→会话清除→返回应用
- 取消:用户按返回键→应用优雅处理
UserCancel
Related Skills
相关技能
- 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
- auth0-maui —— .NET MAUI跨平台应用(iOS + Android + Windows)
- auth0-net-ios —— 仅.NET iOS应用
- auth0-android —— Android原生Kotlin应用
- auth0-aspnetcore-authentication —— ASP.NET Core服务器端Web应用
- auth0-aspnetcore-api —— 带JWT验证的ASP.NET Core Web API
Quick Reference
快速参考
csharp
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);csharp
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
登录
csharp
var loginResult = await client.LoginAsync();csharp
var loginResult = await client.LoginAsync();Handle Errors
错误处理
csharp
var loginResult = await client.LoginAsync();
if (loginResult.IsError)
{
Debug.WriteLine($"An error occurred during login: {loginResult.Error}");
}csharp
var loginResult = await client.LoginAsync();
if (loginResult.IsError)
{
Debug.WriteLine($"登录过程中发生错误:{loginResult.Error}");
}Access Tokens
访问令牌
csharp
var loginResult = await client.LoginAsync();
if (!loginResult.IsError)
{
Debug.WriteLine($"Authentication successful.");
}csharp
var loginResult = await client.LoginAsync();
if (!loginResult.IsError)
{
Debug.WriteLine($"认证成功。");
}User Information
用户信息
csharp
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}");
}csharp
if (!loginResult.IsError)
{
Debug.WriteLine($"姓名: {loginResult.User.FindFirst(c => c.Type == "name")?.Value}");
Debug.WriteLine($"邮箱: {loginResult.User.FindFirst(c => c.Type == "email")?.Value}");
}List All Claims
列出所有声明
csharp
if (!loginResult.IsError)
{
foreach (var claim in loginResult.User.Claims)
{
Debug.WriteLine($"{claim.Type} = {claim.Value}");
}
}csharp
if (!loginResult.IsError)
{
foreach (var claim in loginResult.User.Claims)
{
Debug.WriteLine($"{claim.Type} = {claim.Value}");
}
}Logout
登出
csharp
BrowserResultType browserResult = await client.LogoutAsync();csharp
BrowserResultType browserResult = await client.LogoutAsync();Activity with IntentFilter (Required)
带IntentFilter的Activity(必填)
csharp
[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
}csharp
[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
{
// 代码省略
}Handle Callback in OnNewIntent (Required)
在OnNewIntent中处理回调(必填)
csharp
protected override async void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
Auth0.OidcClient.ActivityMediator.Instance.Send(intent.DataString);
}csharp
protected override async void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
Auth0.OidcClient.ActivityMediator.Instance.Send(intent.DataString);
}