Web Authenticator
この記事では、.NET Multi-Platform App UI (.NET MAUI) IWebAuthenticator インターフェイスを使用する方法について説明します。 このインターフェイスを使用すると、アプリに登録されている特定の URL へのコールバックをリッスンするブラウザーベースの認証フローを開始できます。
IWebAuthenticator
インターフェイスの既定の実装は、WebAuthenticator.Default プロパティを通じて利用できます。 IWebAuthenticator
インターフェイスと WebAuthenticator
クラスは、Microsoft.Maui.Authentication
名前空間に含まれます。
概要
多くのアプリではユーザー認証を追加する必要があり、これは多くの場合、ユーザーが既存の Microsoft、Facebook、Google、または Apple のサインイン アカウントにサインインできるようにすることを意味します。
ヒント
Microsoft Authentication Library (MSAL) には、アプリに認証を追加するための優れたターンキー ソリューションが用意されています。
認証に独自のウェブサービスを使用することに興味がある場合は、WebAuthenticator を使用してクライアント側の機能を実装できます。
サーバー バックエンドを使用する理由
多くの認証プロバイダーは、セキュリティを強化するために、明示的または 2 本足の認証フローのみの提供へと移行しました。 つまり、認証フローを完了するにはプロバイダーからのクライアント シークレットが必要になります。 残念ながら、モバイル アプリはシークレットを保存するのに適した場所ではなく、モバイル アプリのコード、バイナリ、その他に保存されているものはすべて安全ではないと考えられています。
ここでのベスト プラクティスは、モバイル アプリと認証プロバイダーの間の中間レイヤーとして、Web バックエンドを使用することです。
重要
認証フローで Web バックエンドを利用しない古いモバイル専用認証ライブラリとパターンは、クライアント シークレットの格納に対する本質的なセキュリティ不足のため、使用しないようにすることを強くお勧めします。
作業の開始
WebAuthenticator の機能にアクセスするには、次のプラットフォーム固有の設定が必要です。
Android では、コールバック URI を処理するためにインテント フィルターの設定が必要です。 これは、WebAuthenticatorCallbackActivity
クラスから継承することで実現されます。
using Android.App;
using Android.Content.PM;
namespace YourNameSpace;
[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 : Microsoft.Maui.Authentication.WebAuthenticatorCallbackActivity
{
const string CALLBACK_SCHEME = "myapp";
}
プロジェクトの対象の Android バージョンが Android 11 (R API 30) 以降に設定されている場合は、Android のパッケージの可視性要件を使用するクエリで Android マニフェストを更新する必要があります。
Platforms/Android/AndroidManifest.xml ファイルで、manifest
ノードに次の queries/intent
ノードを追加します。
<queries>
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
WebAuthenticator の使用
API は主に、2 つのパラメーターを取る 1 つのメソッド AuthenticateAsync で構成されています。
- Web ブラウザー フローの開始に使用される URL。
- フローが最終的にコールバックすると予想される URI。これはアプリに登録されます。
結果は、コールバック URI から解析されたすべてのクエリ パラメーターを含む WebAuthenticatorResult です。
try
{
WebAuthenticatorResult authResult = await WebAuthenticator.Default.AuthenticateAsync(
new Uri("https://mysite.com/mobileauth/Microsoft"),
new Uri("myapp://"));
string accessToken = authResult?.AccessToken;
// Do something with the token
}
catch (TaskCanceledException e)
{
// Use stopped auth
}
WebAuthenticator API により、ブラウザーでの URL の起動と、コールバックを受信するまでの待機を管理できます。
任意の時点でユーザーがフローをキャンセルした場合、TaskCanceledException がスローされます。
プライベート認証セッション
iOS 13 では、開発者が認証セッションをプライベートとして起動するための一時的な Web ブラウザー API を導入しました。 これにより、開発者は、認証セッション間で Cookie の共有またはデータの参照ができないようにすること、および毎回新しいログイン セッションになるようにすることを要求できます。 これは、AuthenticateAsync メソッドに渡される WebAuthenticatorOptions パラメーターを通じて利用できます。
try
{
WebAuthenticatorResult authResult = await WebAuthenticator.Default.AuthenticateAsync(
new WebAuthenticatorOptions()
{
Url = new Uri("https://mysite.com/mobileauth/Microsoft"),
CallbackUrl = new Uri("myapp://"),
PrefersEphemeralWebBrowserSession = true
});
string accessToken = authResult?.AccessToken;
// Do something with the token
}
catch (TaskCanceledException e)
{
// Use stopped auth
}
プラットフォームによる違い
このセクションでは、Web 認証 API とのプラットフォーム固有の違いについて説明します。
カスタム タブは、使用可能な場合は常に使用されます。使用できない場合は、システム ブラウザーがフォールバックとして使用されます。
Apple サインイン
Apple のレビュー ガイドラインによると、Apple アプリで認証のためにソーシャル ログイン サービスを使用する場合は、オプションとして Apple サインインも提供する必要があります。 Apple サインインをアプリに追加するには、Apple のエンタイトルメントを持つサインインをアプリに追加する必要があります。 このエンタイトルメントは String
の Array
型の com.apple.developer.applesignin
キーを使用して定義されます。
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
詳細については、developer.apple.com で「Apple エンタイトルメントを使用してサインインする」をご覧ください。
iOS 13 以降では、AppleSignInAuthenticator.AuthenticateAsync メソッドを呼び出します。 これはネイティブの Apple サインイン API を使用するため、ユーザーは各自のデバイス上で最良のエクスペリエンスを得ることができます。 例えば、実行時に適切な API を使用する共有コードを記述できます。
var scheme = "..."; // Apple, Microsoft, Google, Facebook, etc.
var authUrlRoot = "https://mysite.com/mobileauth/";
WebAuthenticatorResult result = null;
if (scheme.Equals("Apple")
&& DeviceInfo.Platform == DevicePlatform.iOS
&& DeviceInfo.Version.Major >= 13)
{
// Use Native Apple Sign In API's
result = await AppleSignInAuthenticator.AuthenticateAsync();
}
else
{
// Web Authentication flow
var authUrl = new Uri($"{authUrlRoot}{scheme}");
var callbackUrl = new Uri("myapp://");
result = await WebAuthenticator.Default.AuthenticateAsync(authUrl, callbackUrl);
}
var authToken = string.Empty;
if (result.Properties.TryGetValue("name", out string name) && !string.IsNullOrEmpty(name))
authToken += $"Name: {name}{Environment.NewLine}";
if (result.Properties.TryGetValue("email", out string email) && !string.IsNullOrEmpty(email))
authToken += $"Email: {email}{Environment.NewLine}";
// Note that Apple Sign In has an IdToken and not an AccessToken
authToken += result?.AccessToken ?? result?.IdToken;
ヒント
iOS 13 以外のデバイスの場合、これによって Web 認証フローが開始されます。これを使用して、Android および Windows デバイスで Apple サインインを有効にすることもできます。 iOS シミュレーターで iCloud アカウントにサインインして、Apple サインインをテストできます。
ASP.NET Core サーバー バックエンド
任意の Web バックエンド サービスで WebAuthenticator API を使用することができます。 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 パッケージを使用できます。 完全な 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 のクエリ パラメーターを使用して実現できます。 または、代わりにサーバー上に独自の ID を作成して、独自のトークンをアプリに渡すこともできます。 この部分で何をどのように実行するかは、お客様の自由です。
完全なコントローラーのサンプルを確認してください。
Note
上記のサンプルでは、サード パーティの認証 (つまり OAuth) プロバイダーからアクセス トークンを返す方法が示されています。 Web バックエンド自体への Web 要求を承認するために使用できるトークンを取得するには、Web アプリで独自のトークンを作成し、代わりにそれを返す必要があります。 「ASP.NET Core の認証の概要」には、ASP.NET Core での高度な認証シナリオに関する詳細が記載されています。
.NET MAUI