mcpField
A
auth0-net-android

auth0-net-android

github.com/auth0安全55219 次安装1 天前更新
代码仓库

关于 auth0-net-android

为 Agent 提供在 .NET Android 应用中集成 Auth0 身份验证的指导,使用 `Auth0.OidcClient.AndroidX`。内容涵盖 Chrome Custom Tabs 中的 PKCE 流程、回调处理、安全令牌存储和构建验证。

主要功能

  1. 01.NET Android 的 Auth0 集成指导
  2. 02PKCE 登录与注销流程
  3. 03IntentFilter 和回调配置
  4. 04安全令牌存储指导
  5. 05构建与设备测试清单

适用场景

  1. 01在 .NET Android 应用中集成 Auth0 登录
  2. 02配置 Activity 回调处理
  3. 03使用安全存储保存令牌
  4. 04在设备上验证身份验证流程

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/auth0/agent-skills --skill auth0-net-android

安装后在 Claude Code 中输入/auth0-net-android确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
api.md
integration.md
setup.md

详细介绍

auth0-net-android 集成

为 .NET Android 应用添加 Auth0 身份验证。此技能集成 Auth0.OidcClient.AndroidX NuGet 包,该包使用 Chrome Custom Tabs,通过 PKCE 实现安全的基于 OIDC 的登录和注销流程。

Agent 指令: 在提供 SDK 设置说明之前,运行以下命令获取最新发布版本:

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

在所有依赖项行中使用返回的版本,而不要使用下文中任何硬编码版本。

先决条件

  • .NET 8.0 SDK 或更高版本
  • Visual Studio 2022(17.8+)并安装 .NET Android 工作负载,或 JetBrains Rider
  • Android SDK API 21+(最低要求);建议使用适用于 net9.0-android 的 API 34+
  • 已配置 Native 应用的 Auth0 账户
  • Node.js 20+(用于通过 Auth0 CLI 自动设置)

不适用场景

使用场景推荐技能
.NET MAUI 跨平台应用(iOS + Android + Windows)auth0-maui
仅适用于 .NET iOS 的应用auth0-net-ios
仅适用于 Android 的 Kotlin 应用auth0-android
ASP.NET Core 服务端 Web 应用auth0-aspnetcore-authentication
ASP.NET Core Web API(JWT 验证)auth0-aspnetcore-api
React Native 移动应用auth0-react-native

快速入门工作流

Agent 指令: 开始之前,检查用户的项目:

  1. 从 .csproj 文件中的 TargetFramework 确认 .NET 版本
  2. 检查现有的身份验证实现——搜索现有的登录/注销处理程序;如果找到,则接入这些处理程序(复用现有 UI 元素,例如登录按钮,而不要重复创建)
  3. 从 .csproj 或 AndroidManifest.xml 中记录项目的命名空间和包名
  4. 查找现有的 Auth0Client 或 Auth0ClientOptions 用法,以避免重复配置
  1. 安装 SDK:dotnet add package Auth0.OidcClient.AndroidX
  2. 配置 Auth0:有关自动或手动配置,请参阅设置指南。
  3. 集成身份验证:添加 Auth0Client 实例化代码,在 Activity 上配置 IntentFilter,并将登录/注销操作绑定到 UI 操作。
  4. 处理回调:重写 OnNewIntent,并调用 ActivityMediator.Instance.Send(intent.DataString) 以完成身份验证流程。
  5. 构建并验证:dotnet build

Agent 指令: 编写 Auth0Client 配置时:

  • 将 this(Activity)作为第二个参数传递给 Auth0Client 构造函数。
  • 务必设置 Scope = "openid profile email offline_access"——接收刷新令牌需要 offline_access 范围,这样才能在不再次提示用户的情况下静默续期令牌。
  • 回调 URL 格式为 YOUR_ANDROID_PACKAGE_NAME://YOUR_AUTH0_DOMAIN/android/YOUR_ANDROID_PACKAGE_NAME/callback——全部使用小写字母。
  • IntentFilter 中的 DataScheme 必须为小写,否则 Android 将无法接收回调。
  • 在 Activity 上设置 LaunchMode = LaunchMode.SingleTask,以防止创建重复实例。不要使用 SingleTop——它无法正确处理回调重定向,并会创建重复的 Activity 实例。
  • Activity 应继承 Auth0ClientActivity,或者手动重写 OnNewIntent 并调用 ActivityMediator.Instance.Send(intent.DataString)。
  • 安全存储令牌:成功登录后,使用 SecureStorage(MAUI/Essentials)或 EncryptedSharedPreferences(AndroidX Security——需要运行 dotnet add package Xamarin.AndroidX.Security.SecurityCrypto)持久化 AccessToken 和 RefreshToken。切勿将令牌以明文形式存储在 SharedPreferences 中,也不要只存储在内存变量中。

编写配置和代码后,验证构建是否成功:

dotnet build

如果构建失败,请尝试修复问题。失败 5-6 次后,请向用户寻求帮助。

WebAuth — 身份验证的工作原理

SDK 通过 Chrome Custom Tabs(系统浏览器)使用 WebAuth 模式。调用 LoginAsync() 时,SDK 会:

  1. 使用 PKCE 参数构建 /authorize URL
  2. 使用授权 URL 打开 Chrome Custom Tabs
  3. 身份验证完成后,Auth0 会重定向到原生回调 URL
  4. Android 系统匹配 URL 方案,并通过 OnNewIntent 将其传递给 Activity
  5. ActivityMediator 完成令牌交换

