mcpField
M
maui-authentication

maui-authentication

github.com/davidortinau安全17654 次安装16 周前更新
代码仓库

关于 maui-authentication

为实现 OAuth 和 Microsoft Entra ID 登录的 .NET MAUI 开发者提供身份验证指导,说明安全令牌流程、平台配置陷阱,以及 WebAuthenticator 与 MSAL.NET 的适用场景。

主要功能

  1. 01安全的 OAuth 流程设计
  2. 02WebAuthenticator 配置与注意事项
  3. 03WebAuthenticator 和 MSAL.NET 选择指导
  4. 04MSAL.NET 平台配置检查
  5. 05Blazor Hybrid 身份验证模式

适用场景

  1. 01实现通用 OAuth 或 OIDC 登录
  2. 02添加 Microsoft Entra ID 身份验证
  3. 03排查回调 URI 不匹配
  4. 04处理 Blazor Hybrid 身份验证

安装

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

$npx skills add https://github.com/davidortinau/maui-skills --skill maui-authentication

安装后在 Claude Code 中输入/maui-authentication确认已加载。

附带文件references/authentication-api.md

详细介绍

.NET MAUI 身份验证

安全:切勿嵌入机密信息

❌ 切勿在移动应用二进制文件中嵌入客户端机密、API 密钥或签名密钥。 通过反编译即可轻松提取这些信息。

正确的做法:

  1. 应用调用 WebAuthenticator,并将其指向你的服务端点
  2. 服务向身份提供方发起 OAuth 流程(由服务持有客户端机密)
  3. 提供方通过重定向将授权码返回给你的服务
  4. 服务用授权码交换令牌,并通过回调 URI 将令牌返回给应用

WebAuthenticator 的注意事项

⚠️ Windows WebAuthenticator 无法正常工作

Windows WebAuthenticator 目前无法正常工作。请参阅 dotnet/maui#2702。对于 Windows 身份验证流程,请使用 MSAL 或 WinUI 专用变通方案。

⚠️ Apple Sign In 仅返回一次姓名和电子邮件

Apple 仅在用户首次登录时返回其姓名和电子邮件。请立即缓存这些信息——后续登录不会包含这些信息。

⚠️ PrefersEphemeralWebBrowserSession

在 iOS 13+ 上将其设为 true,以强制显示新的登录提示。设为 false(默认值)时,身份验证会话会与 Safari 共享 Cookie——用户可能会自动登录,这会导致退出登录或切换帐户的流程令人困惑。

⚠️ 回调 URI 不匹配

最常见的身份验证失败原因是 URI 方案不匹配。代码中的 CallbackUrl 必须与以下配置完全匹配:

  • Android:IntentFilter 中的 DataScheme + DataHost
  • iOS:Info.plist 中的 CFBundleURLSchemes
  • Windows:Package.appxmanifest 中的 Protocol Name

WebAuthenticator 检查清单

  • 所有平台配置中的回调 URI 方案均与 CallbackUrl 匹配
  • Android 配置了包含正确 IntentFilter 的 WebAuthenticatorCallbackActivity
  • Android 11+ 的清单中包含用于 Custom Tabs 的 <queries>
  • iOS/Mac Catalyst 的 Info.plist 中包含 CFBundleURLTypes
  • 客户端机密保存在服务端,而不是应用中
  • 使用 SecureStorage 存储令牌,并在退出登录时清除
  • 在 UI 中妥善处理 TaskCanceledException

如何在 WebAuthenticator 和 MSAL.NET 之间进行选择

标准WebAuthenticatorMSAL.NET
身份提供方任意 OAuth 2.0 / OIDCMicrosoft Entra ID
Broker 支持(SSO)❌ 不支持✅ Microsoft Authenticator、Company Portal
条件访问 / MFA❌ 手动处理✅ 内置
令牌缓存与刷新❌ 手动处理(SecureStorage)✅ 自动处理
复杂度简单需要更多设置
适用场景Google、Apple、通用 OIDCEntra ID / Azure AD、Microsoft Graph

MSAL.NET 的注意事项

⚠️ Android:必须实现 OnActivityResult

如果忘记在 MainActivity.OnActivityResult 中调用 AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs,浏览器返回后身份验证会悄无声息地挂起。

⚠️ iOS:必须启用钥匙串共享

如果 Entitlements.plist 中没有包含钥匙串组 com.microsoft.adalcache,令牌缓存会悄无声息地失败,用户每次都会被要求登录。

⚠️ 处理 MsalUiRequiredException

当 AcquireTokenSilent 抛出 MsalUiRequiredException 时,表示缓存的令牌已过期,需要进行交互。请始终回退到 AcquireTokenInteractive。

// ❌ Ignoring MsalUiRequiredException — user gets a crash
var result = await _pca.AcquireTokenSilent(scopes, account).ExecuteAsync(ct);

// ✅ Fall back to interactive when silent fails
try
{
    result = await _pca.AcquireTokenSilent(scopes, account).ExecuteAsync(ct);
}
catch (MsalUiRequiredException)
{
    result = await _pca.AcquireTokenInteractive(scopes).ExecuteAsync(ct);
}
⚠️ 妥善处理用户取消操作
// ✅ Don't treat cancellation as an error
catch (MsalClientException ex) when (ex.ErrorCode == "authentication_canceled")
{
    return null;  // User cancelled — not an error
}
⚠️ Blazor Hybrid:身份验证在 MAUI 层进行

在 MAUI Blazor Hybrid 应用中,身份验证必须在 MAUI 层(MSAL.NET)进行,而不是在 Blazor WebView 中进行。不要使用 AddMicrosoftIdentityWebApp 或服务端 OIDC 模式。请改为:

  1. MAUI 通过 IAuthService(MSAL.NET)处理登录
  2. 自定义 MsalAuthenticationStateProvider 向 Blazor 提供身份验证状态
  3. HttpClient 使用 DelegatingHandler 自动附加持有者令牌

MSAL.NET 检查清单

  • 已添加 Microsoft.Identity.Client NuGet 程序包
  • 已在 Entra ID 中创建应用注册,并设置正确的重定向 URI
  • AuthConfig / appsettings.json 中包含 ClientId、TenantId、Scopes
  • Android:AndroidManifest.xml 中包含用于代理和浏览器的 <queries>
  • Android:MainActivity.OnActivityResult 调用 AuthenticationContinuationHelper
  • iOS:Info.plist 中的 CFBundleURLSchemes 包含 msauth.{BundleId}
  • iOS:Entitlements.plist 中包含密钥链组 com.microsoft.adalcache
  • iOS:AppDelegate.OpenUrl 调用 AuthenticationContinuationHelper
  • 已在 DI 中将 IAuthService 注册为单例
  • 已为 API 调用将 DelegatingHandler 附加到 HttpClient
  • 已接入登录/注销 UI
  • 已处理 MsalUiRequiredException(触发交互式登录)
  • 已妥善处理 authentication_canceled 对应的 MsalClientException

评论

支持 Markdown