認証と承認

Note

この電子ブックは 2017 年の春に発行され、それ以降更新されていません。 本の中には貴重なものメイン多くがありますが、資料の一部は古くなっています。

認証とは、ユーザーから名前やパスワードなどの識別資格情報を取得し、それらの資格情報を機関に対して検証するプロセスです。 資格情報が有効な場合、資格情報を送信したエンティティは認証済み ID と見なされます。 ID が認証されると、承認プロセスによって、その ID が特定のリソースにアクセスできるかどうかを判断します。

認証と承認を、ASP.NET MVC Web アプリケーションと通信するアプリに Xamarin.Forms 統合するには、ASP.NET Core Identity、Microsoft、Google、Facebook、Twitter などの外部認証プロバイダー、認証ミドルウェアの使用など、多くの方法があります。 eShopOnContainers モバイル アプリは、IdentityServer 4 を使用するコンテナー化された ID マイクロサービスで認証と承認を実行します。 モバイル アプリは、ユーザーの認証またはリソースへのアクセスのために、IdentityServer にセキュリティ トークンを要求します。 IdentityServer がユーザーに代わってトークンを発行するには、ユーザーが IdentityServer にサインインする必要があります。 ただし、IdentityServer は、認証用のユーザー インターフェイスまたはデータベースを備えていません。 したがって、eShopOnContainers 参照アプリケーションでは、ASP.NET Core Identity をこの目的に使います。

認証

アプリケーションが現在のユーザーの ID を認識する必要がある場合は、認証が必要です。 ユーザーを識別するための ASP.NET Core の主要なメカニズムは、開発者が構成したデータ ストアにユーザー情報を格納する ASP.NET Core Identity メンバーシップ システムです。 通常、このデータ ストアは EntityFramework ストアになりますが、カスタム ストアまたはサード パーティのパッケージを使用して、Azure Storage、Azure Cosmos DB、またはその他の場所に ID 情報を格納できます。

ローカル ユーザー データ ストアを利用し、Cookie を介して要求間で ID 情報を保持する認証シナリオ (ASP.NET MVC Web アプリケーションの一般的なシナリオ) では、ASP.NET Core Identity が適切なソリューションです。 ただし、Cookie は、データを保持して送信する自然な手段とは限りません。 たとえば、モバイル アプリからアクセスする RESTful エンドポイントを公開する ASP.NET Core Web アプリケーションでは、通常、このシナリオでは Cookie を使用できないため、ベアラー トークン認証を使用する必要があります。 ただし、ベアラー トークンは簡単に取得でき、モバイル アプリから行われた Web 要求の承認ヘッダーに含めることができます。

IdentityServer 4 を使用したベアラー トークンの発行

IdentityServer 4 は、ASP.NET Core 用の オープンソース OpenID Connect および OAuth 2.0 フレームワークであり、ローカル ASP.NET Core ID ユーザーのセキュリティ トークンの発行など、多くの認証および承認シナリオに使用できます。

Note

OpenID Connect と OAuth 2.0 は非常に似ていますが、役割は異なります。

OpenID Connect は、OAuth 2.0 プロトコルの上位の認証レイヤーです。 OAuth 2 は、アプリケーションがセキュリティ トークン サービスにアクセス トークンを要求し、それらを使って API と通信できるようにするプロトコルです。 この委任により、認証と承認を一元化できるため、クライアント アプリケーションと API 両方の複雑さが軽減されます。

OpenID Connect と OAuth 2.0 の組み合わせは、認証と API アクセスの 2 つの基本的なセキュリティ上の問題を組み合わせたものであり、IdentityServer 4 はこれらのプロトコルの実装です。

eShopOnContainers 参照アプリケーションなど、クライアントからマイクロサービスへの直接通信を使用するアプリケーションでは、図 9-1 に示すように、セキュリティ トークン サービス (STS) として機能する専用の認証マイクロサービスを使用してユーザーを認証できます。 クライアントからマイクロサービスへの直接通信の詳細については、「クライアントとマイクロサービス間の通信」を参照してください

