使用 WebAuthenticator 类可以启动基于浏览器的流,以侦听对注册到应用的特定 URL 的回调。
概述
许多应用需要添加用户身份验证,这通常表示用户能够登录到其现有 Microsoft、Facebook、Google 帐户,以及现在的 Apple 登录帐户。
Microsoft 身份验证库 (MSAL) 提供了出色的统包解决方案,用于向应用添加身份验证。 客户端 NuGet 包甚至还支持 Xamarin 应用。
如果你有兴趣使用自己的 Web 服务进行身份验证,可以使用 WebAuthenticator 来实现客户端功能。
为什么使用服务器后端?
许多验证提供程序已转向仅提供显式或两步身份验证流,以确保获得更好的安全性。 这意味着,你将需要提供程序提供的“客户端密码”才能完成身份验证流。 遗憾的是,要存储机密和存储在移动应用代码中的任何内容、二进制文件,移动应用并不是理想的存储位置,这样做通常被视为不安全。
在这种情况下,最佳做法是将 Web 后端用作移动应用与验证提供程序之间的中间层。
重要
强烈建议不要使用旧的仅移动身份验证库和模式,这些库和模式在身份验证流中没有利用 Web 后端,因为它们本身缺乏存储客户端密码的安全性。
入门
若要开始使用此 API,请阅读 Xamarin.Essentials 的入门指南,确保在项目中正确安装和设置库。
若要访问 WebAuthenticator 功能,需要以下特定于平台的设置。
Android 要求设置意图筛选器来处理回调 URI。 这很容易实现,只需要将 WebAuthenticatorCallbackActivity
类作为子类即可:
const string CALLBACK_SCHEME = "myapp";
[Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop, Exported = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionView },
Categories = new[] { Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryBrowsable },
DataScheme = CALLBACK_SCHEME)]
public class WebAuthenticationCallbackActivity : Xamarin.Essentials.WebAuthenticatorCallbackActivity
{
}
如果项目的目标 Android 版本设置为 Android 11 (R API 30),则必须使用与新的包可见性要求一起使用的查询来更新 Android 清单。
打开 Properties 文件夹下的 AndroidManifest.xml 文件,并在“manifest”节点内添加以下代码:
<queries>
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
使用 WebAuthenticator
在类中添加对 Xamarin.Essentials 的引用:
using Xamarin.Essentials;
此 API 主要包含一个方法 AuthenticateAsync
,该方法采用两个参数:一个是应该用于启动 Web 浏览器流的 URL,另一个是你希望流最终回调到的 URI(需要注册应用才能处理该 URI)。
结果为 WebAuthenticatorResult
,其中包括通过回调 URI 分析的任何查询参数:
var authResult = await WebAuthenticator.AuthenticateAsync(
new Uri("https://mysite.com/mobileauth/Microsoft"),
new Uri("myapp://"));
var accessToken = authResult?.AccessToken;
WebAuthenticator
API 负责在浏览器中启动 URL 并等待至收到回调:
如果用户在任何时候取消流,就会抛出 TaskCanceledException
。
专用身份验证会话
iOS 13 引入了临时的 Web 浏览器 API,使开发者能够将身份验证会话作为专用会话启动。 这使开发人员能够请求身份验证会话之间不提供共享 cookie 或浏览数据,并且每次都是全新的登录会话。 这可通过 Xamarin.Essentials 1.7 for iOS 中引入的新的 WebAuthenticatorOptions
获得。
var url = new Uri("https://mysite.com/mobileauth/Microsoft");
var callbackUrl = new Uri("myapp://");
var authResult = await WebAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions
{
Url = url,
CallbackUrl = callbackUrl,
PrefersEphemeralWebBrowserSession = true
});
平台差异
Apple 登录
根据 Apple 的审核准则,如果应用使用任何社交登录服务进行身份验证,则还必须提供“Apple 登录”选项。
若要将“Apple 登录”添加到应用,首先需要将应用配置为使用“Apple 登录”。
对于 iOS 13 和更高版本,需要调用 AppleSignInAuthenticator.AuthenticateAsync()
方法。 这会在后台使用本机 Apple 登录 API,以便用户可以在这些设备上获得最佳体验。 可以编写共享代码,以便在运行时使用正确的 API,如下所示:
var scheme = "..."; // Apple, Microsoft, Google, Facebook, etc.
WebAuthenticatorResult r = null;
if (scheme.Equals("Apple")
&& DeviceInfo.Platform == DevicePlatform.iOS
&& DeviceInfo.Version.Major >= 13)
{
// Use Native Apple Sign In API's
r = await AppleSignInAuthenticator.AuthenticateAsync();
}
else
{
// Web Authentication flow
var authUrl = new Uri(authenticationUrl + scheme);
var callbackUrl = new Uri("xamarinessentials://");
r = await WebAuthenticator.AuthenticateAsync(authUrl, callbackUrl);
}
var authToken = string.Empty;
if (r.Properties.TryGetValue("name", out var name) && !string.IsNullOrEmpty(name))
authToken += $"Name: {name}{Environment.NewLine}";
if (r.Properties.TryGetValue("email", out var email) && !string.IsNullOrEmpty(email))
authToken += $"Email: {email}{Environment.NewLine}";
// Note that Apple Sign In has an IdToken and not an AccessToken
authToken += r?.AccessToken ?? r?.IdToken;
提示
对于非 iOS 13 设备,这将启动 Web 身份验证流,也可用于在 Android 和 UWP 设备上启用 Apple 登录。 可在 iOS 模拟器上登录 iCloud 帐户来测试“Apple 登录”功能。
ASP.NET Core 服务器后端
可以将 WebAuthenticator
API 与任何 Web 后端服务一起使用。 要将它与 ASP.NET Core 应用一起使用,首先需要通过以下步骤配置 Web 应用:
- 在 ASP.NET Core Web 应用中设置所需的外部社交验证提供程序。
- 在
.AddAuthentication()
调用中设置CookieAuthenticationDefaults.AuthenticationScheme
的默认身份验证方案。 - 在 Startup.cs
.AddAuthentication()
调用中使用.AddCookie()
。 - 必须将所有提供程序配置为
.SaveTokens = true;
。
services.AddAuthentication(o =>
{
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddFacebook(fb =>
{
fb.AppId = Configuration["FacebookAppId"];
fb.AppSecret = Configuration["FacebookAppSecret"];
fb.SaveTokens = true;
});
提示
如果要添加“Apple 登录”,可以使用 AspNet.Security.OAuth.Apple
NuGet 包。 可以在 Essentials GitHub 存储库中查看完整的 Startup.cs 示例。
添加自定义移动身份验证控制器
对于移动身份验证流,通常需要直接向用户选择的提供程序发起流程(例如,通过单击应用登录屏幕上的“Microsoft”按钮)。 另外,还必须能够通过特定回调 URI 将相关信息返回到应用以结束身份验证流。
为此,请使用自定义 API 控制器:
[Route("mobileauth")]
[ApiController]
public class AuthController : ControllerBase
{
const string callbackScheme = "myapp";
[HttpGet("{scheme}")] // eg: Microsoft, Facebook, Apple, etc
public async Task Get([FromRoute]string scheme)
{
// 1. Initiate authentication flow with the scheme (provider)
// 2. When the provider calls back to this URL
// a. Parse out the result
// b. Build the app callback URL
// c. Redirect back to the app
}
}
使用此控制器是为了推断应用正在请求的方案(提供程序),并启动社交提供程序的身份验证流。 当提供程序回调到 Web 后端时,控制器将分析出结果,并使用参数重定向到应用的回调 URI。
有时,你可能希望将数据(例如提供程序的 access_token
)返回给应用(可通过回调 URI 的查询参数执行此操作)。 或者,你可能需要对服务器创建自己的标识,并将自己的令牌重新传递到应用。 选择哪种做法,以及如何完成,这都完全取决于你!
请查看 Essentials 存储库中的完整控制器示例。
注意
上面的示例演示如何从第三方身份验证(即:OAuth)提供程序返回访问令牌。 若要获取可用于向 Web 后端本身授权 Web 请求的令牌,应在 Web 应用中创建自己的令牌,并返回该令牌。 ASP.NET Core 身份验证概述包含有关 ASP.NET Core 中的高级身份验证方案的详细信息。