Xamarin.Essentials:Web Authenticator

WebAuthenticator クラスを使用すると、アプリに登録されている特定の URL へのコールバックをリッスンする、ブラウザー ベースのフローを開始できます。

概要

多くのアプリにはユーザー認証を追加する必要があり、これは多くの場合、ユーザーが既存の Microsoft、Facebook、Google、および Apple サインイン アカウントにサインインできるようにすることを意味します。

Microsoft Authentication Library (MSAL) には、アプリに認証を追加するための優れたターンキー ソリューションが用意されています。 クライアントの NuGet パッケージでは、Xamarin アプリもサポートされています。

認証用に独自の Web サービスを使用する場合は、WebAuthenticator を使用してクライアント側の機能を実装することが可能です。

サーバー バックエンドを使用する理由

多くの認証プロバイダーは、セキュリティを強化するために、明示的または 2 本足の認証フローのみの提供へと移行しました。 つまり、認証フローを完了するには、プロバイダーからの "クライアント シークレット" が必要です。 残念ながら、モバイル アプリはシークレットを格納するための最適な場所ではありません。モバイル アプリのコード、バイナリ、またはその他に格納されているデータは、通常、安全でないと見なされます。

ここでのベスト プラクティスは、モバイル アプリと認証プロバイダーの間の中間レイヤーとして、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 マニフェストを更新する必要があります。

[プロパティ] フォルダーにある AndroidManifest.xml ファイルを開き、manifest ノードの内部に以下を追加します。

<queries>
    <intent>
        <action android:name="android.support.customtabs.action.CustomTabsService" />
    </intent>
</queries>

WebAuthenticator の使用

クラスの Xamarin.Essentials への参照を追加します。

using Xamarin.Essentials;

この API は、主に 1 つのメソッド AuthenticateAsync で構成されています。これは 2 つのパラメーターを受け取ります。Web ブラウザー フローを開始するために使用される URL と、フローが最終的にコールバックする予定の、アプリが処理できるように登録されている URI です。

結果は、コールバック URI から解析されたすべてのクエリ パラメーターを含む WebAuthenticatorResult です。

var authResult = await WebAuthenticator.AuthenticateAsync(
        new Uri("https://mysite.com/mobileauth/Microsoft"),
        new Uri("myapp://"));

var accessToken = authResult?.AccessToken;

WebAuthenticator API により、ブラウザーでの URL の起動と、コールバックを受信するまでの待機を管理できます。

Typical Web Authentication Flow

任意の時点でユーザーがフローをキャンセルした場合、TaskCanceledException がスローされます。

プライベート認証セッション

iOS 13 では、開発者が認証セッションをプライベートとして起動するための一時的な Web ブラウザー API を導入しました。 これにより、開発者は、認証セッション間で Cookie の共有またはデータの参照ができないようにすること、および毎回新しいログイン セッションになるようにすることを要求できます。 これは、iOS 用の Xamarin.Essentials 1.7 で導入された新しい 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
    });

プラットフォームによる違い

使用可能な場合は常にカスタム タブが使用されます。それ以外の場合は、URL のインテントが開始されます。

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 サーバー バックエンド

任意の Web バックエンド サービスと共に WebAuthenticator API を使用することができます。 ASP.NET Core アプリと共に使用するには、まず、次の手順で Web アプリを構成する必要があります。

  1. ASP.NET Core Web アプリで、必要な外部ソーシャル認証プロバイダーをセットアップします。
  2. .AddAuthentication() の呼び出しで、既定の認証スキームを CookieAuthenticationDefaults.AuthenticationScheme に設定します。
  3. Startup.cs の .AddAuthentication() の呼び出しで .AddCookie() を使用します。
  4. すべてのプロバイダーは .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 のクエリ パラメーターを使用して実現できます。 または、代わりにサーバー上に独自の ID を作成して、独自のトークンをアプリに渡すこともできます。 この部分で何をどのように実行するかは、お客様の自由です。

Essentials のリポジトリで完全なコントローラーのサンプルを確認してください。

Note

上のサンプルでは、サード パーティの認証 (つまりOAuth) プロバイダーからアクセ ストークンを返す方法が示されています。 Web バックエンド自体への Web 要求を承認するために使用できるトークンを取得するには、Web アプリで独自のトークンを作成し、代わりにそれを返す必要があります。 「ASP.NET Core の認証の概要」には、ASP.NET Core での高度な認証シナリオに関する詳細が記載されています。


API