Authentication by a dedicated authentication microservice

図 9-1: 専用認証マイクロサービスによる認証

eShopOnContainers モバイル アプリは、IdentityServer 4 を使用して認証を実行し、API のアクセス制御を行う ID マイクロサービスと通信します。 そのため、モバイル アプリは、ユーザーの認証またはリソースへのアクセスのために、IdentityServer にトークンを要求します。

  • IdentityServer を使用したユーザーの認証は、認証プロセスの結果を表す ID トークンを要求するモバイル アプリによって実現されます。 少なくとも、ユーザーの識別子と、ユーザーが認証された方法とタイミングに関する情報が含まれます。 また、追加の ID データを含めることもできます。
  • IdentityServer を使用したリソースへのアクセスは、アクセス トークンを要求するモバイル アプリによって実現されます。これにより、API リソースへのアクセスが許可されます。 クライアントはアクセス トークンを要求して、API にそれを転送します。 アクセス トークンには、クライアントとユーザー (存在する場合) に関する情報が含まれます。 その後、API はその情報を使ってデータへのアクセスを承認します。

Note

トークンを要求するには、クライアントを IdentityServer に登録する必要があります。

Web アプリケーションへの IdentityServer の追加

ASP.NET Core Web アプリケーションで IdentityServer 4 を使うには、それを Web アプリケーションの Visual Studio ソリューションに追加する必要があります。 詳細については、IdentityServer ドキュメントの概要を参照してください

IdentityServer を Web アプリケーションの Visual Studio ソリューションに含める場合は、Web アプリケーションの HTTP 要求処理パイプラインに追加して、OpenID Connect および OAuth 2.0 エンドポイントへの要求を処理できるようにする必要があります。 これは、次のコード例で示すように、Web アプリケーションの Startup クラスの Configure メソッドで実現されます。

public void Configure(  
    IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)  
{  
    ...  
    app.UseIdentity();  
    ...  
}

Web アプリケーションの HTTP 要求処理パイプラインでは順序が重要です。 そのため、IdentityServer は、ログイン画面を実装する UI フレームワークの前のパイプラインに追加する必要があります。

IdentityServer の構成

IdentityServer は、eShopOnContainers 参照アプリケーションの次のStartupコード例に示すように、メソッドを呼び出services.AddIdentityServerすことによって、Web アプリケーションのクラスのメソッドで構成ConfigureServicesする必要があります。

public void ConfigureServices(IServiceCollection services)  
{  
    ...  
    services.AddIdentityServer(x => x.IssuerUri = "null")  
        .AddSigningCredential(Certificate.Get())                 
        .AddAspNetIdentity<ApplicationUser>()  
        .AddConfigurationStore(builder =>  
            builder.UseSqlServer(connectionString, options =>  
                options.MigrationsAssembly(migrationsAssembly)))  
        .AddOperationalStore(builder =>  
            builder.UseSqlServer(connectionString, options =>  
                options.MigrationsAssembly(migrationsAssembly)))  
        .Services.AddTransient<IProfileService, ProfileService>();  
}

services.AddIdentityServer メソッドを呼び出した後、追加の Fluent API を呼び出して次の構成を行います。

  • 署名に使われる資格情報。
  • ユーザーがアクセスを要求する可能性がある API と ID リソース。
  • トークンを要求するために接続するクライアント。
  • ASP.NET Core Identity。

ヒント

IdentityServer 4 の構成を動的に読み込みます。 IdentityServer 4 の API を使うと、構成オブジェクトのメモリ内リストから IdentityServer を構成できます。 eShopOnContainers 参照アプリケーションでは、これらのメモリ内コレクションはアプリケーションにハードコーディングされています。 ただし、運用シナリオでは、構成ファイルまたはデータベースから動的に読み込むことができます。

ASP.NET Core Identity を使うように IdentityServer を構成する方法については、IdentityServer のドキュメントの「ASP.NET Core Identity の使用」をご覧ください。

API リソースの構成

