ヒント
この内容は電子ブック『.NET MAUI を使用したエンタープライズ アプリケーション パターン』からの抜粋です。これは .NET Docs で閲覧することも、無料の PDF をダウンロードしてオフラインで読むこともできます。
認証とは、名前とパスワードなどの ID 資格情報をユーザーから取得し、その資格情報を機関に対して検証するプロセスです。 資格情報が有効な場合、資格情報を送信したエンティティは認証済みの ID と見なされます。 ID が確立された後は、承認プロセスによって、その ID に特定のリソースへのアクセス権があるかどうかが判断されます。
ASP.NET Web アプリケーションと通信する .NET MAUI アプリに認証と承認を統合するには、ASP.NET Core Identity、外部認証プロバイダー (Microsoft、Google、Facebook、Twitter など)、認証ミドルウェアの使用など、多数の方法があります。 eShop マルチプラットフォーム アプリは、IdentityServer を使用するコンテナー化された ID マイクロサービスで、認証と認可を実行します。 アプリは、ユーザーの認証またはリソースへのアクセスを行うためのセキュリティ トークンを IdentityServer に要求します。 IdentityServer がユーザーの代わりにトークンを発行するには、ユーザーが IdentityServer にサインインする必要があります。 ただし、IdentityServer は、認証用のユーザー インターフェイスまたはデータベースを備えていません。 したがって、eShop 参照アプリケーションでは、ASP.NET Core ID をこの目的に使います。
認証
アプリケーションが現在のユーザーの ID 知る必要がある場合は、認証が必要です。 ユーザーを識別するための ASP.NET Core の主要なメカニズムは、開発者が構成したデータ ストアにユーザー情報を格納する ASP.NET Core Identity メンバーシップ システムです。 通常、このデータ ストアは EntityFramework ストアですが、カスタム ストアまたはサード パーティのパッケージを使って、Azure Storage、DocumentDB、またはその他の場所に ID 情報を格納できます。
ローカル ユーザーのデータストアを利用したり、Cookie を使って要求間で ID 情報を保持したりする認証シナリオ (ASP.NET Web アプリケーションでは一般的) では、ASP.NET Core Identity が適切なソリューションです。 ただし、Cookie は、データを保持して送信する自然な手段とは限りません。 たとえば、アプリからアクセスされる RESTful エンドポイントを公開する ASP.NET Core Web アプリケーションでは、通常、このシナリオでは Cookie を使えないため、ベアラー トークン認証を使う必要があります。 ただし、ベアラー トークンは簡単に取得し、アプリから行われる Web 要求の承認ヘッダーに含めることができます。
IdentityServer を使用したベアラー トークンの発行
IdentityServer は、ASP.NET Core 用のオープンソースの OpenID Connect および OAuth 2.0 フレームワークであり、ASP.NET Core Identity のローカル ユーザーに対するセキュリティ トークンの発行など、多くの認証と認可のシナリオで使用できます。
注
OpenID Connect と OAuth 2.0 は非常に似ていますが、役割は異なります。
OpenID Connect は、OAuth 2.0 プロトコルの上位の認証レイヤーです。 OAuth 2 は、アプリケーションがセキュリティ トークン サービスにアクセス トークンを要求し、それらを使って API と通信できるようにするプロトコルです。 この委任により、認証と承認を一元化できるため、クライアント アプリケーションと API 両方の複雑さが軽減されます。
OpenID Connect と OAuth 2.0 は、認証と API アクセスという 2 つの基本的なセキュリティ上の問題を組み合わせたものであり、IdentityServer はこれらのプロトコルの実装です。
eShop 参照アプリケーションのように、クライアントからマイクロサービスへの直接通信を使うアプリケーションでは、次の図に示すように、セキュリティ トークン サービス (STS) として機能する専用の認証マイクロサービスを使って、ユーザーを認証できます。 クライアントとマイクロサービスの直接通信について詳しくは、「マイクロサービス」をご覧ください。
eShop のマルチプラットフォーム アプリは、IdentityServer を使用して認証を実行する ID マイクロサービスおよび API のアクセス制御と通信します。 したがって、このマルチプラットフォーム アプリは、ユーザーの認証またはリソースへのアクセスのため、IdentityServer にトークンを要求します。
- IdentityServer でのユーザーの認証は、ID トークンを要求するマルチプラットフォーム アプリによって実行され、認証プロセスの結果が示されます。 少なくとも、それにはユーザーの識別子と、ユーザーが認証される方法とタイミングに関する情報が含まれます。 また、追加の ID データが含まれる場合もあります。
- IdentityServer でのリソースへのアクセスは、"アクセス トークン" を要求するマルチプラットフォーム アプリによって実行され、API リソースへのアクセスが許可されます。 クライアントはアクセス トークンを要求して、API にそれを転送します。 アクセス トークンには、クライアントとユーザーに関する情報が含まれます (存在する場合)。 その後、API はその情報を使ってデータへのアクセスを承認します。
注
トークンの要求が成功するには、事前にクライアントを IdentityServer に登録する必要があります。 クライアントの追加について詳しくは、「クライアントの定義」をご覧ください。
Web アプリケーションへの IdentityServer の追加
ASP.NET Core Web アプリケーションで IdentityServer を使用するには、それを Web アプリケーションの Visual Studio ソリューションに追加する必要があります。 詳しくは、IdentityServer のドキュメントのセットアップと概要に関する説明をご覧ください。
IdentityServer が Web アプリケーションの Visual Studio ソリューションに含まれるようになったら、OpenID Connect と OAuth 2.0 のエンドポイントへの要求を処理するため、HTTP 要求処理パイプラインにそれを追加する必要があります。 これは、次のコード例に示すように、Identity.API プロジェクトの Program.cs で構成されます。
...
app.UseIdentityServer();
Web アプリケーションの HTTP 要求処理パイプラインでは順序が重要です。 そのため、IdentityServer は、ログイン画面を実装する UI フレームワークの前のパイプラインに追加する必要があります。
IdentityServer の構成
IdentityServer は、eShop 参照アプリケーションからの以下のコード例に示すように、Identity.API メソッドを呼び出すことによって、 プロジェクトの AddIdentityServer で構成されます。
builder.Services.AddIdentityServer(options =>
{
options.Authentication.CookieLifetime = TimeSpan.FromHours(2);
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
// TODO: Remove this line in production.
options.KeyManagement.Enabled = false;
})
.AddInMemoryIdentityResources(Config.GetResources())
.AddInMemoryApiScopes(Config.GetApiScopes())
.AddInMemoryApiResources(Config.GetApis())
.AddInMemoryClients(Config.GetClients(builder.Configuration))
.AddAspNetIdentity<ApplicationUser>()
// TODO: Not recommended for production - you need to store your key material somewhere secure
.AddDeveloperSigningCredential();
services.AddIdentityServer メソッドを呼び出した後、追加の Fluent API を呼び出して次の構成を行います。
- 署名に使われる資格情報。
- ユーザーがアクセスを要求する可能性がある API と ID リソース。
- トークンを要求するために接続するクライアント。
- ASP.NET Core Identity。
ヒント
IdentityServer の構成を動的に読み込みます。 IdentityServer の API を使用すると、構成オブジェクトのメモリ内リストから IdentityServer を構成できます。 eShop 参照アプリケーションでは、これらのメモリ内コレクションはアプリケーションにハードコーディングされています。 ただし、運用シナリオでは、構成ファイルまたはデータベースから動的に読み込むことができます。
ASP.NET Core Identity を使うように IdentityServer を構成する方法については、IdentityServer のドキュメントの「ASP.NET Core Identity の使用」をご覧ください。
API リソースの構成
API リソースを構成するとき、AddInMemoryApiResources メソッドは IEnumerable<ApiResource> コレクションを必要とします。 次に示すコード例は、eShop 参照アプリケーションでこのコレクションを提供する GetApis メソッドです。
public static IEnumerable<ApiResource> GetApis()
{
return new List<ApiResource>
{
new ApiScope("orders", "Orders Service"),
new ApiScope("basket", "Basket Service"),
new ApiScope("webhooks", "Webhooks registration Service"),
};
}
このメソッドでは、IdentityServer が orders API と basket API を保護する必要があることが指定されています。 そのため、これらの API を呼び出すときは、IdentityServer で管理されるアクセス トークンが必要になります。
ApiResource の詳細については、IdentityServer のドキュメントの「API リソース」を参照してください。
ID リソースの構成
ID リソースを構成するとき、AddInMemoryIdentityResources メソッドは IEnumerable<IdentityResource> コレクションを必要とします。 ID リソースは、ユーザー ID、名前、メール アドレスなどのデータです。 各 ID リソースには一意の名前があり、それには任意のクレームの種類を割り当てることができ、それはユーザーの ID トークンに組み込まれます。 次に示すコード例は、eShop 参照アプリケーションでこのコレクションを提供する GetResources メソッドです。
public static IEnumerable<IdentityResource> GetResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};
}
OpenID Connect の仕様では、いくつかの標準 ID リソースが指定されています。 最小要件は、ユーザーに一意の ID を生成するためのサポートが提供されていることです。 これは、IdentityResources.OpenId ID リソースを公開することによって実現されます。
注
IdentityResources クラスは、OpenID Connect の仕様で定義されているすべてのスコープ (OpenID、メール、プロファイル、電話、アドレス) がサポートされます。
IdentityServer では、カスタム ID リソースの定義もサポートされています。 詳しくは、IdentityServer のドキュメントのカスタム ID リソースの定義に関する説明をご覧ください。 IdentityResource 型の詳細については、IdentityServer のドキュメントの「ID リソース」を参照してください。
クライアントの構成
クライアントは、IdentityServer にトークンを要求できるアプリケーションです。 通常、少なくとも次の設定がクライアントごとに定義されている必要があります。
- 一意のクライアント ID。
- トークン サービスとの許可される相互作用 (許可の種類と呼ばれます)。
- ID トークンとアクセス トークンの送信先の場所 (リダイレクト URI と呼ばれます)。
- クライアントがアクセスを許可されているリソースのリスト (スコープと呼ばれます)。
クライアントを構成するとき、AddInMemoryClients メソッドは IEnumerable<Client> コレクションを必要とします。 次に示すコード例は、eShop 参照アプリケーションでこのコレクションを提供する GetClients メソッドでの eShop マルチプラットフォーム アプリの構成です。
public static IEnumerable<Client> GetClients(Dictionary<string,string> clientsUrl)
{
return new List<Client>
{
// Omitted for brevity
new Client
{
ClientId = "maui",
ClientName = "eShop MAUI OpenId Client",
AllowedGrantTypes = GrantTypes.Code,
//Used to retrieve the access token on the back channel.
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { configuration["MauiCallback"] },
RequireConsent = false,
RequirePkce = true,
PostLogoutRedirectUris = { $"{configuration["MauiCallback"]}/Account/Redirecting" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess,
"orders",
"basket",
"mobileshoppingagg",
"webhooks"
},
//Allow requesting refresh tokens for long lived API access
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true,
AlwaysIncludeUserClaimsInIdToken = true,
AccessTokenLifetime = 60 * 60 * 2, // 2 hours
IdentityTokenLifetime = 60 * 60 * 2 // 2 hours
}
};
}
この構成では、次のプロパティのデータを指定しています。
| プロパティ | 説明 |
|---|---|
ClientId |
クライアントの一意の ID。 |
ClientName |
クライアントの表示名。ログと同意画面に使用されます。 |
AllowedGrantTypes |
クライアントが IdentityServer と対話する方法を指定します。 詳しくは、「認証フローの構成」をご覧ください。 |
ClientSecrets |
トークン エンドポイントにトークンを要求するときに使われるクライアント シークレット資格情報を指定します。 |
RedirectUris |
トークンまたは承認コードを返す先の許可された URI を指定します。 |
RequireConsent |
同意画面が必要かどうかを指定します。 |
RequirePkce |
承認コードを使用するクライアントが証明キーを送信する必要があるかどうかを指定します。 |
PostLogoutRedirectUris |
ログアウト後にリダイレクトする先の許可された URI を指定します。 |
AllowedCorsOrigins |
IdentityServer が呼び出し元からのクロスオリジン呼び出しを許可できるように、クライアントの呼び出し元を指定します。 |
AllowedScopes |
クライアントがアクセス権を持っているリソースを指定します。 既定では、クライアントはどのリソースに対するアクセス権も持っていません。 |
AllowOfflineAccess |
クライアントが更新トークンを要求できるかどうかを指定します。 |
AllowAccessTokensViaBrowser |
クライアントがブラウザー ウィンドウからアクセス トークンを受け取ることができるかどうかを指定します。 |
AlwaysIncludeUserClaimsInIdToken |
ユーザー要求が常に ID トークンに追加されることを指定します。 既定では、これらは userinfo エンドポイントを使用して取得する必要があります。 |
AccessTokenLifetime |
アクセス トークンの有効期間 (秒) を指定します。 |
IdentityTokenLifetime |
ID トークンの有効期間 (秒) を指定します。 |
認証フローの構成
クライアントと IdentityServer の間の認証フローは、Client.AllowedGrantTypes プロパティで許可の種類を指定することにより構成できます。 OpenID Connect と OAuth 2.0 の仕様では、次のようないくつかの認証フローが定義されています。
| 認証フロー | 説明 |
|---|---|
| 暗黙 | このフローはブラウザー ベースのアプリケーションに最適化されており、ユーザー認証専用または認証とアクセス トークン要求に使用する必要があります。 すべてのトークンはブラウザー経由で送信されるため、更新トークンなどの高度な機能は許可されません。 |
| Authorization code (承認コード) | このフローでは、ブラウザー フロント チャネルとは異なり、バック チャネルでトークンを取得でき、クライアント認証をサポートする機能も提供されます。 |
| ハイブリッド | このフローは、暗黙的な種類と、承認コード許可の種類の組み合わせです。 ID トークンはブラウザー チャネル経由で送信され、署名されたプロトコル応答と、承認コードなどの他の成果物が含まれます。 応答を正常に検証した後は、バック チャネルを使ってアクセス トークンと更新トークンを取得する必要があります。 |
ヒント
ハイブリッド認証フローの使用を検討してください。 ハイブリッド認証フローは、ブラウザー チャネルに対して行われる多くの攻撃を軽減し、アクセス トークン (および場合によっては更新トークン) を取得するネイティブ アプリケーションに推奨されるフローです。
認証フローの詳細については、IdentityServer のドキュメントの「許可の種類」を参照してください。
認証の実行
IdentityServer がユーザーの代わりにトークンを発行するには、ユーザーが IdentityServer にサインインする必要があります。 ただし、IdentityServer は、認証用のユーザー インターフェイスまたはデータベースを備えていません。 したがって、eShop 参照アプリケーションでは、ASP.NET Core ID をこの目的に使います。
eShop マルチプラットフォーム アプリは、ハイブリッド認証フローを使って IdentityServer で認証を行います。次の図はこれを示したものです。
<base endpoint>:5105/connect/authorize に対してサインイン要求が行われます。 認証が成功すると、IdentityServer は認証コードと ID トークンを含む認証応答を返します。 承認コードを送信された <base endpoint>:5105/connect/token は、アクセス トークン、ID トークン、更新トークンで応答します。
eShop マルチプラットフォーム アプリは、追加のパラメーターを指定して <base endpoint>:5105/connect/endsession に要求を送信することで、IdentityServer からサインアウトします。 サインアウトの後、IdentityServer は、ログアウト後のリダイレクト URI をマルチプラットフォーム アプリに送り返すことで応答します。 次の図はこのプロセスを示したものです。
eShop マルチプラットフォーム アプリでは、IdentityServer との通信は、IdentityService インターフェイスを実装する IIdentityService クラスによって実行されます。 このインターフェイスでは、実装するクラスは SignInAsync、SignOutAsync、GetUserInfoAsync、GetAuthTokenAsync メソッドを提供する必要があることが指定されています。
サインイン
ユーザーが LOGIN の LoginView ボタンをタップすると、SignInCommand クラスの LoginViewModel が実行され、それにより SignInAsync メソッドが実行されます。 以下のコード例はこのメソッドを示しています。
[RelayCommand]
private async Task SignInAsync()
{
await IsBusyFor(
async () =>
{
var loginSuccess = await _appEnvironmentService.IdentityService.SignInAsync();
if (loginSuccess)
{
await NavigationService.NavigateToAsync("//Main/Catalog");
}
});
}
このメソッドは、次のコード例で示すように、SignInAsync クラスの IdentityService メソッドを呼び出します。
public async Task<bool> SignInAsync()
{
var response = await GetClient().LoginAsync(new LoginRequest()).ConfigureAwait(false);
if (response.IsError)
{
return false;
}
await _settingsService
.SetUserTokenAsync(
new UserToken
{
AccessToken = response.AccessToken,
IdToken = response.IdentityToken,
RefreshToken = response.RefreshToken,
ExpiresAt = response.AccessTokenExpiration
})
.ConfigureAwait(false);
return !response.IsError;
}
IdentityService は、OidcClient NuGet パッケージで提供される IdentityModel.OidcClient を利用します。 このクライアントは、アプリケーション内のユーザーに認証 Web ビューを表示し、認証結果をキャプチャします。 クライアントは、必要なパラメーターを使用して、IdentityServer の承認エンドポイントの URI に接続します。 承認エンドポイントは、ユーザー設定として公開される基本エンドポイントのポート 5105 上の /connect/authorize にあります。 ユーザー設定について詳しくは、「構成管理」をご覧ください。
注
eShop マルチプラットフォーム アプリの攻撃面は、Proof Key for Code Exchange (PKCE) 拡張機能を OAuth に実装することで軽減されます。 PKCE は、インターセプトされた認証コードが使われないように保護します。 これは、クライアントがシークレット検証子を生成し、そのハッシュが承認要求で渡され、承認コードを引き換えるときにハッシュされていない状態で提示されることによって、実現されます。 PKCE について詳しくは、Internet Engineering Task Force の Web サイトの「OAuth パブリック クライアントによる Proof Key for Code Exchange」をご覧ください。
トークン エンドポイントは、有効な認証情報、認証コード、PKCE シークレット検証子を受け取ると、アクセス トークン、ID トークン、更新トークンで応答します。 アクセス トークン (API リソースへのアクセスを許可する) と ID トークンはアプリケーションの設定として格納され、ページ ナビゲーションが実行されます。 そのため、eShop マルチプラットフォーム アプリでの全体的な影響は次のようになります。ユーザーが IdentityServer で正常に認証できる場合、ユーザーは //Main/Catalog ルートにナビゲートされ、それは選択されたタブとして TabbedPage を表示する CatalogView です。
ページのナビゲーションについては、「ナビゲーション」をご覧ください。 WebView のナビゲーションによってビュー モデルのメソッドがどのように実行されるのかについては、「ビヘイビアーを使用したナビゲーションの呼び出し」をご覧ください。 アプリケーションの設定については、「構成管理」をご覧ください。
注
SettingsView でモック サービスを使うようにアプリが構成されている場合、eShop はモック サインインも許可します。 このモードでは、アプリは IdentityServer と通信せず、代わりにユーザーが任意の資格情報を使用してサインインするのを許可します。
サインアウト
ユーザーが LOG OUT の ProfileView ボタンをタップすると、LogoutCommand クラスの ProfileViewModel が実行され、それにより LogoutAsync メソッドが実行されます。 このメソッドは、LoginView に設定された Logout のクエリ パラメーターを渡して、true ページへのページ ナビゲーションを実行します。
そのパラメーターは ApplyQueryAttributes メソッドで評価されます。
Logout パラメーターに true 値が指定されている場合は、PerformLogoutAsync クラスの LoginViewModel メソッドが実行されます。次のコード例を参照してください。
private async Task PerformLogoutAsync()
{
await _appEnvironmentService.IdentityService.SignOutAsync();
_settingsService.UseFakeLocation = false;
UserName.Value = string.Empty;
Password.Value = string.Empty;
}
このメソッドは、SignOutAsync クラスの IdentityService メソッドを呼び出します。これにより、OidcClient が呼び出されてユーザーのセッションが終了し、保存されていたユーザー トークンがクリアされます。 アプリケーションの設定について詳しくは、「構成管理」をご覧ください。 次のコード例は、SignOutAsync メソッドを示しています。
public async Task<bool> SignOutAsync()
{
var response = await GetClient().LogoutAsync(new LogoutRequest()).ConfigureAwait(false);
if (response.IsError)
{
return false;
}
await _settingsService.SetUserTokenAsync(default);
return !response.IsError;
}
このメソッドは、OidcClient を使用して、必要なパラメーターを使用して IdentityServer のセッション終了エンドポイントへの URI を呼び出します。 セッション終了エンドポイントは、ユーザー設定として公開される基本エンドポイントのポート 5105 上の /connect/endsession にあります。 ユーザーが正常にサインアウトすると、ユーザーに LoginView が表示され、保存されたユーザー情報がクリアされます。
ページのナビゲーションについては、「ナビゲーション」をご覧ください。
WebView のナビゲーションによってビュー モデルのメソッドがどのように実行されるのかについては、「ビヘイビアーを使用したナビゲーションの呼び出し」をご覧ください。 アプリケーションの設定については、「構成管理」をご覧ください。
注
SettingsView でモック サービスを使うようにアプリが構成されている場合、eShop はモック サインアウトも許可します。 このモードでは、アプリは IdentityServer と通信せず、アプリケーションの設定から格納されているトークンをクリアします。
承認
認証の後、ASP.NET Core Web API は多くの場合、アクセスを承認する必要があります。これにより、一部の認証されたユーザーはサービスで API を使用できるようになりますが、すべてのユーザーではありません。
ASP.NET Core ルートへのアクセスを制限するには、次のコード例で示すように、コントローラーまたはアクションに Authorize 属性を適用します。これにより、コントローラーまたはアクションへのアクセスが、認証されたユーザーに制限されます。
[Authorize]
public sealed class BasketController : Controller
{
// Omitted for brevity
}
承認されていないユーザーが Authorize 属性でマークされたコントローラーまたはアクションにアクセスしようとすると、API フレームワークは HTTP ステータス コード 401 (unauthorized) を返します。
注
Authorize 属性でパラメーターを指定して、特定のユーザーに API を制限できます。 詳しくは、ASP.NET Core のドキュメントの承認に関する記事をご覧ください。
IdentityServer を認可ワークフローに統合し、それによって提供されるアクセス トークンで認可を制御することができます。 次の図はこの方法を示したものです。
eShop マルチプラットフォーム アプリは、ID マイクロサービスと通信し、認証プロセスの一部としてアクセス トークンを要求します。 その後、アクセス トークンは、アクセス要求の一部として、注文マイクロサービスとバスケット マイクロサービスによって公開される API に転送されます。 アクセス トークンには、クライアントとユーザーに関する情報が含まれます。 その後、API はその情報を使ってデータへのアクセスを承認します。 API を保護するように IdentityServer を構成する方法については、「API リソースの構成」をご覧ください。
承認を実行するように IdentityServer を構成する
IdentityServer で承認を実行するには、その承認ミドルウェアを Web アプリケーションの HTTP 要求パイプラインに追加する必要があります。 そのミドルウェアは、AddDefaultAuthentication 拡張メソッドに追加されます。これは、AddApplicationServices クラスの Program メソッドから呼び出されるもので、eShop 参照アプリケーションの次のコード例は、これを示しています。
public static IServiceCollection AddDefaultAuthentication(this IHostApplicationBuilder builder)
{
var services = builder.Services;
var configuration = builder.Configuration;
var identitySection = configuration.GetSection("Identity");
if (!identitySection.Exists())
{
// No identity section, so no authentication
return services;
}
// prevent from mapping "sub" claim to nameidentifier.
JsonWebTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
services.AddAuthentication().AddJwtBearer(options =>
{
var identityUrl = identitySection.GetRequiredValue("Url");
var audience = identitySection.GetRequiredValue("Audience");
options.Authority = identityUrl;
options.RequireHttpsMetadata = false;
options.Audience = audience;
options.TokenValidationParameters.ValidIssuers = [identityUrl];
options.TokenValidationParameters.ValidateAudience = false;
});
services.AddAuthorization();
return services;
}
このメソッドを使うと、有効なアクセス トークンでのみ API にアクセスできることが保証されます。 ミドルウェアは、受信したトークンを検証して、それが信頼された発行元から送信されていることを確認し、トークンを受け取った API でそれを使用できることを検証します。 したがって、注文またはバスケット コントローラーを参照すると、アクセス トークンが必要であることを示す HTTP 状態コード 401 (unauthorized) が返されます。
API にアクセス要求を行う
注文およびバスケット マイクロサービスに要求を行うときは、次のコード例に示すように、認証プロセスの間に IdentityServer から取得したアクセス トークンを、要求に含める必要があります。
public async Task CreateOrderAsync(Models.Orders.Order newOrder)
{
var authToken = await _identityService.GetAuthTokenAsync().ConfigureAwait(false);
if (string.IsNullOrEmpty(authToken))
{
return;
}
var uri = $"{UriHelper.CombineUri(_settingsService.GatewayOrdersEndpointBase, ApiUrlBase)}?api-version=1.0";
var success = await _requestProvider.PostAsync(uri, newOrder, authToken, "x-requestid").ConfigureAwait(false);
}
アクセス トークンは IIdentityService 実装と共に格納され、GetAuthTokenAsync メソッドを使用して取得できます。
同様に、次のコードのように、IdentityServer で保護された API にデータを送信するときも、アクセス トークンを含める必要があります。
public async Task ClearBasketAsync()
{
var authToken = await _identityService.GetAuthTokenAsync().ConfigureAwait(false);
if (string.IsNullOrEmpty(authToken))
{
return;
}
await GetBasketClient().DeleteBasketAsync(new DeleteBasketRequest(), CreateAuthenticationHeaders(authToken))
.ConfigureAwait(false);
}
アクセス トークンは IIdentityService から取得され、ClearBasketAsync クラスの BasketService メソッドの呼び出しに追加されます。
eShop マルチプラットフォーム アプリの RequestProvider クラスは、HttpClient クラスを使って、eShop 参照アプリケーションによって公開されている RESTful API への要求を行います。 承認が必要な注文 API とバスケット API に要求を行うときは、有効なアクセス トークンを要求に含める必要があります。 これは、次のコード例で示すように、HttpClient インスタンスのヘッダーにアクセス トークンを追加することで実現されます。
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
各要求で送信されるヘッダーは DefaultRequestHeaders クラスの HttpClient プロパティで公開されており、アクセス トークンは文字列 Authorization を前に付けて Bearer ヘッダーに追加されます。 要求が RESTful API に送信されると、Authorization ヘッダーの値が抽出されて、それが信頼された発行者から送信されていることを確認するために検証され、それを受信した API を呼び出すアクセス許可がユーザーにあるかどうかを判断するために使われます。
eShop マルチプラットフォーム アプリが Web 要求を行う方法の詳細については、「リモート データへのアクセス」を参照してください。
まとめ
ASP.NET Web アプリケーションと通信する .NET MAUI アプリに認証と承認を統合するには、多くの方法があります。 eShop マルチプラットフォーム アプリは、IdentityServer を使用するコンテナー化された ID マイクロサービスで、認証と認可を実行します。 IdentityServer は、ASP.NET Core Identity と統合してベアラー トークン認証を実行する ASP.NET Core 用の、オープンソースの OpenID Connect および OAuth 2.0 フレームワークです。
このマルチプラットフォーム アプリは、ユーザーの認証またはリソースへのアクセスを行うためのセキュリティ トークンを IdentityServer に要求します。 リソースにアクセスするときは、承認を必要とする API への要求にアクセス トークンを含める必要があります。 IdentityServer のミドルウェアは、受信したアクセス トークンを検証し、それらが信頼された発行元から送信されていること、およびそれらを受け取った API で使用できることを確認します。
.NET