Azure Active Directory B2C を使用して、ASP.NET Core Blazor WebAssembly スタンドアロン アプリをセキュリティで保護する
この記事では、認証用に Azure Active Directory (AAD) B2C を使用するスタンドアロン Blazor WebAssembly アプリを作成する方法について説明します。
テナントを作成するか、AAD B2C テナントの作成 (Azure ドキュメント) に関する記事に記載されているガイダンスに従って Azure portal で使用するアプリの既存の B2C テナントを選択します。 使用するテナントを作成または特定した直後に、この記事に戻ります。
次の情報を記録しておきます。
- AAD B2C インスタンス (例: 末尾にスラッシュが含まれている
https://contoso.b2clogin.com/
):インスタンスは、Azure B2C アプリの登録のスキームとホストです。これは、Azure portal で [アプリの登録] ページから [エンドポイント] ウィンドウを開くことによって見つけることができます。 - AAD B2C プライマリ、パブリッシャー、テナント ドメイン (
contoso.onmicrosoft.com
など):ドメインは、Azure portal で登録されているアプリに対する [ブランド] ブレードの [パブリッシャー ドメイン] として使用できます。
AAD B2C アプリを登録します。
- Azure portal で [Azure Active Directory] に移動します。 サイドバーで [アプリの登録] を選択します。 [新規登録] ボタンを選択します。
- アプリの名前を指定します (例: Blazor スタンドアロン AAD B2C)。
- [サポートされているアカウントの種類] で、マルチテナント オプションを選択します: [任意の組織ディレクトリ内のアカウントまたは任意の ID プロバイダー。Azure AD B2C でユーザーを認証します。]
- [リダイレクト URI] ドロップダウンを [シングルページ アプリケーション (SPA)] に設定し、次のリダイレクト URI を指定します:
https://localhost:{PORT}/authentication/login-callback
。 Kestrel で実行されているアプリの既定のポートは 5001 です。 アプリが別の Kestrel ポートで実行されている場合は、アプリのポートを使用します。 IIS Express の場合、アプリのランダムに生成されたポートは、 [デバッグ] パネルのアプリのプロパティで確認できます。 この時点ではアプリは存在せず、IIS Express ポートは不明であるため、アプリが作成された後にこの手順に戻り、リダイレクト URI を更新してください。 このトピックの後半で、IIS Express ユーザーにリダイレクト URI を更新するよう促す注意が表示されます。 - 未確認の発行元ドメインを使用している場合は、 [アクセス許可]>[openid と offline_access アクセス許可に対して管理者の同意を付与します] が選択されていることを確認します。 発行元ドメインが検証済みの場合、このチェックボックスは表示されません。
- [登録] を選択します。
アプリケーション (クライアント) ID を記録しておきます (例: 41451fa7-82d9-4673-8fa5-69eff5a761fd
)。
[認証]>[プラットフォーム構成]>[シングルページ アプリケーション (SPA)] で次のようにします。
- [リダイレクト URI] が
https://localhost:{PORT}/authentication/login-callback
であることを確認します。 - [暗黙の付与] セクションで、[アクセス トークン] と [ID トークン] のチェックボックスが選択されていないことを確認します。
- アプリの残りの既定値は、このエクスペリエンスで使用可能です。
- [保存] ボタンを選択します。
Home>[Azure AD B2C]>[ユーザー フロー] で、次の操作を行います。
少なくとも、 [アプリケーション要求]>[表示名] ユーザー属性を選択して、LoginDisplay
コンポーネント (Shared/LoginDisplay.razor
) に context.User.Identity.Name
を設定します。
アプリ用に作成されたサインアップおよびサインイン ユーザーフロー名を記録しておきます (例: B2C_1_signupsignin
)。
空のフォルダーで、次のコマンドのプレースホルダーを、前に記録した情報に置き換え、コマンド シェルでこのコマンドを実行します。
dotnet new blazorwasm -au IndividualB2C --aad-b2c-instance "{AAD B2C INSTANCE}" --client-id "{CLIENT ID}" --domain "{TENANT DOMAIN}" -o {APP NAME} -ssp "{SIGN UP OR SIGN IN POLICY}"
プレースホルダー | Azure portal での名前 | 例 |
---|---|---|
{AAD B2C INSTANCE} |
インスタンス | https://contoso.b2clogin.com/ (末尾のスラッシュを含む) |
{APP NAME} |
— | BlazorSample |
{CLIENT ID} |
アプリケーション (クライアント) ID | 41451fa7-82d9-4673-8fa5-69eff5a761fd |
{SIGN UP OR SIGN IN POLICY} |
サインアップまたはサインインのユーザー フロー | B2C_1_signupsignin1 |
{TENANT DOMAIN} |
プライマリ、パブリッシャー、テナント ドメイン | contoso.onmicrosoft.com |
-o|--output
オプションで指定した出力場所にプロジェクト フォルダーが存在しない場合は作成されて、アプリの名前の一部になります。
Note
Azure portal では、アプリのプラットフォーム構成の [リダイレクト URI] は、既定の設定の Kestrel サーバーで実行されるアプリの場合、ポート 5001 に構成されます。
アプリがランダム IIS Express ポートで実行されている場合、アプリのポートは [デバッグ] パネルのアプリのプロパティで確認できます。
ポートがアプリの既知のポートで事前に構成されていない場合は、Azure portal でアプリの登録に戻り、正しいポートでリダイレクト URI を更新します。
openid
と offline_access
DefaultAccessTokenScopes 用の MsalProviderOptions を組みで追加します。
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.DefaultAccessTokenScopes.Add("openid");
options.ProviderOptions.DefaultAccessTokenScopes.Add("offline_access");
});
アプリを作成すると、次のことができるようになります。
- AAD ユーザー アカウントを使用してアプリにログインする。
- Microsoft API のアクセス トークンを要求する。 詳細については次を参照してください:
認証パッケージ
個人の B2C アカウント (IndividualB2C
) を使用するようにアプリを作成すると、そのアプリで Microsoft Authentication Library (Microsoft.Authentication.WebAssembly.Msal
) のパッケージ参照を自動的に受け取ります。 このパッケージには、アプリでユーザーを認証し、保護された API を呼び出すためのトークンを取得するのに役立つ一連のプリミティブが用意されています。
アプリに認証を追加する場合は、アプリに Microsoft.Authentication.WebAssembly.Msal
パッケージを手動で追加します。
Note
.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。
Microsoft.Authentication.WebAssembly.Msal
パッケージによって、Microsoft.AspNetCore.Components.WebAssembly.Authentication
パッケージがアプリに推移的に追加されます。
認証サービスのサポート
ユーザーの認証に対するサポートは、Microsoft.Authentication.WebAssembly.Msal
パッケージによって提供される AddMsalAuthentication 拡張メソッドを使用して、サービス コンテナーに登録されます。 このメソッドでは、アプリが IdentityID プロバイダー (IP) とやり取りするために必要なすべてのサービスが設定されます。
Program.cs
:
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication);
});
AddMsalAuthentication メソッドでは、アプリを認証するために必要なパラメーターを構成するためのコールバックを受け入れます。 アプリを構成するために必要な値は、アプリを登録するときに AAD 構成から取得できます。
構成は wwwroot/appsettings.json
ファイルによって提供されます。
{
"AzureAdB2C": {
"Authority": "{AAD B2C INSTANCE}{DOMAIN}/{SIGN UP OR SIGN IN POLICY}",
"ClientId": "{CLIENT ID}",
"ValidateAuthority": false
}
}
前の構成では、{AAD B2C INSTANCE}
の末尾にスラッシュが含まれています。
例:
{
"AzureAdB2C": {
"Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_signupsignin1",
"ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd",
"ValidateAuthority": false
}
}
アクセス トークン スコープ
Blazor WebAssembly テンプレートでは、セキュリティで保護された API のアクセス トークンを要求するようにアプリが自動的に構成されるわけではありません。 サインイン フローの一部としてアクセス トークンをプロビジョニングするには、MsalProviderOptions の既定のアクセス トークン スコープにスコープを追加します。
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});
AdditionalScopesToConsent
を使用して追加のスコープを指定します。
options.ProviderOptions.AdditionalScopesToConsent.Add("{ADDITIONAL SCOPE URI}");
詳細については、"その他のシナリオ" に関する記事の次のセクションを参照してください。
ログイン モード
フレームワークは、既定ではポップアップ ログイン モードになり、ポップアップを開くことができない場合はリダイレクト ログイン モードに戻ります。 MsalProviderOptions の LoginMode
プロパティを redirect
に設定して、リダイレクト ログイン モードを使用するように MSAL を構成します。
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.LoginMode = "redirect";
});
既定の設定は popup
であり、文字列の値の大文字と小文字は区別されません。
インポート ファイル
Microsoft.AspNetCore.Components.Authorization 名前空間は、_Imports.razor
ファイルを介してアプリ全体で使用できるようになります。
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using {APPLICATION ASSEMBLY}
@using {APPLICATION ASSEMBLY}.Shared
Index ページ
Index ページ (wwwroot/index.html
) ページには、JavaScript で AuthenticationService
を定義するスクリプトが含まれています。 AuthenticationService
によって、OIDC プロトコルの下位レベルの詳細が処理されます。 アプリは、認証操作を実行するために、スクリプトで定義されているメソッドを内部的に呼び出します。
<script src="_content/Microsoft.Authentication.WebAssembly.Msal/
AuthenticationService.js"></script>
アプリ コンポーネント
App
コンポーネント (App.razor
) は、Blazor Server アプリにある App
コンポーネントに似ています。
- CascadingAuthenticationState コンポーネントによって、アプリの残りの部分に AuthenticationState を公開する動作が管理されます。
- AuthorizeRouteView コンポーネントによって、現在のユーザーには所与のページへのアクセスが許可されます。それ以外では、
RedirectToLogin
コンポーネントがレンダリングされます。 RedirectToLogin
コンポーネントによって、承認されていないユーザーのログイン ページへのリダイレクトが管理されます。
ASP.NET Core のリリースごとにフレームワークに違いがあるため、App
コンポーネント (App.razor
) の Razor マークアップは、このセクションでは説明しません。 特定のリリース向けのコンポーネントのマークアップを調べる場合は、次の方法の ''いずれか'' を使用してください。
使用しようとしている ASP.NET Core のバージョン向けの既定の Blazor WebAssembly プロジェクト テンプレートから、認証のためにプロビジョニングされたアプリを作成します。 作成されたアプリで、
App
コンポーネント (App.razor
) を検証します。参照元 で、
App
コンポーネント (App.razor
) を検証します。注意
ASP.NET Core 参照ソースへのドキュメント リンクを使用すると、リポジトリの
main
ブランチが読み込まれます。このブランチは、ASP.NET Core の次回リリースに向けて行われている製品単位の現在の開発を表します。 別のリリースのブランチを選択するには、 [Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使用して、そのブランチを選択します。 たとえば、ASP.NET Core 6.0 リリースの場合は、release/6.0
ブランチを選択します。
RedirectToLogin コンポーネント
RedirectToLogin
コンポーネント (Shared/RedirectToLogin.razor
) は:
- 承認されていないユーザーのログイン ページへのリダイレクトを管理します。
- 認証が成功した場合にそのページに戻ることができるように、ユーザーがアクセスしようとしている現在の URL を保持します。
@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@code {
protected override void OnInitialized()
{
Navigation.NavigateTo(
$"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}");
}
}
LoginDisplay コンポーネント
LoginDisplay
コンポーネント (Shared/LoginDisplay.razor
) は MainLayout
コンポーネント (Shared/MainLayout.razor
) でレンダリングされます。このコンポーネントによって次の動作が管理されます。
- 認証されたユーザーの場合:
- 現在のユーザー名が表示されます。
- アプリからログアウトするためのボタンが用意されます。
- 匿名ユーザーの場合は、ログインするオプションが用意されます。
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager
<AuthorizeView>
<Authorized>
Hello, @context.User.Identity.Name!
<button class="nav-link btn btn-link" @onclick="BeginLogout">
Log out
</button>
</Authorized>
<NotAuthorized>
<a href="authentication/login">Log in</a>
</NotAuthorized>
</AuthorizeView>
@code {
private async Task BeginLogout(MouseEventArgs args)
{
await SignOutManager.SetSignOutState();
Navigation.NavigateTo("authentication/logout");
}
}
認証コンポーネント
Authentication
コンポーネント (Pages/Authentication.razor
) によって生成されるページによって、さまざまな認証ステージを処理するために必要なルートが定義されます。
RemoteAuthenticatorView コンポーネント:
Microsoft.AspNetCore.Components.WebAssembly.Authentication
パッケージによって提供されます。- 認証の各段階における適切なアクションの実行を管理します。
@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="@Action" />
@code {
[Parameter]
public string Action { get; set; }
}
カスタム ユーザー フロー
Microsoft 認証ライブラリ (Microsoft.Authentication.WebAssembly.Msal、NuGet パッケージ) は、既定で AAD B2C ユーザー フローをサポートしていません。 開発者コードでカスタム ユーザー フローを作成してください。
カスタム ユーザー フローのチャレンジを構築する方法の詳細については、「Azure Active Directory B2C のユーザー フロー」を参照してください。
トラブルシューティング
一般的なエラー
アプリまたは Identity プロバイダー (IP) の構成の誤り
最も一般的なエラーの原因は、構成の誤りです。 以下に例を示します。
- シナリオの要件によっては、権限、インスタンス、テナント ID、テナント ドメイン、クライアント ID、またはリダイレクト URI の欠落または誤りによって、アプリによるクライアントの認証ができなくなります。
- アクセス トークン スコープが正しくないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
- サーバー API のアクセス許可が正しくないか、存在しないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
- Identity プロバイダーのアプリ登録のリダイレクト URI で構成されているものとは異なるポートでアプリが実行されています。
この記事のガイダンスの構成セクションに、正しい構成の例を示します。 記事の各セクションを慎重に確認して、アプリと IP の構成の誤りを探してください。
構成が正しい場合:
アプリケーション ログを分析します。
ブラウザーの開発者ツールを使用して、クライアント アプリと IP またはサーバー アプリの間のネットワーク トラフィックを確認します。 多くの場合、要求を行った後、IP またはサーバー アプリによって、問題の原因を特定する手掛かりを含む正確なエラー メッセージまたはメッセージがクライアントに返されます。 開発者ツールのガイダンスは、次の記事にあります。
- Google Chrome (Google ドキュメント)
- Microsoft Edge
- Mozilla Firefox (Mozilla ドキュメント)
問題が発生している場所に応じて、クライアントの認証またはサーバー Web API へのアクセスに使用される JSON Web Token (JWT) の内容をデコードします。 詳細については、「JSON Web トークン (JWT) の内容を検査する」を参照してください。
ドキュメント チームは、ドキュメントのフィードバックと記事のバグについては対応します (こちらのページのフィードバック セクションからイシューを作成してください) が、製品サポートを提供することはできません。 アプリのトラブルシューティングに役立つ、いくつかのパブリック サポート フォーラムが用意されています。 次をお勧めします。
上記のフォーラムは、Microsoft が所有または管理するものではありません。
セキュリティで保護されておらず、機密でも社外秘でもない再現可能なフレームワークのバグ レポートについては、ASP.NET Core 製品単位でイシューを作成してください。 問題の原因を徹底的に調査し、パブリック サポート フォーラムのコミュニティの助けを借りてもお客様自身で解決できない場合にのみ、製品単位でイシューを作成してください。 単純な構成の誤りやサードパーティのサービスに関連するユース ケースによって破損した個々のアプリのトラブルシューティングは、製品単位で行うことはできません。 レポートが機密性の高い性質のものでる場合や、攻撃者が悪用するおそれのある製品の潜在的なセキュリティ上の欠陥が記述されている場合は、セキュリティの問題とバグの報告 (dotnet/Aspnetcore GitHub リポジトリ) を参照してください。
AAD で承認されないクライアント
情報:Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] 承認に失敗しました。 次の要件が満たされていません。DenyAnonymousAuthorizationRequirement:認証済みユーザーが必要です。
AAD からのログイン コールバック エラー:
- エラー:
unauthorized_client
- 説明:
AADB2C90058: The provided application is not configured to allow public clients.
このエラーを解決するには:
- Azure portal で、アプリのマニフェストにアクセスします。
allowPublicClient
属性をnull
またはtrue
に設定します。
- エラー:
Cookie とサイト データ
Cookie とサイト データは、アプリが更新されても保持され、テストやトラブルシューティングに影響する可能性があります。 アプリ コードの変更、プロバイダーによるユーザー アカウントの変更、プロバイダー アプリの構成変更を行うときは、次のものをクリアしてください。
- ユーザー サインイン cookie
- アプリ cookie
- キャッシュおよび保存されたサイト データ
残った cookie とサイト データがテストとトラブルシューティングに影響しないようにする方法を、次に示します。
- ブラウザーを構成する
- ブラウザーが閉じるたびに cookie とサイト データをすべて削除するように構成できることをテストするために、ブラウザーを使用します。
- アプリ、テスト ユーザー、プロバイダー構成が変更されるたびにブラウザーが手動で、または IDE によって閉じられていることを確認します。
- カスタム コマンドを使用して、Visual Studio でブラウザーをシークレットまたはプライベート モードで開く。
- Visual Studio の [実行] ボタンをクリックして [ブラウザーの選択] ダイアログボックスを開きます。
- [追加] ボタンを選びます。
- [プログラム] フィールドでブラウザーのパスを指定します。 次の実行可能パスが、Windows 10 の一般的なインストール場所です。 ブラウザーが別の場所にインストールされている場合、または Windows 10 を使用していない場合は、ブラウザーの実行可能ファイルのパスを指定してください。
- Microsoft Edge:
C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
- Google Chrome:
C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
- Mozilla Firefox:
C:\Program Files\Mozilla Firefox\firefox.exe
- Microsoft Edge:
- [引数] フィールドに、ブラウザーをシークレットまたはプライベート モードで開くために使用するコマンドライン オプションを指定します。 ブラウザーによっては、アプリの URL が必要になる場合があります。
- Microsoft Edge:
-inprivate
を使用してください。 - Google Chrome:
--incognito --new-window {URL}
を使用します。プレースホルダー{URL}
は開く URL (https://localhost:5001
など) です。 - Mozilla Firefox:
-private -url {URL}
を使用します。プレースホルダー{URL}
は開く URL (https://localhost:5001
など) です。
- Microsoft Edge:
- [フレンドリ名] フィールドに名前を指定します。 たとえば、
Firefox Auth Testing
のようにします。 - [OK] ボタンを選択します。
- アプリでテストを繰り返すたびにブラウザー プロファイルを選択する必要がないようにするには、 [既定値として設定] ボタンでプロファイルを既定値として設定します。
- アプリ、テスト ユーザー、またはプロバイダー構成が変更されるたびに、ブラウザーが IDE によって閉じられていることを確認します。
アプリのアップグレード
開発マシンで .NET Core SDK をアップグレードしたり、アプリ内のパッケージ バージョンを変更したりした直後に、機能しているアプリが失敗することがあります。 場合によっては、パッケージに統一性がないと、メジャー アップグレード実行時にアプリが破壊されることがあります。 これらの問題のほとんどは、次の手順で解決できます。
- コマンド シェルから
dotnet nuget locals all --clear
を実行して、ローカル システムの NuGet パッケージ キャッシュをクリアします。 - プロジェクトのフォルダー
bin
とobj
を削除します。 - プロジェクトを復元してリビルドします。
- アプリを再展開する前に、サーバー上の展開フォルダー内のすべてのファイルを削除します。
Note
アプリのターゲット フレームワークと互換性のないパッケージ バージョンの使用はサポートされていません。 パッケージの詳細については、NuGet ギャラリーまたは FuGet パッケージ エクスプローラーを使用してください。
Server アプリを実行する
ホステッド Blazor ソリューションのテストとトラブルシューティングを行うときは、 Server
プロジェクトからアプリを実行していることをご確認ください。 たとえば、Visual Studio で、次のいずれかの方法を使用してアプリを起動する前に、Server プロジェクトがソリューション エクスプローラーで強調表示されていることを確認します。
- [実行] ボタンを選択します。
- メニューの、 [デバッグ]>[デバッグ開始] を使用します。
- F5キーを押します。
ユーザーを検査する
ASP.NET Core フレームワークのテスト アセットには、トラブルシューティングに役立つ Blazor WebAssembly クライアント アプリと User
コンポーネントが含まれます。 User
コンポーネントは、アプリ内で直接使うことも、さらにカスタマイズするための基礎として使うこともできます。
dotnet/aspnetcore
GitHub リポジトリの User
テスト コンポーネント
注意
ASP.NET Core 参照ソースへのドキュメント リンクを使用すると、リポジトリの main
ブランチが読み込まれます。このブランチは、ASP.NET Core の次回リリースに向けて行われている製品単位の現在の開発を表します。 別のリリースのブランチを選択するには、 [Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使用して、そのブランチを選択します。 たとえば、ASP.NET Core 6.0 リリースの場合は、release/6.0
ブランチを選択します。
JSON Web トークン (JWT) の内容を検査する
JSON Web トークン (JWT) をデコードするには、Microsoft の jwt.ms ツールを使用します。 UI の値がブラウザーに残ることはありません。
エンコードされた JWT の例 (表示用に短縮されています):
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1j ... bQdHBHGcQQRbW7Wmo6SWYG4V_bU55Ug_PW4pLPr20tTS8Ct7_uwy9DWrzCMzpD-EiwT5IjXwlGX3IXVjHIlX50IVIydBoPQtadvT7saKo1G5Jmutgq41o-dmz6-yBMKV2_nXA25Q
Azure AAD B2C に対して認証するアプリのツールによってデコードされた JWT の例:
{
"typ": "JWT",
"alg": "RS256",
"kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
}.{
"exp": 1610059429,
"nbf": 1610055829,
"ver": "1.0",
"iss": "https://mysiteb2c.b2clogin.com/5cc15ea8-a296-4aa3-97e4-226dcc9ad298/v2.0/",
"sub": "5ee963fb-24d6-4d72-a1b6-889c6e2c7438",
"aud": "70bde375-fce3-4b82-984a-b247d823a03f",
"nonce": "b2641f54-8dc4-42ca-97ea-7f12ff4af871",
"iat": 1610055829,
"auth_time": 1610055822,
"idp": "idp.com",
"tfp": "B2C_1_signupsignin"
}.[Signature]
その他の技術情報
- ASP.NET Core Blazor WebAssembly のセキュリティに関するその他のシナリオ
- Authentication.MSAL JavaScript ライブラリのカスタム バージョンをビルドする
- セキュリティで保護された既定のクライアントを使用する、アプリ内の認証または承認されていない Web API 要求
- ASP.NET Core での Azure Active Directory B2C を使用したクラウド認証
- チュートリアル: Azure Active Directory B2C テナントを作成する
- チュートリアル:Azure Active Directory B2C にアプリケーションを登録する
- Microsoft ID プラットフォームのドキュメント
テナントを作成するか、AAD B2C テナントの作成 (Azure ドキュメント) に関する記事に記載されているガイダンスに従って Azure portal で使用するアプリの既存の B2C テナントを選択します。 使用するテナントを作成または特定した直後に、この記事に戻ります。
次の情報を記録しておきます。
- AAD B2C インスタンス (例: 末尾にスラッシュが含まれている
https://contoso.b2clogin.com/
):インスタンスは、Azure B2C アプリの登録のスキームとホストです。これは、Azure portal で [アプリの登録] ページから [エンドポイント] ウィンドウを開くことによって見つけることができます。 - AAD B2C プライマリ、パブリッシャー、テナント ドメイン (
contoso.onmicrosoft.com
など):ドメインは、Azure portal で登録されているアプリに対する [ブランド] ブレードの [パブリッシャー ドメイン] として使用できます。
AAD B2C アプリを登録します。
- Azure portal で [Azure Active Directory] に移動します。 サイドバーで [アプリの登録] を選択します。 [新規登録] ボタンを選択します。
- アプリの名前を指定します (例: Blazor スタンドアロン AAD B2C)。
- [サポートされているアカウントの種類] で、マルチテナント オプションを選択します: [任意の組織ディレクトリ内のアカウントまたは任意の ID プロバイダー。Azure AD B2C でユーザーを認証します。]
- [リダイレクト URI] ドロップダウンを [シングルページ アプリケーション (SPA)] に設定し、次のリダイレクト URI を指定します:
https://localhost:{PORT}/authentication/login-callback
。 Kestrel で実行されているアプリの既定のポートは 5001 です。 アプリが別の Kestrel ポートで実行されている場合は、アプリのポートを使用します。 IIS Express の場合、アプリのランダムに生成されたポートは、 [デバッグ] パネルのアプリのプロパティで確認できます。 この時点ではアプリは存在せず、IIS Express ポートは不明であるため、アプリが作成された後にこの手順に戻り、リダイレクト URI を更新してください。 このトピックの後半で、IIS Express ユーザーにリダイレクト URI を更新するよう促す注意が表示されます。 - 未確認の発行元ドメインを使用している場合は、 [アクセス許可]>[openid と offline_access アクセス許可に対して管理者の同意を付与します] が選択されていることを確認します。 発行元ドメインが検証済みの場合、このチェックボックスは表示されません。
- [登録] を選択します。
アプリケーション (クライアント) ID を記録しておきます (例: 41451fa7-82d9-4673-8fa5-69eff5a761fd
)。
[認証]>[プラットフォーム構成]>[シングルページ アプリケーション (SPA)] で次のようにします。
- [リダイレクト URI] が
https://localhost:{PORT}/authentication/login-callback
であることを確認します。 - [暗黙の付与] セクションで、[アクセス トークン] と [ID トークン] のチェックボックスが選択されていないことを確認します。
- アプリの残りの既定値は、このエクスペリエンスで使用可能です。
- [保存] ボタンを選択します。
Home>[Azure AD B2C]>[ユーザー フロー] で、次の操作を行います。
少なくとも、 [アプリケーション要求]>[表示名] ユーザー属性を選択して、LoginDisplay
コンポーネント (Shared/LoginDisplay.razor
) に context.User.Identity.Name
を設定します。
アプリ用に作成されたサインアップおよびサインイン ユーザーフロー名を記録しておきます (例: B2C_1_signupsignin
)。
空のフォルダーで、次のコマンドのプレースホルダーを、前に記録した情報に置き換え、コマンド シェルでこのコマンドを実行します。
dotnet new blazorwasm -au IndividualB2C --aad-b2c-instance "{AAD B2C INSTANCE}" --client-id "{CLIENT ID}" --domain "{TENANT DOMAIN}" -o {APP NAME} -ssp "{SIGN UP OR SIGN IN POLICY}"
プレースホルダー | Azure portal での名前 | 例 |
---|---|---|
{AAD B2C INSTANCE} |
インスタンス | https://contoso.b2clogin.com/ |
{APP NAME} |
— | BlazorSample |
{CLIENT ID} |
アプリケーション (クライアント) ID | 41451fa7-82d9-4673-8fa5-69eff5a761fd |
{SIGN UP OR SIGN IN POLICY} |
サインアップまたはサインインのユーザー フロー | B2C_1_signupsignin1 |
{TENANT DOMAIN} |
プライマリ、パブリッシャー、テナント ドメイン | contoso.onmicrosoft.com |
-o|--output
オプションで指定した出力場所にプロジェクト フォルダーが存在しない場合は作成されて、アプリの名前の一部になります。
Note
Azure portal では、アプリのプラットフォーム構成の [リダイレクト URI] は、既定の設定の Kestrel サーバーで実行されるアプリの場合、ポート 5001 に構成されます。
アプリがランダム IIS Express ポートで実行されている場合、アプリのポートは [デバッグ] パネルのアプリのプロパティで確認できます。
ポートがアプリの既知のポートで事前に構成されていない場合は、Azure portal でアプリの登録に戻り、正しいポートでリダイレクト URI を更新します。
openid
と offline_access
DefaultAccessTokenScopes 用の MsalProviderOptions を組みで追加します。
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.DefaultAccessTokenScopes.Add("openid");
options.ProviderOptions.DefaultAccessTokenScopes.Add("offline_access");
});
アプリを作成すると、次のことができるようになります。
- AAD ユーザー アカウントを使用してアプリにログインする。
- Microsoft API のアクセス トークンを要求する。 詳細については次を参照してください:
認証パッケージ
個人の B2C アカウント (IndividualB2C
) を使用するようにアプリを作成すると、そのアプリで Microsoft Authentication Library (Microsoft.Authentication.WebAssembly.Msal
) のパッケージ参照を自動的に受け取ります。 このパッケージには、アプリでユーザーを認証し、保護された API を呼び出すためのトークンを取得するのに役立つ一連のプリミティブが用意されています。
アプリに認証を追加する場合は、アプリに Microsoft.Authentication.WebAssembly.Msal
パッケージを手動で追加します。
Note
.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。
Microsoft.Authentication.WebAssembly.Msal
パッケージによって、Microsoft.AspNetCore.Components.WebAssembly.Authentication
パッケージがアプリに推移的に追加されます。
認証サービスのサポート
ユーザーの認証に対するサポートは、Microsoft.Authentication.WebAssembly.Msal
パッケージによって提供される AddMsalAuthentication 拡張メソッドを使用して、サービス コンテナーに登録されます。 このメソッドでは、アプリが IdentityID プロバイダー (IP) とやり取りするために必要なすべてのサービスが設定されます。
Program.cs
:
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication);
});
AddMsalAuthentication メソッドでは、アプリを認証するために必要なパラメーターを構成するためのコールバックを受け入れます。 アプリを構成するために必要な値は、アプリを登録するときに AAD 構成から取得できます。
構成は wwwroot/appsettings.json
ファイルによって提供されます。
{
"AzureAdB2C": {
"Authority": "{AAD B2C INSTANCE}{DOMAIN}/{SIGN UP OR SIGN IN POLICY}",
"ClientId": "{CLIENT ID}",
"ValidateAuthority": false
}
}
例:
{
"AzureAdB2C": {
"Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_signupsignin1",
"ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd",
"ValidateAuthority": false
}
}
アクセス トークン スコープ
Blazor WebAssembly テンプレートでは、セキュリティで保護された API のアクセス トークンを要求するようにアプリが自動的に構成されるわけではありません。 サインイン フローの一部としてアクセス トークンをプロビジョニングするには、MsalProviderOptions の既定のアクセス トークン スコープにスコープを追加します。
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});
AdditionalScopesToConsent
を使用して追加のスコープを指定します。
options.ProviderOptions.AdditionalScopesToConsent.Add("{ADDITIONAL SCOPE URI}");
詳細については、"その他のシナリオ" に関する記事の次のセクションを参照してください。
ログイン モード
フレームワークは、既定ではポップアップ ログイン モードになり、ポップアップを開くことができない場合はリダイレクト ログイン モードに戻ります。 MsalProviderOptions の LoginMode
プロパティを redirect
に設定して、リダイレクト ログイン モードを使用するように MSAL を構成します。
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.LoginMode = "redirect";
});
既定の設定は popup
であり、文字列の値の大文字と小文字は区別されません。
インポート ファイル
Microsoft.AspNetCore.Components.Authorization 名前空間は、_Imports.razor
ファイルを介してアプリ全体で使用できるようになります。
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using {APPLICATION ASSEMBLY}
@using {APPLICATION ASSEMBLY}.Shared
Index ページ
Index ページ (wwwroot/index.html
) ページには、JavaScript で AuthenticationService
を定義するスクリプトが含まれています。 AuthenticationService
によって、OIDC プロトコルの下位レベルの詳細が処理されます。 アプリは、認証操作を実行するために、スクリプトで定義されているメソッドを内部的に呼び出します。
<script src="_content/Microsoft.Authentication.WebAssembly.Msal/
AuthenticationService.js"></script>
アプリ コンポーネント
App
コンポーネント (App.razor
) は、Blazor Server アプリにある App
コンポーネントに似ています。
- CascadingAuthenticationState コンポーネントによって、アプリの残りの部分に AuthenticationState を公開する動作が管理されます。
- AuthorizeRouteView コンポーネントによって、現在のユーザーには所与のページへのアクセスが許可されます。それ以外では、
RedirectToLogin
コンポーネントがレンダリングされます。 RedirectToLogin
コンポーネントによって、承認されていないユーザーのログイン ページへのリダイレクトが管理されます。
ASP.NET Core のリリースごとにフレームワークに違いがあるため、App
コンポーネント (App.razor
) の Razor マークアップは、このセクションでは説明しません。 特定のリリース向けのコンポーネントのマークアップを調べる場合は、次の方法の ''いずれか'' を使用してください。
使用しようとしている ASP.NET Core のバージョン向けの既定の Blazor WebAssembly プロジェクト テンプレートから、認証のためにプロビジョニングされたアプリを作成します。 作成されたアプリで、
App
コンポーネント (App.razor
) を検証します。参照元 で、
App
コンポーネント (App.razor
) を検証します。注意
ASP.NET Core 参照ソースへのドキュメント リンクを使用すると、リポジトリの
main
ブランチが読み込まれます。このブランチは、ASP.NET Core の次回リリースに向けて行われている製品単位の現在の開発を表します。 別のリリースのブランチを選択するには、 [Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使用して、そのブランチを選択します。 たとえば、ASP.NET Core 6.0 リリースの場合は、release/6.0
ブランチを選択します。
RedirectToLogin コンポーネント
RedirectToLogin
コンポーネント (Shared/RedirectToLogin.razor
) は:
- 承認されていないユーザーのログイン ページへのリダイレクトを管理します。
- 認証が成功した場合にそのページに戻ることができるように、ユーザーがアクセスしようとしている現在の URL を保持します。
@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@code {
protected override void OnInitialized()
{
Navigation.NavigateTo(
$"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}");
}
}
LoginDisplay コンポーネント
LoginDisplay
コンポーネント (Shared/LoginDisplay.razor
) は MainLayout
コンポーネント (Shared/MainLayout.razor
) でレンダリングされます。このコンポーネントによって次の動作が管理されます。
- 認証されたユーザーの場合:
- 現在のユーザー名が表示されます。
- アプリからログアウトするためのボタンが用意されます。
- 匿名ユーザーの場合は、ログインするオプションが用意されます。
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager
<AuthorizeView>
<Authorized>
Hello, @context.User.Identity.Name!
<button class="nav-link btn btn-link" @onclick="BeginLogout">
Log out
</button>
</Authorized>
<NotAuthorized>
<a href="authentication/login">Log in</a>
</NotAuthorized>
</AuthorizeView>
@code {
private async Task BeginLogout(MouseEventArgs args)
{
await SignOutManager.SetSignOutState();
Navigation.NavigateTo("authentication/logout");
}
}
認証コンポーネント
Authentication
コンポーネント (Pages/Authentication.razor
) によって生成されるページによって、さまざまな認証ステージを処理するために必要なルートが定義されます。
RemoteAuthenticatorView コンポーネント:
Microsoft.AspNetCore.Components.WebAssembly.Authentication
パッケージによって提供されます。- 認証の各段階における適切なアクションの実行を管理します。
@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="@Action" />
@code {
[Parameter]
public string Action { get; set; }
}
カスタム ユーザー フロー
Microsoft 認証ライブラリ (Microsoft.Authentication.WebAssembly.Msal、NuGet パッケージ) は、既定で AAD B2C ユーザー フローをサポートしていません。 開発者コードでカスタム ユーザー フローを作成してください。
カスタム ユーザー フローのチャレンジを構築する方法の詳細については、「Azure Active Directory B2C のユーザー フロー」を参照してください。
トラブルシューティング
一般的なエラー
アプリまたは Identity プロバイダー (IP) の構成の誤り
最も一般的なエラーの原因は、構成の誤りです。 以下に例を示します。
- シナリオの要件によっては、権限、インスタンス、テナント ID、テナント ドメイン、クライアント ID、またはリダイレクト URI の欠落または誤りによって、アプリによるクライアントの認証ができなくなります。
- アクセス トークン スコープが正しくないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
- サーバー API のアクセス許可が正しくないか、存在しないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
- Identity プロバイダーのアプリ登録のリダイレクト URI で構成されているものとは異なるポートでアプリが実行されています。
この記事のガイダンスの構成セクションに、正しい構成の例を示します。 記事の各セクションを慎重に確認して、アプリと IP の構成の誤りを探してください。
構成が正しい場合:
アプリケーション ログを分析します。
ブラウザーの開発者ツールを使用して、クライアント アプリと IP またはサーバー アプリの間のネットワーク トラフィックを確認します。 多くの場合、要求を行った後、IP またはサーバー アプリによって、問題の原因を特定する手掛かりを含む正確なエラー メッセージまたはメッセージがクライアントに返されます。 開発者ツールのガイダンスは、次の記事にあります。
- Google Chrome (Google ドキュメント)
- Microsoft Edge
- Mozilla Firefox (Mozilla ドキュメント)
問題が発生している場所に応じて、クライアントの認証またはサーバー Web API へのアクセスに使用される JSON Web Token (JWT) の内容をデコードします。 詳細については、「JSON Web トークン (JWT) の内容を検査する」を参照してください。
ドキュメント チームは、ドキュメントのフィードバックと記事のバグについては対応します (こちらのページのフィードバック セクションからイシューを作成してください) が、製品サポートを提供することはできません。 アプリのトラブルシューティングに役立つ、いくつかのパブリック サポート フォーラムが用意されています。 次をお勧めします。
上記のフォーラムは、Microsoft が所有または管理するものではありません。
セキュリティで保護されておらず、機密でも社外秘でもない再現可能なフレームワークのバグ レポートについては、ASP.NET Core 製品単位でイシューを作成してください。 問題の原因を徹底的に調査し、パブリック サポート フォーラムのコミュニティの助けを借りてもお客様自身で解決できない場合にのみ、製品単位でイシューを作成してください。 単純な構成の誤りやサードパーティのサービスに関連するユース ケースによって破損した個々のアプリのトラブルシューティングは、製品単位で行うことはできません。 レポートが機密性の高い性質のものでる場合や、攻撃者が悪用するおそれのある製品の潜在的なセキュリティ上の欠陥が記述されている場合は、セキュリティの問題とバグの報告 (dotnet/Aspnetcore GitHub リポジトリ) を参照してください。
AAD で承認されないクライアント
情報:Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] 承認に失敗しました。 次の要件が満たされていません。DenyAnonymousAuthorizationRequirement:認証済みユーザーが必要です。
AAD からのログイン コールバック エラー:
- エラー:
unauthorized_client
- 説明:
AADB2C90058: The provided application is not configured to allow public clients.
このエラーを解決するには:
- Azure portal で、アプリのマニフェストにアクセスします。
allowPublicClient
属性をnull
またはtrue
に設定します。
- エラー:
Cookie とサイト データ
Cookie とサイト データは、アプリが更新されても保持され、テストやトラブルシューティングに影響する可能性があります。 アプリ コードの変更、プロバイダーによるユーザー アカウントの変更、プロバイダー アプリの構成変更を行うときは、次のものをクリアしてください。
- ユーザー サインイン cookie
- アプリ cookie
- キャッシュおよび保存されたサイト データ
残った cookie とサイト データがテストとトラブルシューティングに影響しないようにする方法を、次に示します。
- ブラウザーを構成する
- ブラウザーが閉じるたびに cookie とサイト データをすべて削除するように構成できることをテストするために、ブラウザーを使用します。
- アプリ、テスト ユーザー、プロバイダー構成が変更されるたびにブラウザーが手動で、または IDE によって閉じられていることを確認します。
- カスタム コマンドを使用して、Visual Studio でブラウザーをシークレットまたはプライベート モードで開く。
- Visual Studio の [実行] ボタンをクリックして [ブラウザーの選択] ダイアログボックスを開きます。
- [追加] ボタンを選びます。
- [プログラム] フィールドでブラウザーのパスを指定します。 次の実行可能パスが、Windows 10 の一般的なインストール場所です。 ブラウザーが別の場所にインストールされている場合、または Windows 10 を使用していない場合は、ブラウザーの実行可能ファイルのパスを指定してください。
- Microsoft Edge:
C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
- Google Chrome:
C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
- Mozilla Firefox:
C:\Program Files\Mozilla Firefox\firefox.exe
- Microsoft Edge:
- [引数] フィールドに、ブラウザーをシークレットまたはプライベート モードで開くために使用するコマンドライン オプションを指定します。 ブラウザーによっては、アプリの URL が必要になる場合があります。
- Microsoft Edge:
-inprivate
を使用してください。 - Google Chrome:
--incognito --new-window {URL}
を使用します。プレースホルダー{URL}
は開く URL (https://localhost:5001
など) です。 - Mozilla Firefox:
-private -url {URL}
を使用します。プレースホルダー{URL}
は開く URL (https://localhost:5001
など) です。
- Microsoft Edge:
- [フレンドリ名] フィールドに名前を指定します。 たとえば、
Firefox Auth Testing
のようにします。 - [OK] ボタンを選択します。
- アプリでテストを繰り返すたびにブラウザー プロファイルを選択する必要がないようにするには、 [既定値として設定] ボタンでプロファイルを既定値として設定します。
- アプリ、テスト ユーザー、またはプロバイダー構成が変更されるたびに、ブラウザーが IDE によって閉じられていることを確認します。
アプリのアップグレード
開発マシンで .NET Core SDK をアップグレードしたり、アプリ内のパッケージ バージョンを変更したりした直後に、機能しているアプリが失敗することがあります。 場合によっては、パッケージに統一性がないと、メジャー アップグレード実行時にアプリが破壊されることがあります。 これらの問題のほとんどは、次の手順で解決できます。
- コマンド シェルから
dotnet nuget locals all --clear
を実行して、ローカル システムの NuGet パッケージ キャッシュをクリアします。 - プロジェクトのフォルダー
bin
とobj
を削除します。 - プロジェクトを復元してリビルドします。
- アプリを再展開する前に、サーバー上の展開フォルダー内のすべてのファイルを削除します。
Note
アプリのターゲット フレームワークと互換性のないパッケージ バージョンの使用はサポートされていません。 パッケージの詳細については、NuGet ギャラリーまたは FuGet パッケージ エクスプローラーを使用してください。
Server アプリを実行する
ホステッド Blazor ソリューションのテストとトラブルシューティングを行うときは、 Server
プロジェクトからアプリを実行していることをご確認ください。 たとえば、Visual Studio で、次のいずれかの方法を使用してアプリを起動する前に、Server プロジェクトがソリューション エクスプローラーで強調表示されていることを確認します。
- [実行] ボタンを選択します。
- メニューの、 [デバッグ]>[デバッグ開始] を使用します。
- F5キーを押します。
ユーザーを検査する
ASP.NET Core フレームワークのテスト アセットには、トラブルシューティングに役立つ Blazor WebAssembly クライアント アプリと User
コンポーネントが含まれます。 User
コンポーネントは、アプリ内で直接使うことも、さらにカスタマイズするための基礎として使うこともできます。
dotnet/aspnetcore
GitHub リポジトリの User
テスト コンポーネント
注意
ASP.NET Core 参照ソースへのドキュメント リンクを使用すると、リポジトリの main
ブランチが読み込まれます。このブランチは、ASP.NET Core の次回リリースに向けて行われている製品単位の現在の開発を表します。 別のリリースのブランチを選択するには、 [Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使用して、そのブランチを選択します。 たとえば、ASP.NET Core 6.0 リリースの場合は、release/6.0
ブランチを選択します。
JSON Web トークン (JWT) の内容を検査する
JSON Web トークン (JWT) をデコードするには、Microsoft の jwt.ms ツールを使用します。 UI の値がブラウザーに残ることはありません。
エンコードされた JWT の例 (表示用に短縮されています):
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1j ... bQdHBHGcQQRbW7Wmo6SWYG4V_bU55Ug_PW4pLPr20tTS8Ct7_uwy9DWrzCMzpD-EiwT5IjXwlGX3IXVjHIlX50IVIydBoPQtadvT7saKo1G5Jmutgq41o-dmz6-yBMKV2_nXA25Q
Azure AAD B2C に対して認証するアプリのツールによってデコードされた JWT の例:
{
"typ": "JWT",
"alg": "RS256",
"kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
}.{
"exp": 1610059429,
"nbf": 1610055829,
"ver": "1.0",
"iss": "https://mysiteb2c.b2clogin.com/5cc15ea8-a296-4aa3-97e4-226dcc9ad298/v2.0/",
"sub": "5ee963fb-24d6-4d72-a1b6-889c6e2c7438",
"aud": "70bde375-fce3-4b82-984a-b247d823a03f",
"nonce": "b2641f54-8dc4-42ca-97ea-7f12ff4af871",
"iat": 1610055829,
"auth_time": 1610055822,
"idp": "idp.com",
"tfp": "B2C_1_signupsignin"
}.[Signature]
その他の技術情報
- ASP.NET Core Blazor WebAssembly のセキュリティに関するその他のシナリオ
- Authentication.MSAL JavaScript ライブラリのカスタム バージョンをビルドする
- セキュリティで保護された既定のクライアントを使用する、アプリ内の認証または承認されていない Web API 要求
- ASP.NET Core での Azure Active Directory B2C を使用したクラウド認証
- チュートリアル: Azure Active Directory B2C テナントを作成する
- チュートリアル:Azure Active Directory B2C にアプリケーションを登録する
- Microsoft ID プラットフォームのドキュメント
テナントを作成するか、AAD B2C テナントの作成 (Azure ドキュメント) に関する記事に記載されているガイダンスに従って Azure portal で使用するアプリの既存の B2C テナントを選択します。 使用するテナントを作成または特定した直後に、この記事に戻ります。
次の情報を記録しておきます。
- AAD B2C インスタンス (例: 末尾にスラッシュが含まれている
https://contoso.b2clogin.com/
):インスタンスは、Azure B2C アプリの登録のスキームとホストです。これは、Azure portal で [アプリの登録] ページから [エンドポイント] ウィンドウを開くことによって見つけることができます。 - AAD B2C プライマリ、パブリッシャー、テナント ドメイン (
contoso.onmicrosoft.com
など):ドメインは、Azure portal で登録されているアプリに対する [ブランド] ブレードの [パブリッシャー ドメイン] として使用できます。
AAD B2C アプリを登録します。
- Azure portal で [Azure Active Directory] に移動します。 サイドバーで [アプリの登録] を選択します。 [新規登録] ボタンを選択します。
- アプリの名前を指定します (例: Blazor スタンドアロン AAD B2C)。
- [サポートされているアカウントの種類] で、マルチテナント オプションを選択します: [任意の組織ディレクトリ内のアカウントまたは任意の ID プロバイダー。Azure AD B2C でユーザーを認証します。]
- [リダイレクト URI] ドロップ ダウンの設定を [Web] のままとし、次のリダイレクト URI を指定します:
https://localhost:{PORT}/authentication/login-callback
。 Kestrel で実行されているアプリの既定のポートは 5001 です。 アプリが別の Kestrel ポートで実行されている場合は、アプリのポートを使用します。 IIS Express の場合、アプリのランダムに生成されたポートは、 [デバッグ] パネルのアプリのプロパティで確認できます。 この時点ではアプリは存在せず、IIS Express ポートは不明であるため、アプリが作成された後にこの手順に戻り、リダイレクト URI を更新してください。 このトピックの後半で、IIS Express ユーザーにリダイレクト URI を更新するよう促す注意が表示されます。 - 未確認の発行元ドメインを使用している場合は、 [アクセス許可]>[openid と offline_access アクセス許可に対して管理者の同意を付与します] が選択されていることを確認します。 発行元ドメインが検証済みの場合、このチェックボックスは表示されません。
- [登録] を選択します。
アプリケーション (クライアント) ID を記録しておきます (例: 41451fa7-82d9-4673-8fa5-69eff5a761fd
)。
[認証]>[プラットフォーム構成]>[Web] で、次を行います。
- [リダイレクト URI] が
https://localhost:{PORT}/authentication/login-callback
であることを確認します。 - [暗黙の付与] セクションで、[アクセス トークン] と [ID トークン] のチェックボックスをオンにします。
- アプリの残りの既定値は、このエクスペリエンスで使用可能です。
- [保存] ボタンを選択します。
Home>[Azure AD B2C]>[ユーザー フロー] で、次の操作を行います。
少なくとも、 [アプリケーション要求]>[表示名] ユーザー属性を選択して、LoginDisplay
コンポーネント (Shared/LoginDisplay.razor
) に context.User.Identity.Name
を設定します。
アプリ用に作成されたサインアップおよびサインイン ユーザーフロー名を記録しておきます (例: B2C_1_signupsignin
)。
空のフォルダーで、次のコマンドのプレースホルダーを、前に記録した情報に置き換え、コマンド シェルでこのコマンドを実行します。
dotnet new blazorwasm -au IndividualB2C --aad-b2c-instance "{AAD B2C INSTANCE}" --client-id "{CLIENT ID}" --domain "{TENANT DOMAIN}" -o {APP NAME} -ssp "{SIGN UP OR SIGN IN POLICY}"
プレースホルダー | Azure portal での名前 | 例 |
---|---|---|
{AAD B2C INSTANCE} |
インスタンス | https://contoso.b2clogin.com/ |
{APP NAME} |
— | BlazorSample |
{CLIENT ID} |
アプリケーション (クライアント) ID | 41451fa7-82d9-4673-8fa5-69eff5a761fd |
{SIGN UP OR SIGN IN POLICY} |
サインアップまたはサインインのユーザー フロー | B2C_1_signupsignin1 |
{TENANT DOMAIN} |
プライマリ、パブリッシャー、テナント ドメイン | contoso.onmicrosoft.com |
-o|--output
オプションで指定した出力場所にプロジェクト フォルダーが存在しない場合は作成されて、アプリの名前の一部になります。
Note
Azure portal では、アプリのプラットフォーム構成の [リダイレクト URI] は、既定の設定の Kestrel サーバーで実行されるアプリの場合、ポート 5001 に構成されます。
アプリがランダム IIS Express ポートで実行されている場合、アプリのポートは [デバッグ] パネルのアプリのプロパティで確認できます。
ポートがアプリの既知のポートで事前に構成されていない場合は、Azure portal でアプリの登録に戻り、正しいポートでリダイレクト URI を更新します。
アプリを作成すると、次のことができるようになります。
- AAD ユーザー アカウントを使用してアプリにログインする。
- Microsoft API のアクセス トークンを要求する。 詳細については次を参照してください:
認証パッケージ
個人の B2C アカウント (IndividualB2C
) を使用するようにアプリを作成すると、そのアプリで Microsoft Authentication Library (Microsoft.Authentication.WebAssembly.Msal
) のパッケージ参照を自動的に受け取ります。 このパッケージには、アプリでユーザーを認証し、保護された API を呼び出すためのトークンを取得するのに役立つ一連のプリミティブが用意されています。
アプリに認証を追加する場合は、アプリに Microsoft.Authentication.WebAssembly.Msal
パッケージを手動で追加します。
Note
.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。
Microsoft.Authentication.WebAssembly.Msal
パッケージによって、Microsoft.AspNetCore.Components.WebAssembly.Authentication
パッケージがアプリに推移的に追加されます。
認証サービスのサポート
ユーザーの認証に対するサポートは、Microsoft.Authentication.WebAssembly.Msal
パッケージによって提供される AddMsalAuthentication 拡張メソッドを使用して、サービス コンテナーに登録されます。 このメソッドでは、アプリが IdentityID プロバイダー (IP) とやり取りするために必要なすべてのサービスが設定されます。
Program.cs
:
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication);
});
AddMsalAuthentication メソッドでは、アプリを認証するために必要なパラメーターを構成するためのコールバックを受け入れます。 アプリを構成するために必要な値は、アプリを登録するときに AAD 構成から取得できます。
構成は wwwroot/appsettings.json
ファイルによって提供されます。
{
"AzureAdB2C": {
"Authority": "{AAD B2C INSTANCE}{DOMAIN}/{SIGN UP OR SIGN IN POLICY}",
"ClientId": "{CLIENT ID}",
"ValidateAuthority": false
}
}
例:
{
"AzureAdB2C": {
"Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_signupsignin1",
"ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd",
"ValidateAuthority": false
}
}
アクセス トークン スコープ
Blazor WebAssembly テンプレートでは、セキュリティで保護された API のアクセス トークンを要求するようにアプリが自動的に構成されるわけではありません。 サインイン フローの一部としてアクセス トークンをプロビジョニングするには、MsalProviderOptions の既定のアクセス トークン スコープにスコープを追加します。
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});
AdditionalScopesToConsent
を使用して追加のスコープを指定します。
options.ProviderOptions.AdditionalScopesToConsent.Add("{ADDITIONAL SCOPE URI}");
詳細については、"その他のシナリオ" に関する記事の次のセクションを参照してください。
インポート ファイル
Microsoft.AspNetCore.Components.Authorization 名前空間は、_Imports.razor
ファイルを介してアプリ全体で使用できるようになります。
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using {APPLICATION ASSEMBLY}
@using {APPLICATION ASSEMBLY}.Shared
Index ページ
Index ページ (wwwroot/index.html
) ページには、JavaScript で AuthenticationService
を定義するスクリプトが含まれています。 AuthenticationService
によって、OIDC プロトコルの下位レベルの詳細が処理されます。 アプリは、認証操作を実行するために、スクリプトで定義されているメソッドを内部的に呼び出します。
<script src="_content/Microsoft.Authentication.WebAssembly.Msal/
AuthenticationService.js"></script>
アプリ コンポーネント
App
コンポーネント (App.razor
) は、Blazor Server アプリにある App
コンポーネントに似ています。
- CascadingAuthenticationState コンポーネントによって、アプリの残りの部分に AuthenticationState を公開する動作が管理されます。
- AuthorizeRouteView コンポーネントによって、現在のユーザーには所与のページへのアクセスが許可されます。それ以外では、
RedirectToLogin
コンポーネントがレンダリングされます。 RedirectToLogin
コンポーネントによって、承認されていないユーザーのログイン ページへのリダイレクトが管理されます。
ASP.NET Core のリリースごとにフレームワークに違いがあるため、App
コンポーネント (App.razor
) の Razor マークアップは、このセクションでは説明しません。 特定のリリース向けのコンポーネントのマークアップを調べる場合は、次の方法の ''いずれか'' を使用してください。
使用しようとしている ASP.NET Core のバージョン向けの既定の Blazor WebAssembly プロジェクト テンプレートから、認証のためにプロビジョニングされたアプリを作成します。 作成されたアプリで、
App
コンポーネント (App.razor
) を検証します。参照元 で、
App
コンポーネント (App.razor
) を検証します。注意
ASP.NET Core 参照ソースへのドキュメント リンクを使用すると、リポジトリの
main
ブランチが読み込まれます。このブランチは、ASP.NET Core の次回リリースに向けて行われている製品単位の現在の開発を表します。 別のリリースのブランチを選択するには、 [Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使用して、そのブランチを選択します。 たとえば、ASP.NET Core 6.0 リリースの場合は、release/6.0
ブランチを選択します。
RedirectToLogin コンポーネント
RedirectToLogin
コンポーネント (Shared/RedirectToLogin.razor
) は:
- 承認されていないユーザーのログイン ページへのリダイレクトを管理します。
- 認証が成功した場合にそのページに戻ることができるように、ユーザーがアクセスしようとしている現在の URL を保持します。
@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@code {
protected override void OnInitialized()
{
Navigation.NavigateTo(
$"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}");
}
}
LoginDisplay コンポーネント
LoginDisplay
コンポーネント (Shared/LoginDisplay.razor
) は MainLayout
コンポーネント (Shared/MainLayout.razor
) でレンダリングされます。このコンポーネントによって次の動作が管理されます。
- 認証されたユーザーの場合:
- 現在のユーザー名が表示されます。
- アプリからログアウトするためのボタンが用意されます。
- 匿名ユーザーの場合は、ログインするオプションが用意されます。
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager
<AuthorizeView>
<Authorized>
Hello, @context.User.Identity.Name!
<button class="nav-link btn btn-link" @onclick="BeginLogout">
Log out
</button>
</Authorized>
<NotAuthorized>
<a href="authentication/login">Log in</a>
</NotAuthorized>
</AuthorizeView>
@code {
private async Task BeginLogout(MouseEventArgs args)
{
await SignOutManager.SetSignOutState();
Navigation.NavigateTo("authentication/logout");
}
}
認証コンポーネント
Authentication
コンポーネント (Pages/Authentication.razor
) によって生成されるページによって、さまざまな認証ステージを処理するために必要なルートが定義されます。
RemoteAuthenticatorView コンポーネント:
Microsoft.AspNetCore.Components.WebAssembly.Authentication
パッケージによって提供されます。- 認証の各段階における適切なアクションの実行を管理します。
@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="@Action" />
@code {
[Parameter]
public string Action { get; set; }
}
カスタム ユーザー フロー
Microsoft 認証ライブラリ (Microsoft.Authentication.WebAssembly.Msal、NuGet パッケージ) は、既定で AAD B2C ユーザー フローをサポートしていません。 開発者コードでカスタム ユーザー フローを作成してください。
カスタム ユーザー フローのチャレンジを構築する方法の詳細については、「Azure Active Directory B2C のユーザー フロー」を参照してください。
トラブルシューティング
一般的なエラー
アプリまたは Identity プロバイダー (IP) の構成の誤り
最も一般的なエラーの原因は、構成の誤りです。 以下に例を示します。
- シナリオの要件によっては、権限、インスタンス、テナント ID、テナント ドメイン、クライアント ID、またはリダイレクト URI の欠落または誤りによって、アプリによるクライアントの認証ができなくなります。
- アクセス トークン スコープが正しくないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
- サーバー API のアクセス許可が正しくないか、存在しないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
- Identity プロバイダーのアプリ登録のリダイレクト URI で構成されているものとは異なるポートでアプリが実行されています。
この記事のガイダンスの構成セクションに、正しい構成の例を示します。 記事の各セクションを慎重に確認して、アプリと IP の構成の誤りを探してください。
構成が正しい場合:
アプリケーション ログを分析します。
ブラウザーの開発者ツールを使用して、クライアント アプリと IP またはサーバー アプリの間のネットワーク トラフィックを確認します。 多くの場合、要求を行った後、IP またはサーバー アプリによって、問題の原因を特定する手掛かりを含む正確なエラー メッセージまたはメッセージがクライアントに返されます。 開発者ツールのガイダンスは、次の記事にあります。
- Google Chrome (Google ドキュメント)
- Microsoft Edge
- Mozilla Firefox (Mozilla ドキュメント)
問題が発生している場所に応じて、クライアントの認証またはサーバー Web API へのアクセスに使用される JSON Web Token (JWT) の内容をデコードします。 詳細については、「JSON Web トークン (JWT) の内容を検査する」を参照してください。
ドキュメント チームは、ドキュメントのフィードバックと記事のバグについては対応します (こちらのページのフィードバック セクションからイシューを作成してください) が、製品サポートを提供することはできません。 アプリのトラブルシューティングに役立つ、いくつかのパブリック サポート フォーラムが用意されています。 次をお勧めします。
上記のフォーラムは、Microsoft が所有または管理するものではありません。
セキュリティで保護されておらず、機密でも社外秘でもない再現可能なフレームワークのバグ レポートについては、ASP.NET Core 製品単位でイシューを作成してください。 問題の原因を徹底的に調査し、パブリック サポート フォーラムのコミュニティの助けを借りてもお客様自身で解決できない場合にのみ、製品単位でイシューを作成してください。 単純な構成の誤りやサードパーティのサービスに関連するユース ケースによって破損した個々のアプリのトラブルシューティングは、製品単位で行うことはできません。 レポートが機密性の高い性質のものでる場合や、攻撃者が悪用するおそれのある製品の潜在的なセキュリティ上の欠陥が記述されている場合は、セキュリティの問題とバグの報告 (dotnet/Aspnetcore GitHub リポジトリ) を参照してください。
AAD で承認されないクライアント
情報:Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] 承認に失敗しました。 次の要件が満たされていません。DenyAnonymousAuthorizationRequirement:認証済みユーザーが必要です。
AAD からのログイン コールバック エラー:
- エラー:
unauthorized_client
- 説明:
AADB2C90058: The provided application is not configured to allow public clients.
このエラーを解決するには:
- Azure portal で、アプリのマニフェストにアクセスします。
allowPublicClient
属性をnull
またはtrue
に設定します。
- エラー:
Cookie とサイト データ
Cookie とサイト データは、アプリが更新されても保持され、テストやトラブルシューティングに影響する可能性があります。 アプリ コードの変更、プロバイダーによるユーザー アカウントの変更、プロバイダー アプリの構成変更を行うときは、次のものをクリアしてください。
- ユーザー サインイン cookie
- アプリ cookie
- キャッシュおよび保存されたサイト データ
残った cookie とサイト データがテストとトラブルシューティングに影響しないようにする方法を、次に示します。
- ブラウザーを構成する
- ブラウザーが閉じるたびに cookie とサイト データをすべて削除するように構成できることをテストするために、ブラウザーを使用します。
- アプリ、テスト ユーザー、プロバイダー構成が変更されるたびにブラウザーが手動で、または IDE によって閉じられていることを確認します。
- カスタム コマンドを使用して、Visual Studio でブラウザーをシークレットまたはプライベート モードで開く。
- Visual Studio の [実行] ボタンをクリックして [ブラウザーの選択] ダイアログボックスを開きます。
- [追加] ボタンを選びます。
- [プログラム] フィールドでブラウザーのパスを指定します。 次の実行可能パスが、Windows 10 の一般的なインストール場所です。 ブラウザーが別の場所にインストールされている場合、または Windows 10 を使用していない場合は、ブラウザーの実行可能ファイルのパスを指定してください。
- Microsoft Edge:
C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
- Google Chrome:
C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
- Mozilla Firefox:
C:\Program Files\Mozilla Firefox\firefox.exe
- Microsoft Edge:
- [引数] フィールドに、ブラウザーをシークレットまたはプライベート モードで開くために使用するコマンドライン オプションを指定します。 ブラウザーによっては、アプリの URL が必要になる場合があります。
- Microsoft Edge:
-inprivate
を使用してください。 - Google Chrome:
--incognito --new-window {URL}
を使用します。プレースホルダー{URL}
は開く URL (https://localhost:5001
など) です。 - Mozilla Firefox:
-private -url {URL}
を使用します。プレースホルダー{URL}
は開く URL (https://localhost:5001
など) です。
- Microsoft Edge:
- [フレンドリ名] フィールドに名前を指定します。 たとえば、
Firefox Auth Testing
のようにします。 - [OK] ボタンを選択します。
- アプリでテストを繰り返すたびにブラウザー プロファイルを選択する必要がないようにするには、 [既定値として設定] ボタンでプロファイルを既定値として設定します。
- アプリ、テスト ユーザー、またはプロバイダー構成が変更されるたびに、ブラウザーが IDE によって閉じられていることを確認します。
アプリのアップグレード
開発マシンで .NET Core SDK をアップグレードしたり、アプリ内のパッケージ バージョンを変更したりした直後に、機能しているアプリが失敗することがあります。 場合によっては、パッケージに統一性がないと、メジャー アップグレード実行時にアプリが破壊されることがあります。 これらの問題のほとんどは、次の手順で解決できます。
- コマンド シェルから
dotnet nuget locals all --clear
を実行して、ローカル システムの NuGet パッケージ キャッシュをクリアします。 - プロジェクトのフォルダー
bin
とobj
を削除します。 - プロジェクトを復元してリビルドします。
- アプリを再展開する前に、サーバー上の展開フォルダー内のすべてのファイルを削除します。
Note
アプリのターゲット フレームワークと互換性のないパッケージ バージョンの使用はサポートされていません。 パッケージの詳細については、NuGet ギャラリーまたは FuGet パッケージ エクスプローラーを使用してください。
Server アプリを実行する
ホステッド Blazor ソリューションのテストとトラブルシューティングを行うときは、 Server
プロジェクトからアプリを実行していることをご確認ください。 たとえば、Visual Studio で、次のいずれかの方法を使用してアプリを起動する前に、Server プロジェクトがソリューション エクスプローラーで強調表示されていることを確認します。
- [実行] ボタンを選択します。
- メニューの、 [デバッグ]>[デバッグ開始] を使用します。
- F5キーを押します。
ユーザーを検査する
ASP.NET Core フレームワークのテスト アセットには、トラブルシューティングに役立つ Blazor WebAssembly クライアント アプリと User
コンポーネントが含まれます。 User
コンポーネントは、アプリ内で直接使うことも、さらにカスタマイズするための基礎として使うこともできます。
dotnet/aspnetcore
GitHub リポジトリの User
テスト コンポーネント
注意
ASP.NET Core 参照ソースへのドキュメント リンクを使用すると、リポジトリの main
ブランチが読み込まれます。このブランチは、ASP.NET Core の次回リリースに向けて行われている製品単位の現在の開発を表します。 別のリリースのブランチを選択するには、 [Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使用して、そのブランチを選択します。 たとえば、ASP.NET Core 6.0 リリースの場合は、release/6.0
ブランチを選択します。
JSON Web トークン (JWT) の内容を検査する
JSON Web トークン (JWT) をデコードするには、Microsoft の jwt.ms ツールを使用します。 UI の値がブラウザーに残ることはありません。
エンコードされた JWT の例 (表示用に短縮されています):
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1j ... bQdHBHGcQQRbW7Wmo6SWYG4V_bU55Ug_PW4pLPr20tTS8Ct7_uwy9DWrzCMzpD-EiwT5IjXwlGX3IXVjHIlX50IVIydBoPQtadvT7saKo1G5Jmutgq41o-dmz6-yBMKV2_nXA25Q
Azure AAD B2C に対して認証するアプリのツールによってデコードされた JWT の例:
{
"typ": "JWT",
"alg": "RS256",
"kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
}.{
"exp": 1610059429,
"nbf": 1610055829,
"ver": "1.0",
"iss": "https://mysiteb2c.b2clogin.com/5cc15ea8-a296-4aa3-97e4-226dcc9ad298/v2.0/",
"sub": "5ee963fb-24d6-4d72-a1b6-889c6e2c7438",
"aud": "70bde375-fce3-4b82-984a-b247d823a03f",
"nonce": "b2641f54-8dc4-42ca-97ea-7f12ff4af871",
"iat": 1610055829,
"auth_time": 1610055822,
"idp": "idp.com",
"tfp": "B2C_1_signupsignin"
}.[Signature]
その他の技術情報
- ASP.NET Core Blazor WebAssembly のセキュリティに関するその他のシナリオ
- Authentication.MSAL JavaScript ライブラリのカスタム バージョンをビルドする
- セキュリティで保護された既定のクライアントを使用する、アプリ内の認証または承認されていない Web API 要求
- ASP.NET Core での Azure Active Directory B2C を使用したクラウド認証
- チュートリアル: Azure Active Directory B2C テナントを作成する
- チュートリアル:Azure Active Directory B2C にアプリケーションを登録する
- Microsoft ID プラットフォームのドキュメント