API リソースを構成するとき、AddInMemoryApiResources メソッドは IEnumerable<ApiResource> コレクションを必要とします。 次に示すコード例は、eShopOnContainers 参照アプリケーションでこのコレクションを提供する GetApis メソッドです。

public static IEnumerable<ApiResource> GetApis()  
{  
    return new List<ApiResource>  
    {  
        new ApiResource("orders", "Orders Service"),  
        new ApiResource("basket", "Basket Service")  
    };  
}

このメソッドでは、IdentityServer が orders API と basket API を保護する必要があることが指定されています。 そのため、これらの API を呼び出すときは、IdentityServer マネージド アクセス トークンが必要になります。 ApiResource 型について詳しくは、IdentityServer 4 のドキュメントの「API リソース」をご覧ください。

ID リソースの構成

ID リソースを構成するとき、AddInMemoryIdentityResources メソッドは IEnumerable<IdentityResource> コレクションを必要とします。 ID リソースは、ユーザー ID、名前、メール アドレスなどのデータです。 各 ID リソースには一意の名前があり、任意の要求の種類を割り当てることができ、ユーザーの ID トークンに含められます。 次に示すコード例は、eShopOnContainers 参照アプリケーションでこのコレクションを提供する GetResources メソッドです。

public static IEnumerable<IdentityResource> GetResources()  
{  
    return new List<IdentityResource>  
    {  
        new IdentityResources.OpenId(),  
        new IdentityResources.Profile()  
    };  
}

OpenID Connect の仕様では、いくつかの標準 ID リソースが指定されています。 最小要件は、ユーザーに一意の ID を生成するためのサポートが提供されていることです。 これは、IdentityResources.OpenId ID リソースを公開することによって実現されます。

Note

このクラスは IdentityResources 、OpenID Connect 仕様で定義されているすべてのスコープ (openid、電子メール、プロファイル、電話、およびアドレス) をサポートします。

IdentityServer では、カスタム ID リソースの定義もサポートされています。 型の IdentityResource 詳細については、 IdentityServer 4 ドキュメントの ID リソース を参照してください。

クライアントの構成

クライアントは、IdentityServer にトークンを要求できるアプリケーションです。 通常、少なくとも次の設定がクライアントごとに定義されている必要があります。

  • 一意のクライアント ID。
  • トークン サービスとの許可される相互作用 (許可の種類と呼ばれます)。
  • ID トークンとアクセス トークンの送信先の場所 (リダイレクト URI と呼ばれます)。
  • クライアントがアクセスを許可されているリソースのリスト (スコープと呼ばれます)。

クライアントを構成するとき、AddInMemoryClients メソッドは IEnumerable<Client> コレクションを必要とします。 次のコード例は、eShopOnContainers 参照アプリケーションでこのコレクションを GetClients 提供するメソッドの eShopOnContainers モバイル アプリの構成を示しています。

public static IEnumerable<Client> GetClients(Dictionary<string,string> clientsUrl)
{
    return new List<Client>
    {
        ...
        new Client
        {
            ClientId = "xamarin",
            ClientName = "eShop Xamarin OpenId Client",
            AllowedGrantTypes = GrantTypes.Hybrid,
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            RedirectUris = { clientsUrl["Xamarin"] },
            RequireConsent = false,
            RequirePkce = true,
            PostLogoutRedirectUris = { $"{clientsUrl["Xamarin"]}/Account/Redirecting" },
            AllowedCorsOrigins = { "http://eshopxamarin" },
            AllowedScopes = new List<string>
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.OfflineAccess,
                "orders",
                "basket"
            },
            AllowOfflineAccess = true,
            AllowAccessTokensViaBrowser = true
        },
        ...
    };
}