这是 OAuth 2.0 授权码流与 PKCE 的标准流程,推荐用于原生移动应用。

回调 URL 配置

.NET Android 的原生回调 URL 使用包名作为方案。格式如下:

YOUR_ANDROID_PACKAGE_NAME://YOUR_AUTH0_DOMAIN/android/YOUR_ANDROID_PACKAGE_NAME/callback

其中,YOUR_ANDROID_PACKAGE_NAME 是应用的包名,例如 com.mycompany.myapplication。例如:com.mycompany.myapp://tenant.us.auth0.com/android/com.mycompany.myapp/callback。

注意: 某些 Auth0 原生 SDK 使用 https://{domain}/android/{package}/callback 作为回调 URL 格式。 .NET Android SDK 则使用包名作为 URL 方案。

确保此回调 URL 使用小写字母。

此 URL 必须:

  1. 在 Auth0 Dashboard 的 Allowed Callback URLs 和 Allowed Logout URLs 中注册
  2. 与 Activity 上 IntentFilter 的属性(DataScheme、DataHost、DataPathPrefix)匹配

完成标准

  • 已安装 Auth0.OidcClient.AndroidX 包(最新稳定版本)
  • 已使用 Domain、ClientId 和 Scope = "openid profile email offline_access" 配置 Auth0Client
  • 已在 Activity 上配置 IntentFilter,并设置正确的 DataScheme、DataHost、DataPathPrefix
  • 已在 Activity 上设置 LaunchMode = LaunchMode.SingleTask
  • 已通过 ActivityMediator.Instance.Send(intent.DataString) 处理 OnNewIntent
  • 已将回调 URL 添加到 Auth0 Dashboard 的 Allowed Callback URLs 和 Allowed Logout URLs
  • 令牌已安全存储(SecureStorage 或 EncryptedSharedPreferences)
  • 登录/注销流程正常运行
  • 构建成功且无错误

详细文档

  • 设置指南 — Auth0 租户配置、SDK 安装、IntentFilter 设置
  • 集成模式 — 登录/注销流程、令牌访问、用户资料、错误处理
  • API 参考与测试 — 完整的 Auth0ClientOptions 参考、声明、测试清单、故障排查

常见错误

错误修复方法
Auth0 Dashboard 中的应用类型未设置为 Native在 Dashboard 设置中将应用类型更改为 "Native"
Auth0 Dashboard 中缺少回调 URL将 yourpackagename://{domain}/android/yourpackagename/callback 添加到 Allowed Callback URLs 和 Allowed Logout URLs
DataScheme 未使用小写字母Android 要求方案使用小写字母 — 请使用小写包名
缺少 LaunchMode.SingleTask在 Activity 上设置 LaunchMode = LaunchMode.SingleTask,以防止创建重复实例
未处理 OnNewIntent重写 OnNewIntent 并调用 ActivityMediator.Instance.Send(intent.DataString)
Domain 使用了 https:// 前缀Domain 应仅为主机名(例如 tenant.auth0.com,而不是 https://tenant.auth0.com)
未向 Auth0Client 传递 Activity 上下文将 this 作为第二个参数传递:new Auth0Client(options, this)
IntentFilter 的 DataHost/DataPathPrefix 不匹配确保 DataHost 与 Auth0 域名匹配,且 DataPathPrefix 为 /android/yourpackagename/callback
缺少 offline_access 作用域始终在 Scope 中包含 offline_access,以接收用于静默续期的刷新令牌
使用 LaunchMode.SingleTop 而不是 SingleTask必须使用 LaunchMode.SingleTask — SingleTop 无法正确处理 Auth0 回调重定向
将令牌存储在普通 SharedPreferences 中使用 AndroidX Security 库中的 SecureStorage 或 EncryptedSharedPreferences

测试说明

Agent 指令: 提醒用户除了模拟器,还要在实体设备上进行测试。某些 WebAuth 行为(Chrome Custom Tabs、URL 方案拦截)在实体设备和模拟器上可能有所不同。发布前,请在真实硬件上测试完整的登录 → 回调 → 令牌流程。

实体设备测试:

  • 登录流程:打开 Chrome Custom Tab → 完成身份验证 → 返回应用
  • 回调:OnNewIntent 使用正确的 intent 数据触发
  • 注销流程:打开浏览器 → 清除会话 → 返回应用
  • 取消:用户按下返回键 → 应用妥善处理 UserCancel

相关技能

  • 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

快速参考

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);
登录
var loginResult = await client.LoginAsync();
处理错误
var loginResult = await client.LoginAsync();

if (loginResult.IsError)
{
    Debug.WriteLine($"An error occurred during login: {loginResult.Error}");
}
访问令牌
var loginResult = await client.LoginAsync();

if (!loginResult.IsError)
{
    Debug.WriteLine($"Authentication successful.");
}
用户信息
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}");
}
列出所有声明
if (!loginResult.IsError)
{
    foreach (var claim in loginResult.User.Claims)
    {
        Debug.WriteLine($"{claim.Type} = {claim.Value}");
    }
}
注销
BrowserResultType browserResult = await client.LogoutAsync();
带 IntentFilter 的 Activity(必需)
[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
}
在 OnNewIntent 中处理回调(必需)
protected override async void OnNewIntent(Intent intent)
{
    base.OnNewIntent(intent);

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

参考资料

评论

支持 Markdown