关于 auth0-maui
auth0-maui 是为 .NET MAUI 应用接入 Auth0 OIDC 登录和退出的技能,涵盖 iOS、Android、macOS 和 Windows,并指导 PKCE 流程及刷新令牌会话恢复。
主要功能
- 01基于 PKCE 的 OIDC 登录与退出
- 02通过 WebAuthenticator 使用系统浏览器认证
- 03刷新令牌存储与会话恢复
- 04平台专属回调配置
适用场景
- 01为 .NET MAUI 应用添加 Auth0 认证
- 02在应用重启后恢复登录会话
- 03配置 Android 和 Windows 回调处理
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ auth0/ agent-skills --skill auth0-maui安装后在 Claude Code 中输入/auth0-maui确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api.mdintegration.mdsetup.md详细介绍
auth0-maui 集成
为面向 iOS、Android、macOS 和 Windows 的 .NET MAUI 应用添加 Auth0 身份验证。此技能集成 Auth0.OidcClient.MAUI NuGet 包,该包通过 MAUI 的 WebAuthenticator 使用系统浏览器,实现基于 OIDC 和 PKCE 的安全登录与注销流程。
**Agent 指令:**提供 SDK 设置说明前,请运行以下命令获取最新的 MAUI 发布版本:
gh api repos/auth0/auth0-oidc-client-net/releases --jq '[.[] | select(.tag_name | startswith("maui-")) | .tag_name | ltrimstr("maui-")] | .[0]'在所有依赖项行中使用返回的版本,而不是下方的任何硬编码版本。
前提条件
- .NET 8.0 SDK 或更高版本
- Visual Studio 2022 (17.8+) 并安装 MAUI 工作负载,或支持 MAUI 的 JetBrains Rider
- 对于 iOS:安装了 Xcode 15+ 的 macOS
- 对于 Android:Android SDK API 33+ (net8.0) 或 API 34+ (net9.0)
- 对于 Windows:Windows 10 (10.0.19041.0)+
- 已配置 Native 应用程序的 Auth0 帐户
- Node.js 20+(用于 Auth0 CLI 自动化设置)
不要用于以下场景
| 使用场景 | 推荐技能 |
|---|---|
| ASP.NET Core 服务端 Web 应用 | auth0-aspnetcore-authentication |
| ASP.NET Core Web API(JWT 验证) | auth0-aspnetcore-api |
| React Native 移动应用 | auth0-react-native |
| 仅适用于 iOS 的 Swift 应用 | auth0-swift |
| 仅适用于 Android 的 Kotlin 应用 | auth0-android |
| Expo React Native 应用 | auth0-expo |
快速入门工作流
**Agent 指令:**开始之前,检查用户的项目:
- 从
.csproj文件(TargetFrameworks)中确定 .NET 版本- 检查是否已有身份验证实现 — 搜索现有的登录/注销处理程序,如果找到则接入
- 记录项目的命名空间和目录约定
- 查找现有的
Auth0Client或Auth0ClientOptions用法,避免重复配置
- 安装 SDK:
dotnet add package Auth0.OidcClient.MAUI - 配置 Auth0:有关自动或手动配置,请参阅设置指南。
- 集成身份验证:添加
Auth0Client实例化,并将登录/注销操作连接到 UI 操作。- **重要:**始终设置
Scope = "openid profile email offline_access"—offline_access作用域是获取刷新令牌以静默续订令牌所必需的。
- **重要:**始终设置
- 使用 SecureStorage 持久化令牌:登录后,使用
await SecureStorage.Default.SetAsync("refresh_token", loginResult.RefreshToken)存储刷新令牌。应用启动时,使用RefreshTokenAsync恢复会话。注销时,使用SecureStorage.Default.Remove("refresh_token")清除令牌。 - 注册 URL 方案:配置特定于平台的回调处理:
- Android:创建带有自定义方案(例如
myapp)IntentFilter 的WebAuthenticatorActivity - Windows(需要两个步骤):(1) 将
<uap:Extension Category="windows.protocol"><uap:Protocol Name="myapp"/></uap:Extension>添加到Platforms/Windows/Package.appxmanifest,并且 (2) 在Platforms/Windows/App.xaml.cs中调用Activator.Default.CheckRedirectionActivation() - iOS/macOS:无需额外配置
- Android:创建带有自定义方案(例如
- 构建并验证:
dotnet build
**Agent 指令:**编写 Auth0Client 配置时:
- 务必在 Scope 字符串中包含
offline_access— 如果不包含,则不会返回刷新令牌,访问令牌过期时用户必须每次都重新进行身份验证。- 务必实现令牌持久化:登录后使用
SecureStorage.Default.SetAsync("refresh_token", ...),并在应用启动时使用SecureStorage.Default.GetAsync("refresh_token")静默恢复会话。- 注销时,使用
SecureStorage.Default.Remove("refresh_token")清除存储的令牌。- 务必创建/更新
Platforms/Windows/Package.appxmanifest以注册自定义 URL 方案协议。否则,Windows 在身份验证后不会拦截回调 URL。在<Application>节点的<Extensions>元素内添加<uap:Extension Category="windows.protocol"><uap:Protocol Name="myapp"/></uap:Extension>。- 务必在
Platforms/Windows/App.xaml.cs的构造函数中,将CheckRedirectionActivation()添加为第一行,放在InitializeComponent()之前。编写配置和代码后,验证构建是否成功:
dotnet build如果构建失败,请尝试修复问题。失败 5-6 次后,请向用户寻求帮助。
回调 URL 配置
MAUI SDK 使用自定义 URL 方案处理回调。默认模式为:
myapp://callback
与使用 https://{domain}/{platform}/{bundleId}/callback 或
{bundleId}.auth0://{domain}/ios/{bundleId}/callback 模式的其他 Auth0 原生 SDK 不同,MAUI 使用更简单的自定义方案
方式。你可以自定义方案(例如 com.mycompany.myapp://callback)。无论选择哪种方案,都必须:
- 在 Auth0 Dashboard 的 Allowed Callback URLs 和 Allowed Logout URLs 下注册
- 在特定于平台的回调处理程序中配置(Android
IntentFilter、WindowsPackage.appxmanifest) - 在
Auth0ClientOptions.RedirectUri和Auth0ClientOptions.PostLogoutRedirectUri中设置
**注意:**对于生产应用,请使用反向域名方案(例如
com.yourcompany.yourapp://callback),以降低 URL 方案劫持的风险。
完成标准
- 已安装
Auth0.OidcClient.MAUI包 - 已配置
Auth0Client,包含 Domain、ClientId,以及包含offline_access的Scope - 已在 Android(WebAuthenticatorCallbackActivity)和 Windows(Package.appxmanifest)上注册 URL scheme
- 已将回调 URL(
myapp://callback)添加到 Auth0 Dashboard 的 Allowed Callback URLs 和 Allowed Logout URLs - 登录/登出流程正常运行
- 登录后通过
SecureStorage.Default.SetAsync持久化刷新令牌 - 已在应用启动时通过
SecureStorage.Default.GetAsync+RefreshTokenAsync实现会话恢复 - 构建成功且无错误
- 已在实体设备或模拟器/仿真器上测试
详细文档
- 设置指南 — Auth0 租户配置、SDK 安装、特定平台的回调设置
- 集成模式 — 登录/登出流程、令牌刷新、用户资料、错误处理、MVVM 模式
- API 参考与测试 — 完整的
Auth0ClientOptions参考、声明、测试清单、故障排查
常见错误
| 错误 | 修复方法 |
|---|---|
| 未在 Auth0 Dashboard 中将应用类型设为 Native | 在 Dashboard 设置中将应用类型更改为“Native” |
| Auth0 Dashboard 中缺少回调 URL | 将 myapp://callback(或你的 scheme)添加到 Allowed Callback URLs 和 Allowed Logout URLs |
Android:缺少 WebAuthenticatorCallbackActivity | 创建带有 [IntentFilter] 且与回调 scheme 匹配的 activity 类 |
Windows:未调用 CheckRedirectionActivation() | 在 Windows App.xaml.cs 的开头、InitializeComponent() 之前添加 Activator.Default.CheckRedirectionActivation() |
Domain 使用了 https:// 前缀 | Domain 应仅为主机名(例如 tenant.auth0.com,而不是 https://tenant.auth0.com) |
未请求用于刷新令牌的 offline_access scope | 在 Auth0ClientOptions 的 Scope 中添加 offline_access 以获取刷新令牌 |
| RedirectUri/PostLogoutRedirectUri 与 Dashboard 不匹配 | 确保 URI(scheme + 路径)与 Auth0 Dashboard 中配置的内容完全一致 |
| 未在 Android/Windows 上注册 URL scheme | 在特定平台的配置中注册自定义 URL scheme(参见平台设置步骤) |
| 以纯文本形式存储令牌 | 使用 MAUI Essentials 中的 SecureStorage 持久化刷新令牌 |
测试说明
Agent 指令: 提醒用户除模拟器/仿真器外,还要在实体设备上测试。部分 WebAuthenticator 行为(系统浏览器集成、URL scheme 拦截)在实体设备和模拟器上可能有所不同。发布前,请在真实硬件上测试完整的登录 → 回调 → 令牌流程。
测试清单:
- 登录流程:打开系统浏览器 → 完成身份验证 → 返回应用
- 登出流程:打开浏览器 → 清除会话 → 返回应用
- 令牌刷新:使用存储的刷新令牌调用
RefreshTokenAsync,确保正常运行 - 取消:用户取消登录 → 应用妥善处理
UserCancel - 实体设备:在真实 iOS/Android 设备上测试(不只是模拟器)
- 离线:验证应用重启后令牌刷新正常运行
- 多平台:至少在一个移动平台(iOS 或 Android)和 Windows 上测试
相关技能
- auth0-aspnetcore-authentication — ASP.NET Core 服务端 Web 应用
- auth0-aspnetcore-api — 使用 JWT 验证的 ASP.NET Core Web API
- auth0-android — Android 原生 Kotlin 应用
- auth0-swift — iOS/macOS Swift 应用
- auth0-react-native — React Native 移动应用
- auth0-net-android-ios — .NET Android/iOS(非 MAUI)
快速参考
using Auth0.OidcClient;
// Initialize client
var client = new Auth0Client(new Auth0ClientOptions
{
Domain = "YOUR_AUTH0_DOMAIN",
ClientId = "YOUR_AUTH0_CLIENT_ID",
RedirectUri = "myapp://callback",
PostLogoutRedirectUri = "myapp://callback",
Scope = "openid profile email offline_access"
});
// Login — opens system browser
var loginResult = await client.LoginAsync();
if (!loginResult.IsError)
{
var user = loginResult.User;
var accessToken = loginResult.AccessToken;
var idToken = loginResult.IdentityToken;
var refreshToken = loginResult.RefreshToken;
// Access user claims
var name = user.FindFirst("name")?.Value;
var email = user.FindFirst("email")?.Value;
// Persist refresh token securely for session restoration
if (!string.IsNullOrEmpty(refreshToken))
await SecureStorage.Default.SetAsync("refresh_token", refreshToken);
}
// Logout — clears Auth0 session and stored tokens
await client.LogoutAsync();
SecureStorage.Default.Remove("refresh_token");
// Restore session on app startup (no user interaction needed)
var savedToken = await SecureStorage.Default.GetAsync("refresh_token");
if (!string.IsNullOrEmpty(savedToken))
{
var refreshResult = await client.RefreshTokenAsync(savedToken);
if (!refreshResult.IsError)
{
var newAccessToken = refreshResult.AccessToken;
// Update stored token if rotated
if (!string.IsNullOrEmpty(refreshResult.RefreshToken))
await SecureStorage.Default.SetAsync("refresh_token", refreshResult.RefreshToken);
}
else
{
// Refresh failed — clear and require re-login
SecureStorage.Default.Remove("refresh_token");
}
}
// Get user info from /userinfo endpoint
var userInfo = await client.GetUserInfoAsync(accessToken);
// Login with extra parameters (organization, audience, connection)
var orgLogin = await client.LoginAsync(new { organization = "org_abc123" });
var apiLogin = await client.LoginAsync(new { audience = "https://my-api.example.com" });
Android 回调 Activity(必需)
[Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop, Exported = true)]
[IntentFilter(new[] { Intent.ActionView },
Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
DataScheme = CALLBACK_SCHEME)]
public class WebAuthenticatorActivity : Microsoft.Maui.Authentication.WebAuthenticatorCallbackActivity
{
const string CALLBACK_SCHEME = "myapp";
}
Windows 平台设置(必需 — 两个步骤)
步骤 1:在 Platforms/Windows/Package.appxmanifest 中注册协议:
<Extensions>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="myapp"/>
</uap:Extension>
</Extensions>
步骤 2:在 Platforms/Windows/App.xaml.cs 中处理重定向:
// In Platforms/Windows/App.xaml.cs
public App()
{
if (Auth0.OidcClient.Platforms.Windows.Activator.Default.CheckRedirectionActivation())
return;
this.InitializeComponent();
}