この構成では、次のプロパティのデータを指定しています。

  • ClientId: クライアントの一意の ID。
  • ClientName: クライアント表示名。ログ記録と同意画面に使用されます。
  • AllowedGrantTypes: クライアントが IdentityServer と対話する方法を指定します。 詳細については、認証フローの構成を参照してください
  • ClientSecrets: トークン エンドポイントからトークンを要求するときに使用されるクライアント シークレット資格情報を指定します。
  • RedirectUris: トークンまたは承認コードを返す許可 URI を指定します。
  • RequireConsent: 同意画面が必要かどうかを指定します。
  • RequirePkce: 承認コードを使用するクライアントが証明キーを送信する必要があるかどうかを指定します。
  • PostLogoutRedirectUris: ログアウト後にリダイレクトできる URI を指定します。
  • AllowedCorsOrigins: IdentityServer が配信元からのクロスオリジン呼び出しを許可できるように、クライアントの配信元を指定します。
  • AllowedScopes: クライアントがアクセスできるリソースを指定します。 既定では、クライアントはどのリソースに対するアクセス権も持っていません。
  • AllowOfflineAccess: クライアントが更新トークンを要求できるかどうかを指定します。

認証フローの構成

クライアントと IdentityServer の間の認証フローは、Client.AllowedGrantTypes プロパティで許可の種類を指定することにより構成できます。 OpenID Connect と OAuth 2.0 の仕様では、次のような多くの認証フローが定義されています。

  • 暗黙。 このフローはブラウザー ベースのアプリケーションに最適化されており、ユーザー認証専用または認証とアクセス トークン要求に使用する必要があります。 すべてのトークンはブラウザー経由で送信されるため、更新トークンなどの高度な機能は許可されません。
  • 承認コード。 このフローでは、ブラウザー フロント チャネルとは異なり、バック チャネルでトークンを取得でき、クライアント認証をサポートする機能も提供されます。
  • ハイブリッド。 このフローは、暗黙的な種類と、承認コード許可の種類の組み合わせです。 ID トークンはブラウザー チャネルを介して送信され、署名されたプロトコル応答と、承認コードなどの他の成果物が含まれます。 応答の検証が成功したら、バック チャネルを使用してアクセス トークンと更新トークンを取得する必要があります。

ヒント

ハイブリッド認証フローを使用します。 ハイブリッド認証フローは、ブラウザー チャネルに対して行われる多くの攻撃を軽減し、アクセス トークン (および場合によっては更新トークン) を取得するネイティブ アプリケーションに推奨されるフローです。

認証フローについて詳しくは、IdentityServer 4 のドキュメントの許可の種類に関する説明をご覧ください。

認証の実行

IdentityServer がユーザーに代わってトークンを発行するには、ユーザーが IdentityServer にサインインする必要があります。 ただし、IdentityServer は、認証用のユーザー インターフェイスまたはデータベースを備えていません。 したがって、eShopOnContainers 参照アプリケーションでは、ASP.NET Core Identity をこの目的に使います。

eShopOnContainers モバイル アプリは、図 9-2 に示すハイブリッド認証フローを使用して IdentityServer で認証します。

High-level overview of the sign-in process

図 9-2: サインイン プロセスの概要

サインイン要求が行われます <base endpoint>:5105/connect/authorize。 認証が成功すると、IdentityServer は認証コードと ID トークンを含む認証応答を返します。 その後、承認コードが送信され <base endpoint>:5105/connect/token、アクセス トークン、ID トークン、および更新トークンで応答します。

eShopOnContainers モバイル アプリは、追加のパラメーターを使用して <base endpoint>:5105/connect/endsession要求を送信することによって IdentityServer からサインアウトします。 サインアウトが発生すると、IdentityServer はログアウト後のリダイレクト URI をモバイル アプリに送信して応答します。 図 9-3 は、このプロセスを示しています。

High-level overview of the sign-out process

図 9-3: サインアウト プロセスの概要

eShopOnContainers モバイル アプリでは、IdentityServer との通信は、インターフェイスを IdentityService 実装 IIdentityService するクラスによって実行されます。 このインターフェイスでは、実装するクラスは CreateAuthorizationRequestCreateLogoutRequestGetTokenAsync メソッドを提供する必要があることが指定されています。

サインイン

ユーザーが LOGIN ボタンLoginViewタップすると、SignInCommandクラス内LoginViewModelが実行され、メソッドがSignInAsync実行されます。 以下のコード例はこのメソッドを示しています。

private async Task SignInAsync()  
{  
    ...  
    LoginUrl = _identityService.CreateAuthorizationRequest();  
    IsLogin = true;  
    ...  
}

このメソッドは、次の CreateAuthorizationRequest コード例に示すように、クラス内のメソッド IdentityService を呼び出します。

public string CreateAuthorizationRequest()
{
    // Create URI to authorization endpoint
    var authorizeRequest = new AuthorizeRequest(GlobalSetting.Instance.IdentityEndpoint);

    // Dictionary with values for the authorize request
    var dic = new Dictionary<string, string>();
    dic.Add("client_id", GlobalSetting.Instance.ClientId);
    dic.Add("client_secret", GlobalSetting.Instance.ClientSecret); 
    dic.Add("response_type", "code id_token");
    dic.Add("scope", "openid profile basket orders locations marketing offline_access");
    dic.Add("redirect_uri", GlobalSetting.Instance.Callback);
    dic.Add("nonce", Guid.NewGuid().ToString("N"));
    dic.Add("code_challenge", CreateCodeChallenge());
    dic.Add("code_challenge_method", "S256");

    // Add CSRF token to protect against cross-site request forgery attacks.
    var currentCSRFToken = Guid.NewGuid().ToString("N");
    dic.Add("state", currentCSRFToken);

    var authorizeUri = authorizeRequest.Create(dic); 
    return authorizeUri;
}

このメソッドは、必要なパラメーターを使用して IdentityServer の承認エンドポイントURI を作成します。 承認エンドポイントは、ユーザー設定として公開される基本エンドポイントのポート 5105 上の /connect/authorize にあります。 ユーザー設定について詳しくは、「構成管理」をご覧ください。

Note

eShopOnContainers モバイル アプリの攻撃対象領域は、コード交換用 Proof Key (PKCE) 拡張機能を OAuth に実装することで減少します。 PKCE は、認証コードがインターセプトされた場合に使用されないように保護します。 これは、クライアントがシークレット検証子を生成し、そのハッシュが承認要求で渡され、承認コードを引き換えるときにハッシュされていない状態で提示されることによって、実現されます。 PKCE について詳しくは、Internet Engineering Task Force の Web サイトの「OAuth パブリック クライアントによる Proof Key for Code Exchange」をご覧ください。

返された URI は、LoginViewModel クラスの LoginUrl プロパティに格納されます。 プロパティがIsLogin表示されるとtrue、in がWebViewLoginView表示されます。 データWebViewは、そのSourceプロパティLoginUrlLoginUrlをクラスのプロパティにバインドします。これにより、プロパティが "Identity Server" 認証エンドポイントに設定されている場合に、"IdentityServer にサインイン" 要求が行われます。 LoginViewModel IdentityServer がこの要求を受け取り、ユーザーが認証されていない場合、 WebView 構成済みのログイン ページにリダイレクトされます(図 9-4 を参照)。

Login page displayed by the WebView

図 9-4: WebView によって表示されるログイン ページ

ログインが完了すると、WebView は戻り先 URI にリダイレクトされます。 この WebView のナビゲーションにより、次のコード例で示すように、LoginViewModel クラスの NavigateAsync メソッドが実行されます。

private async Task NavigateAsync(string url)  
{  
    ...  
    var authResponse = new AuthorizeResponse(url);  
    if (!string.IsNullOrWhiteSpace(authResponse.Code))  
    {  
        var userToken = await _identityService.GetTokenAsync(authResponse.Code);  
        string accessToken = userToken.AccessToken;  

        if (!string.IsNullOrWhiteSpace(accessToken))  
        {  
            Settings.AuthAccessToken = accessToken;  
            Settings.AuthIdToken = authResponse.IdentityToken;  

            await NavigationService.NavigateToAsync<MainViewModel>();  
            await NavigationService.RemoveLastFromBackStackAsync();  
        }  
    }  
    ...  
}

このメソッドは、戻り URI に含まれる認証応答を解析し、有効な承認コードが存在する場合は、IdentityServer の トークン エンドポイントに要求を行い、承認コード、PKCE シークレット検証ツール、およびその他の必要なパラメーターを渡します。 トークン エンドポイントは、ユーザー設定として公開される基本エンドポイントのポート 5105 上の /connect/token にあります。 ユーザー設定について詳しくは、「構成管理」をご覧ください。

ヒント

戻り URI を検証します。 eShopOnContainers モバイル アプリはリターン URI を検証しませんが、ベスト プラクティスは、リターン URI が既知の場所を参照していることを検証して、オープン リダイレクト攻撃を防ぐことです。

トークン エンドポイントは、有効な承認コードと PKCE シークレット検証子を受け取ると、アクセス トークン、ID トークン、更新トークンで応答します。 アクセス トークン (API リソースへのアクセスを許可する) と ID トークンがアプリケーション設定として格納され、ページ ナビゲーションが実行されます。 したがって、eShopOnContainers モバイル アプリの全体的な効果は次のとおりです。ユーザーが IdentityServer で正常に認証できる場合は、ページに MainView 移動します。これは、 TabbedPage 選択したタブとして表示 CatalogView されます。

ページのナビゲーションについては、「ナビゲーション」をご覧ください。 ナビゲーションによってビュー モデル メソッドが実行される方法WebViewについては、「ビヘイビアーを使用したナビゲーションの呼び出し」を参照してください。 アプリケーション設定の詳細については、「構成管理」を参照してください

Note

eShopOnContainers では、アプリでモック サービスを使用するように構成されている場合に、モック サインインも許可されます SettingsView。 このモードでは、アプリは IdentityServer と通信せず、代わりにユーザーが任意の資格情報を使用してサインインできるようにします。

サインアウト

ユーザーが [LOG OUT] ボタンProfileViewタップすると、LogoutCommandクラス内ProfileViewModelが実行され、メソッドがLogoutAsync実行されます。 このメソッドは、LoginView ページへのページ ナビゲーションを実行し、true に設定された LogoutParameter のインスタンスをパラメーターとして渡します。 ページ ナビゲーション中にパラメーターを渡す方法の詳細については、「ナビゲーション中にパラメーターを渡す」を参照してください

ビューが作成され、そこに移動すると、ビューに関連付けられているビュー モデルの InitializeAsync メソッドが実行され、LoginViewModel クラスの Logout メソッドが実行されます。次に示すのはそのコード例です。

private void Logout()  
{  
    var authIdToken = Settings.AuthIdToken;  
    var logoutRequest = _identityService.CreateLogoutRequest(authIdToken);  

    if (!string.IsNullOrEmpty(logoutRequest))  
    {  
        // Logout  
        LoginUrl = logoutRequest;  
    }  
    ...  
}

このメソッドは、IdentityService クラスの CreateLogoutRequest メソッドを呼び出し、アプリケーションの設定から取得した ID トークンをパラメーターとして渡します。 アプリケーション設定の詳細については、「構成管理」を参照してください。 次のコード例は、CreateLogoutRequest メソッドを示しています。

public string CreateLogoutRequest(string token)  
{  
    ...  
    return string.Format("{0}?id_token_hint={1}&post_logout_redirect_uri={2}",   
        GlobalSetting.Instance.LogoutEndpoint,  
        token,  
        GlobalSetting.Instance.LogoutCallback);  
}

このメソッドは、必要なパラメーターを使用して IdentityServer の エンド セッション エンドポイントへの URI を作成します。 セッション終了エンドポイントは、ユーザー設定として公開される基本エンドポイントのポート 5105 上の /connect/endsession にあります。 ユーザー設定について詳しくは、「構成管理」をご覧ください。

返された URI は、LoginViewModel クラスの LoginUrl プロパティに格納されます。 プロパティが IsLogin 表示されている true間は、in WebViewLoginView 表示されます。 データは WebView 、その Source プロパティを LoginUrl クラスの LoginViewModel プロパティにバインドするため、プロパティが IdentityServer のエンド セッション エンドポイントに設定されている場合 LoginUrl に IdentityServer にサインアウト要求を行います。 ユーザーがサインインしている場合、IdentityServer がこの要求を受信すると、サインアウトが発生します。 認証は、ASP.NET Core の Cookie 認証ミドルウェアによって管理される Cookie を使って追跡されます。 そのため、IdentityServer からサインアウトすると、認証 Cookie が削除され、ログアウト後のリダイレクト URI がクライアントに返されます。

モバイル アプリでは、 WebView ログアウト後のリダイレクト URI にリダイレクトされます。 この WebView のナビゲーションにより、次のコード例で示すように、LoginViewModel クラスの NavigateAsync メソッドが実行されます。

private async Task NavigateAsync(string url)  
{  
    ...  
    Settings.AuthAccessToken = string.Empty;  
    Settings.AuthIdToken = string.Empty;  
    IsLogin = false;  
    LoginUrl = _identityService.CreateAuthorizationRequest();  
    ...  
}

このメソッドは、ID トークンとアクセス トークンの両方をアプリケーション設定からクリアし、プロパティをIsLoginfalse設定します。これによりWebView、ページ上がLoginView非表示になります。 最後に、ユーザーが次にサインインを始めるときに備えて、LoginUrl プロパティには、必要なパラメーターを使って IdentityServer の承認エンドポイントの URI が設定されます。

ページのナビゲーションについては、「ナビゲーション」をご覧ください。 ナビゲーションによってビュー モデル メソッドが実行される方法WebViewについては、「ビヘイビアーを使用したナビゲーションの呼び出し」を参照してください。 アプリケーション設定の詳細については、「構成管理」を参照してください

Note

eShopOnContainers では、アプリが 設定View でモック サービスを使用するように構成されている場合に、モック サインアウトも許可されます。 このモードでは、アプリは IdentityServer と通信せず、アプリケーションの設定から格納されているトークンをクリアします。

承認

認証後、ASP.NET Core Web API は多くの場合、アクセスを承認する必要があります。これにより、サービスは認証された一部のユーザーが API を使用できるようになりますが、すべてではありません。

ASP.NET Core MVC ルートへのアクセスを制限するには、次のコード例に示すように、コントローラーまたはアクションに Authorize 属性を適用します。これによって、コントローラーまたはアクションへのアクセスが認証されたユーザーに制限されます。

[Authorize]  
public class BasketController : Controller  
{  
    ...  
}

未承認のユーザーが属性で Authorize マークされたコントローラーまたはアクションにアクセスしようとすると、MVC フレームワークは 401 (未承認) HTTP 状態コードを返します。

Note

属性にパラメーターを指定して、 Authorize API を特定のユーザーに制限できます。 詳細については、「承認」をご覧ください。

IdentityServer を承認ワークフローに統合し、それによって提供されるアクセス トークンで承認を制御することができます。 この方法を図 9-5 に示します。

Authorization by access token

図 9-5: アクセス トークンによる承認

eShopOnContainers モバイル アプリは、ID マイクロサービスと通信し、認証プロセスの一部としてアクセス トークンを要求します。 その後、アクセス トークンは、アクセス要求の一部として、注文マイクロサービスとバスケット マイクロサービスによって公開される API に転送されます。 アクセス トークンには、クライアントとユーザーに関する情報が含まれます。 その後、API はその情報を使ってデータへのアクセスを承認します。 API を保護するように IdentityServer を構成する方法については、「API リソースの構成」を参照してください

承認を実行するための IdentityServer の構成

IdentityServer で承認を実行するには、その承認ミドルウェアを Web アプリケーションの HTTP 要求パイプラインに追加する必要があります。 ミドルウェアは、メソッドからConfigure呼び出される Web アプリケーションのクラスのStartupメソッドに追加ConfigureAuthされ、eShopOnContainers 参照アプリケーションの次のコード例で示されています。

protected virtual void ConfigureAuth(IApplicationBuilder app)  
{  
    var identityUrl = Configuration.GetValue<string>("IdentityUrl");  
    app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions  
    {  
        Authority = identityUrl.ToString(),  
        ScopeName = "basket",  
        RequireHttpsMetadata = false  
    });  
} 

このメソッドを使うと、有効なアクセス トークンでのみ API にアクセスできることが保証されます。 ミドルウェアは、受信トークンを検証して、信頼された発行者から送信されていることを確認し、トークンを受信する API でトークンが使用できることを検証します。 したがって、注文コントローラーまたはバスケット コントローラーを参照すると、アクセス トークンが必要であることを示す 401 (未承認) HTTP 状態コードが返されます。

Note

app.UseMvc() または app.UseMvcWithDefaultRoute() で MVC を追加する前に、IdentityServer の承認ミドルウェアを Web アプリケーションの HTTP 要求パイプラインに追加する必要があります。

API へのアクセス要求の作成

注文マイクロサービスとバスケット マイクロサービスに要求を行うときは、次のコード例に示すように、認証プロセス中に IdentityServer から取得したアクセス トークンを要求に含める必要があります。

var authToken = Settings.AuthAccessToken;  
Order = await _ordersService.GetOrderAsync(Convert.ToInt32(order.OrderNumber), authToken);

アクセス トークンはアプリケーション設定として格納され、プラットフォーム固有のストレージから取得され、クラス内のメソッドの呼び出しにGetOrderAsyncOrderService含まれます。

同様に、次のコードのように、IdentityServer で保護された API にデータを送信するときも、アクセス トークンを含める必要があります。

var authToken = Settings.AuthAccessToken;  
await _basketService.UpdateBasketAsync(new CustomerBasket  
{  
    BuyerId = userInfo.UserId,   
    Items = BasketItems.ToList()  
}, authToken);

アクセス トークンはプラットフォーム固有のストレージから取得され、クラス内のメソッドの UpdateBasketAsync 呼び出しに BasketService 含まれます。

eShopOnContainers モバイル アプリのクラスは RequestProvider 、このクラスを HttpClient 使用して、eShopOnContainers 参照アプリケーションによって公開される RESTful API に要求を行います。 承認が必要な注文 API とバスケット API に要求を行うときは、有効なアクセス トークンを要求に含める必要があります。 これは、次のコード例に示すように、インスタンスの HttpClient ヘッダーにアクセス トークンを追加することによって実現されます。

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

各要求で送信されるヘッダーは HttpClient クラスの DefaultRequestHeaders プロパティで公開されており、アクセス トークンは文字列 Authorization を前に付けて Bearer ヘッダーに追加されます。 要求が RESTful API に送信されると、ヘッダーの Authorization 値が抽出されて検証され、信頼された発行者から送信されることを確認し、それを受け取る API を呼び出すアクセス許可をユーザーが持っているかどうかを判断するために使用されます。

eShopOnContainers モバイル アプリが Web 要求を行う方法の詳細については、「リモート データへのアクセス」を参照してください

まとめ

認証と承認を、ASP.NET MVC Web アプリケーションと通信するアプリに Xamarin.Forms 統合するには、多くの方法があります。 eShopOnContainers モバイル アプリは、IdentityServer 4 を使用するコンテナー化された ID マイクロサービスで認証と承認を実行します。 IdentityServer は、ASP.NET Core Identity と統合してベアラー トークン認証を実行する ASP.NET Core 用の、オープンソースの OpenID Connect および OAuth 2.0 フレームワークです。

モバイル アプリは、ユーザーの認証またはリソースへのアクセスのために、IdentityServer にセキュリティ トークンを要求します。 リソースにアクセスするときは、承認を必要とする API への要求にアクセス トークンを含める必要があります。 IdentityServer のミドルウェアは、受信アクセス トークンを検証して、信頼された発行者から送信されていること、および受信する API で使用することが有効であることを確認します。