ホストされている ASP.NET Core Blazor WebAssembly アプリを Azure Active Directory B2C を使ってセキュリティ保護する

この記事では、認証に Azure Active Directory (AAD) B2C を使用するホステッド Blazor WebAssembly ソリューションを作成する方法について説明します。

ソリューションの詳細については、「ASP.NET Core Blazor 用のツール」を参照してください。

AAD B2C でアプリを登録してソリューションを作成する

テナントの作成

チュートリアル: Azure Active Directory B2C テナントの作成」のガイダンスに従って、AAD B2C テナントを作成します。 使用するテナントを作成または特定した直後に、この記事に戻ります。

AAD B2C インスタンスを記録しておきます (例: 末尾にスラッシュが含まれている https://contoso.b2clogin.com/)。 インスタンスは、Azure B2C アプリの登録のスキームとホストです。これは、Azure portal で [アプリの登録] ページから [エンドポイント] ウィンドウを開くことによって見つけることができます。

サーバー API アプリを登録する

"サーバー API アプリ" 用の AAD B2C アプリを登録します。

  1. Azure portal で [Azure Active Directory] に移動します。 サイドバーで [アプリの登録] を選択します。 [新規登録] ボタンを選択します。
  2. アプリの [名前] を指定します (例: Blazor Server AAD B2C)。
  3. [サポートされているアカウントの種類] で、マルチテナント オプションを選択します: ID プロバイダーまたは組織ディレクトリのアカウント (ユーザー フローでユーザーを認証するため)
  4. "サーバー API アプリ" の場合、このシナリオでは [リダイレクト URI] は必要ないので、ドロップダウンは [Web] に設定されたままにして、リダイレクト URI は入力しません。
  5. 未確認の発行元ドメインを使用している場合は、 [アクセス許可]>[openid と offline_access アクセス許可に対して管理者の同意を付与します] が選択されていることを確認します。 発行元ドメインが検証済みの場合、このチェックボックスは表示されません。
  6. [登録] を選択します。

次の情報を記録しておきます。

  • "サーバー API アプリ" のアプリケーション (クライアント) ID (例: 41451fa7-82d9-4673-8fa5-69eff5a761fd)
  • AAD プライマリ、パブリッシャー、テナント ドメイン (contoso.onmicrosoft.com など):ドメインは、Azure portal で登録されているアプリに対する [ブランド] ブレードの [パブリッシャー ドメイン] として使用できます。

[API の公開] で:

  1. [Scope の追加] を選択します。
  2. [Save and continue](保存して続行) を選択します。
  3. [スコープ名] を指定します (例: API.Access)。
  4. [管理者の同意の表示名] を指定します (例: Access API)。
  5. [管理者の同意の説明] を指定します (例: Allows the app to access server app API endpoints.)。
  6. [状態][有効] に設定されていることを確認します。
  7. [スコープの追加] を選択します。

次の情報を記録しておきます。

  • アプリ ID の URI (例: api://41451fa7-82d9-4673-8fa5-69eff5a761fdhttps://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd、または指定したカスタム値)
  • スコープ名 (例: API.Access)

クライアント アプリを登録する

"クライアント アプリ" 用の AAD B2C アプリを登録します。

  1. Azure portal で [Azure Active Directory] に移動します。 サイドバーで [アプリの登録] を選択します。 [新規登録] ボタンを選択します。
  2. アプリの [名前] を指定します (例: Blazor クライアント AAD B2C)。
  3. [サポートされているアカウントの種類] で、マルチテナント オプションを選択します: ID プロバイダーまたは組織ディレクトリのアカウント (ユーザー フローでユーザーを認証するため)
  4. [リダイレクト URI] ドロップダウンを [シングルページ アプリケーション (SPA)] に設定し、次のリダイレクト URI を指定します: https://localhost/authentication/login-callback。 Azure の既定のホスト (たとえば azurewebsites.net) またはカスタム ドメイン ホスト (たとえば contoso.com) の運用リダイレクト URI がわかっている場合は、localhost リダイレクト URI を提供するのと同時に運用リダイレクト URI を追加することもできます。 追加する運用リダイレクト URI には、ポート:443 以外のポートのポート番号を必ず含めてください。
  5. 未確認の発行元ドメインを使用している場合は、 [アクセス許可]>[openid と offline_access アクセス許可に対して管理者の同意を付与します] が選択されていることを確認します。 発行元ドメインが検証済みの場合、このチェックボックスは表示されません。
  6. [登録] を選択します。

Note

localhost AAD B2C リダイレクト URI のポート番号を指定する必要はありません。 詳細については、「リダイレクト URI (応答 URL) に関する制約と制限」の「Localhost 例外」(Azure ドキュメント) を参照してください。

アプリケーション (クライアント) ID を記録しておきます (例: 4369008b-21fa-427c-abaa-9b53bf58e538)。

[認証]>[プラットフォーム構成]>[シングルページ アプリケーション (SPA)] で次のようにします。

  1. [リダイレクト URI]https://localhost/authentication/login-callback であることを確認します。
  2. [暗黙の付与] セクションで、[アクセス トークン][ID トークン] のチェックボックスが選択されていないことを確認します。
  3. アプリの残りの既定値は、このエクスペリエンスで使用可能です。
  4. [保存] ボタンを選択します。

[API のアクセス許可] で:

  1. [アクセス許可の追加] を選択し、 [自分の API] を選択します。
  2. [名前] 列で "サーバー API アプリ" を選択します (例: Blazor Server AAD B2C)。
  3. [API] の一覧を開きます。
  4. API へのアクセスを有効にします (例: API.Access)。
  5. [アクセス許可の追加] を選択します.
  6. [<テナント名> に管理者の同意を与えます] ボタンを選択します。 [はい] を選択して確定します。

重要

アプリの使用に対する同意がユーザーに委任されたため、API アクセス許可の構成の最後の手順でテナントに管理者の同意を付与する権限を持っていなかった場合は、次の追加の手順を実行する必要があります。

  • アプリでは、信頼された発行元ドメインを使用する必要があります。
  • Azure portal の Server アプリの構成で、[API の公開] を選択します。 [認可済みのクライアント アプリケーション] で、[クライアント アプリケーションの追加] ボタンを選択します。 Client アプリのアプリケーション (クライアント) ID を追加します (例: 4369008b-21fa-427c-abaa-9b53bf58e538)。

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}" --api-client-id "{SERVER API APP CLIENT ID}" --app-id-uri "{SERVER API APP ID URI}" --client-id "{CLIENT APP CLIENT ID}" --default-scope "{DEFAULT SCOPE}" --domain "{TENANT DOMAIN}" -ho -o {APP NAME} -ssp "{SIGN UP OR SIGN IN POLICY}"

警告

OIDC アプリ識別子の形成を妨げるダッシュ (-) をアプリ名 {APP NAME} に使用しないでください。 Blazor WebAssembly プロジェクト テンプレート内のロジックでは、ソリューションの構成内の OIDC アプリ識別子にプロジェクト名を使用します。 パスカル ケース (BlazorSample) またはアンダースコア (Blazor_Sample) は許容可能な代替手段です 詳細については、ホストされた Blazor WebAssembly プロジェクト名に含まれるダッシュによって OIDC のセキュリティが破られる (dotnet/aspnetcore #35337)を参照してください。

プレースホルダー Azure portal での名前
{AAD B2C INSTANCE} インスタンス https://contoso.b2clogin.com/ (末尾のスラッシュを含む)
{APP NAME} BlazorSample
{CLIENT APP CLIENT ID} Client アプリのアプリケーション (クライアント) ID 4369008b-21fa-427c-abaa-9b53bf58e538
{DEFAULT SCOPE} スコープ名 API.Access
{SERVER API APP CLIENT ID} "サーバー API アプリ" のアプリケーション (クライアント) ID 41451fa7-82d9-4673-8fa5-69eff5a761fd
{SERVER API APP ID URI} アプリケーション ID の URI† 41451fa7-82d9-4673-8fa5-69eff5a761fd
{SIGN UP OR SIGN IN POLICY} サインアップまたはサインインのユーザー フロー B2C_1_signupsignin1
{TENANT DOMAIN} プライマリ、パブリッシャー、テナント ドメイン contoso.onmicrosoft.com

dotnet new コマンドに渡されるアプリ ID URI 引数に、Blazor WebAssembly テンプレートによって api:// のスキームが自動的に追加されます。 {SERVER API APP ID URI} プレースホルダーでアプリ ID URI を指定し、スキームが api:// の場合は、上記の表の例の値に示すように、引数からスキーム (api://) を削除します。 アプリ ID URI がカスタム値の場合、または他の何らかのスキームである場合 (たとえば、https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd のような未確認の発行元ドメインhttps://) は、既定のスコープ URI を手動で更新し、テンプレートによって Client アプリが作成された後で、api:// スキームを削除する必要があります。 詳細については、「アクセス トークン スコープ」セクションの注を参照してください。 Blazor WebAssembly テンプレートは、このようなシナリオに対応するため、ASP.NET Core の今後のリリースで変更される可能性があります。 詳細については、「Blazor WASM テンプレートでのアプリ ID URI 用の二重スキーム (ホストされた、単一組織) (dotnet/aspnetcore #27417)」を参照してください。

-o|--output オプションで指定した出力場所にプロジェクト フォルダーが存在しない場合は作成されて、アプリの名前の一部になります。 OIDC アプリ識別子の形成を妨げるダッシュ (-) をアプリ名に使用しないでください (前述の警告を参照)。

注意

Blazor WebAssembly プロジェクト テンプレートによってホストされている Blazor WebAssembly ソリューションで設定されるスコープでは、アプリ ID URI ホストが繰り返される場合があります。 DefaultAccessTokenScopes コレクションに対して構成されたスコープが Client アプリの Program.cs で正しいことを確認します。

Server アプリの構成

"このセクションは、ソリューションの Server アプリに関連しています。 "

認証パッケージ

Microsoft Identity Platform での ASP.NET Core Web API の呼び出しの認証と承認のサポートは、Microsoft.Identity.Web パッケージによって提供されます。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。

Blazor WebAssembly テンプレートから作成された、ホストされている Blazor ソリューションの Server アプリには、既定で Microsoft.Identity.Web.UI パッケージが含まれます。 このパッケージでは、Web アプリでユーザー認証用の UI が追加され、Blazor フレームワークでは使用されません。 ユーザーの認証に Server アプリが直接使われない場合は、Server アプリのプロジェクト ファイルからパッケージ参照を削除しても安全です。

認証サービスのサポート

AddAuthentication メソッドにより、アプリ内での認証サービスが設定され、JWT ベアラー ハンドラーが既定の認証方法として構成されます。 AddMicrosoftIdentityWebApi メソッドによって、Microsoft Identity Platform v2.0 を使用して Web API を保護するようにサービスを構成できます。 このメソッドでは、認証オプションを初期化するために必要な設定で、アプリの構成の AzureAdB2C セクションが想定されます。

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAdB2C"));

注意

1 つの認証スキームが登録されると、認証スキームがアプリの既定のスキームとして自動的に使用され、スキームを AddAuthentication に指定、または AuthenticationOptions 経由にする必要はありません。 詳細については、「ASP.NET Core の認証の概要」と ASP.NET Core のお知らせ (aspnet/Announcements #490) を参照してください。

UseAuthenticationUseAuthorization により、次のようになります。

  • アプリにより、受信要求のトークンの解析と検証が試みられます。
  • 適切な資格情報なしで保護されたリソースへのアクセスを試みた要求は失敗します。
app.UseAuthentication();
app.UseAuthorization();

User.Identity.Name

既定では、User.Identity.Name は設定されません。

name 要求の種類から値を受け取るようにアプリを構成するために、以下のようにします。

アプリの設定

appsettings.json ファイルには、アクセス トークンの検証に使用される JWT ベアラー ハンドラーを構成するためのオプションが含まれています。

{
  "AzureAdB2C": {
    "Instance": "https://{TENANT}.b2clogin.com/",
    "ClientId": "{SERVER API APP CLIENT ID}",
    "Domain": "{TENANT DOMAIN}",
    "SignUpSignInPolicyId": "{SIGN UP OR SIGN IN POLICY}"
  }
}

例:

{
  "AzureAdB2C": {
    "Instance": "https://contoso.b2clogin.com/",
    "ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd",
    "Domain": "contoso.onmicrosoft.com",
    "SignUpSignInPolicyId": "B2C_1_signupsignin1",
  }
}

WeatherForecast コントローラー

WeatherForecast コントローラー (Controllers/WeatherForecastController.cs) は、[Authorize] 属性 が適用されている保護された API をコントローラーに公開します。 次のことを理解しておくことが重要です。

  • この API コントローラーの [Authorize] 属性は、この API を不正アクセスから保護する唯一のものです。
  • Blazor WebAssembly アプリで使用される [Authorize] 属性は、アプリが正しく動作するにはユーザーを承認する必要がある、というアプリへのヒントとしてのみ機能します。
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        ...
    }
}

Client アプリの構成

"このセクションは、ソリューションの Client アプリに関連しています。 "

認証パッケージ

個人の 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 パッケージがアプリに推移的に追加されます。

認証サービスのサポート

サーバー プロジェクトへの要求を行うときのアクセス トークンが含まれる HttpClient インスタンスのサポートが追加されます。

Program.cs:

builder.Services.AddHttpClient("{APP ASSEMBLY}.ServerAPI", client => 
    client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
    .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
    .CreateClient("{APP ASSEMBLY}.ServerAPI"));

プレースホルダー {APP ASSEMBLY} は、アプリのアセンブリ名です (例: BlazorSample.Client)。

ユーザーの認証に対するサポートは、Microsoft.Authentication.WebAssembly.Msal パッケージによって提供される AddMsalAuthentication 拡張メソッドを使用して、サービス コンテナーに登録されます。 このメソッドでは、アプリが IdentityID プロバイダー (IP) とやり取りするために必要なサービスが設定されます。

Program.cs:

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication);
    options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});

AddMsalAuthentication メソッドでは、アプリを認証するために必要なパラメーターを構成するためのコールバックを受け入れます。 アプリを構成するために必要な値は、アプリを登録するときに Azure Portal の AAD の構成から取得できます。

構成は wwwroot/appsettings.json ファイルによって提供されます。

{
  "AzureAdB2C": {
    "Authority": "{AAD B2C INSTANCE}{TENANT DOMAIN}/{SIGN UP OR SIGN IN POLICY}",
    "ClientId": "{CLIENT APP CLIENT ID}",
    "ValidateAuthority": false
  }
}

前の構成では、{AAD B2C INSTANCE} の末尾にスラッシュが含まれています。

例:

{
  "AzureAdB2C": {
    "Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_signupsignin1",
    "ClientId": "4369008b-21fa-427c-abaa-9b53bf58e538",
    "ValidateAuthority": false
  }
}

アクセス トークン スコープ

既定のアクセス トークン スコープでは、次のようなアクセス トークン スコープの一覧が表されます。

  • サインイン要求に既定で含まれます。
  • 認証直後にアクセス トークンをプロビジョニングするために使用されます。

すべてのスコープは、Azure Active Directory の規則に従って同じアプリに属している必要があります。 必要に応じて追加の API アプリ用に追加のスコープを追加できます。

builder.Services.AddMsalAuthentication(options =>
{
    ...
    options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});

Note

dotnet new コマンドに渡されるアプリ ID URI 引数に、Blazor WebAssembly テンプレートによって api:// のスキームが自動的に追加されます。 Blazor プロジェクト テンプレートからアプリを生成するときは、既定のアクセス トークン スコープの値で、Azure portal で指定した正しいカスタム アプリ ID URI の値、または次のいずれかの形式の値が使用されていることを確認します。

  • ディレクトリの発行元ドメインが信頼されている場合は、通常、既定のアクセス トークンのスコープは次の例のような値になります。API.Access は既定のスコープ名です。

    options.ProviderOptions.DefaultAccessTokenScopes.Add(
        "api://41451fa7-82d9-4673-8fa5-69eff5a761fd/API.Access");
    

    二重スキーム (api://api://...) の値を調べます。 二重スキームが存在する場合は、最初の api:// スキームを値から削除します。

  • ディレクトリの発行元ドメインが信頼されていない場合は、通常、既定のアクセス トークンのスコープは次の例のような値になります。API.Access は既定のスコープ名です。

    options.ProviderOptions.DefaultAccessTokenScopes.Add(
        "https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd/API.Access");
    

    余分な api:// スキーム (api://https://contoso.onmicrosoft.com/...) の値を調べます。 余分な api:// スキームが存在する場合は、api:// スキームを値から削除します。

Blazor WebAssembly テンプレートは、このようなシナリオに対応するため、ASP.NET Core の今後のリリースで変更される可能性があります。 詳細については、「Blazor WASM テンプレートでのアプリ ID URI 用の二重スキーム (ホストされた、単一組織) (dotnet/aspnetcore #27417)」を参照してください。

AdditionalScopesToConsent を使用して追加のスコープを指定します。

options.ProviderOptions.AdditionalScopesToConsent.Add("{ADDITIONAL SCOPE URI}");

詳細については、"その他のシナリオ" に関する記事の次のセクションを参照してください。

ログイン モード

フレームワークは、既定ではポップアップ ログイン モードになり、ポップアップを開くことができない場合はリダイレクト ログイン モードに戻ります。 MsalProviderOptionsLoginMode プロパティを 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}.Client
@using {APPLICATION ASSEMBLY}.Client.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) を検証します。

    注意

    通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

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)}");
    }
}

ASP.NET Core 7.0 で、Blazor WebAssembly アプリでの認証のサポートが変更され、URL のクエリ文字列ではなく履歴状態に依存するようになりました。 その結果、クエリ文字列を介して戻り先 URL を渡すと、ログインの成功後に元のページへのリダイレクトが失敗します。 代わりに NavigateToLogin 拡張メソッドを使用してください。 詳細については、「破壊的変更: WebAssembly アプリでの認証」を参照してください。

@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Microsoft.Extensions.Options

@inject IOptionsSnapshot<RemoteAuthenticationOptions<ApiAuthorizationProviderOptions>> Options
@code {
    protected override void OnInitialized()
    {
        Navigation.NavigateToLogin(Options.Get(Microsoft.Extensions.Options.Options.DefaultName).AuthenticationPaths.LogInPath);
    }
}

LoginDisplay コンポーネント

LoginDisplay コンポーネント (Shared/LoginDisplay.razor) は MainLayout コンポーネント (Shared/MainLayout.razor) でレンダリングされます。このコンポーネントによって次の動作が管理されます。

  • 認証されたユーザーの場合:
    • 現在のユーザー名が表示されます。
    • アプリからログアウトするためのボタンが用意されます。
  • 匿名ユーザーの場合は、ログインするオプションが用意されます。

ASP.NET Core のリリースごとにフレームワークに違いがあるため、LoginDisplay コンポーネントの Razor マークアップは、このセクションでは説明しません。 特定のリリース向けのコンポーネントのマークアップを調べる場合は、次の方法の ''いずれか'' を使用してください。

  • 使用しようとしている ASP.NET Core のバージョン向けの既定の Blazor WebAssembly プロジェクト テンプレートから、認証のためにプロビジョニングされたアプリを作成します。 作成されたアプリで、LoginDisplay コンポーネントを検証します。

  • 参照元で、LoginDisplay コンポーネントを検証します。

    注意

    通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

認証コンポーネント

Authentication コンポーネント (Pages/Authentication.razor) によって生成されるページによって、さまざまな認証ステージを処理するために必要なルートが定義されます。

RemoteAuthenticatorView コンポーネント:

@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

<RemoteAuthenticatorView Action="@Action" />

@code {
    [Parameter]
    public string Action { get; set; }
}

FetchData コンポーネント

FetchData コンポーネントは次の方法を示します。

  • アクセス トークンをプロビジョニングする。
  • アクセス トークンを使用して、Server アプリで保護されたリソース API を呼び出す。

@attribute [Authorize] ディレクティブは、このコンポーネントにアクセスするためにユーザーを承認する必要があることを Blazor WebAssembly の承認システムに示します。 Client アプリに属性が存在しても、適切な資格情報を使用せずにサーバー上の API が呼び出されるのを防ぐことはできません。 また、Server アプリは、適切なエンドポイントでそれを正しく保護するために [Authorize] も使用する必要があります。

IAccessTokenProvider.RequestAccessToken は、API を呼び出すために要求に追加できるアクセス トークンの要求を処理します。 トークンがキャッシュされている場合、またはサービスがユーザーの操作なしで新しいアクセス トークンをプロビジョニングできる場合、トークン要求は成功します。 それ以外の場合、トークン要求は、try-catch ステートメントでキャッチされた AccessTokenNotAvailableException により失敗します。

要求に含める実際のトークンを取得するには、アプリが tokenResult.TryGetToken(out var token) を呼び出して、要求が成功したことを確認する必要があります。

要求が成功すると、トークン変数にアクセス トークンが設定されます。 トークンの AccessToken.Value プロパティは、Authorization 要求ヘッダーに含めるリテラル文字列を公開します。

ユーザーの操作なしでトークンをプロビジョニングできなかったために要求が失敗した場合:

  • ASP.NET Core 7.0 以降: 指定された AccessTokenResult.InteractionOptions を使用してアプリは AccessTokenResult.InteractiveRequestUrl に移動し、アクセス トークンの更新を許可します。
  • ASP.NET Core 6.0 以前: トークン結果にはリダイレクト URL が含まれます。 この URL に移動すると、認証が成功した後、ユーザーがログイン ページに移動してから、現在のページに戻ります。
@page "/fetchdata"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using {APP NAMESPACE}.Shared
@attribute [Authorize]
@inject HttpClient Http

...

@code {
    private WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }
}

アプリを実行する

サーバー プロジェクトからアプリを実行します。 Visual Studio を使用しているときは、次のいずれかを行います。

  • ツール バーの [スタートアップ プロジェクト] ドロップダウン リストを "サーバー API アプリ" に設定して、 [実行] ボタンを選択します。
  • ソリューション エクスプローラーでサーバー プロジェクトを選択し、ツール バーの [実行] ボタンを選択するか、 [デバッグ] メニューからアプリを開始します。

カスタム ユーザー フロー

Microsoft 認証ライブラリ (Microsoft.Authentication.WebAssembly.MsalNuGet パッケージ) は、既定で AAD B2C ユーザー フローをサポートしていません。 開発者コードでカスタム ユーザー フローを作成してください。

カスタム ユーザー フローのチャレンジを構築する方法の詳細については、「Azure Active Directory B2C のユーザー フロー」を参照してください。

トラブルシューティング

ログ記録

Blazor WebAssembly 認証のデバッグまたはトレース ログを有効にするには、「ASP.NET Core Blazor のログ」をご覧ください。

一般的なエラー

  • アプリまたは Identity プロバイダー (IP) の構成の誤り

    最も一般的なエラーの原因は、構成の誤りです。 以下に例を示します。

    • シナリオの要件によっては、権限、インスタンス、テナント ID、テナント ドメイン、クライアント ID、またはリダイレクト URI の欠落または誤りによって、アプリによるクライアントの認証ができなくなります。
    • アクセス トークン スコープが正しくないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
    • サーバー API のアクセス許可が正しくないか、存在しないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
    • Identity プロバイダーのアプリ登録のリダイレクト URI で構成されているものとは異なるポートでアプリが実行されています。

    この記事のガイダンスの構成セクションに、正しい構成の例を示します。 記事の各セクションを慎重に確認して、アプリと IP の構成の誤りを探してください。

    構成が正しい場合:

    • アプリケーション ログを分析します。

    • ブラウザーの開発者ツールを使用して、クライアント アプリと IP またはサーバー アプリの間のネットワーク トラフィックを確認します。 多くの場合、要求を行った後、IP またはサーバー アプリによって、問題の原因を特定する手掛かりを含む正確なエラー メッセージまたはメッセージがクライアントに返されます。 開発者ツールのガイダンスは、次の記事にあります。

    • 問題が発生している場所に応じて、クライアントの認証またはサーバー 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.

    このエラーを解決するには:

    1. Azure portal で、アプリのマニフェストにアクセスします。
    2. 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
    • [引数] フィールドに、ブラウザーをシークレットまたはプライベート モードで開くために使用するコマンドライン オプションを指定します。 ブラウザーによっては、アプリの 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 など) です。
    • [フレンドリ名] フィールドに名前を指定します。 たとえば、Firefox Auth Testing のようにします。
    • [OK] ボタンを選択します。
    • アプリでテストを繰り返すたびにブラウザー プロファイルを選択する必要がないようにするには、 [既定値として設定] ボタンでプロファイルを既定値として設定します。
    • アプリ、テスト ユーザー、またはプロバイダー構成が変更されるたびに、ブラウザーが IDE によって閉じられていることを確認します。

アプリのアップグレード

開発マシンで .NET Core SDK をアップグレードしたり、アプリ内のパッケージ バージョンを変更したりした直後に、機能しているアプリが失敗することがあります。 場合によっては、パッケージに統一性がないと、メジャー アップグレード実行時にアプリが破壊されることがあります。 これらの問題のほとんどは、次の手順で解決できます。

  1. コマンド シェルから dotnet nuget locals all --clear を実行して、ローカル システムの NuGet パッケージ キャッシュをクリアします。
  2. プロジェクトのフォルダー binobj を削除します。
  3. プロジェクトを復元してリビルドします。
  4. アプリを再展開する前に、サーバー上の展開フォルダー内のすべてのファイルを削除します。

Note

アプリのターゲット フレームワークと互換性のないパッケージ バージョンの使用はサポートされていません。 パッケージの詳細については、NuGet ギャラリーまたは FuGet パッケージ エクスプローラーを使用してください。

Server アプリを実行する

ホステッド Blazor WebAssemblyソリューションのテストとトラブルシューティングを行うときは、Server プロジェクトからアプリを実行していることをご確認ください。 たとえば、Visual Studio で、次のいずれかの方法を使用してアプリを起動する前に、Server プロジェクトがソリューション エクスプローラーで強調表示されていることを確認します。

  • [実行] ボタンを選択します。
  • メニューの、 [デバッグ]>[デバッグ開始] を使用します。
  • F5キーを押します。

ユーザーを検査する

ASP.NET Core フレームワークのテスト アセットには、トラブルシューティングに役立つ Blazor WebAssembly クライアント アプリUser コンポーネントが含まれます。 User コンポーネントは、アプリ内で直接使うことも、さらにカスタマイズするための基礎として使うこともできます。

dotnet/aspnetcore GitHub リポジトリの User テスト コンポーネント

注意

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

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]

その他の技術情報

AAD B2C でアプリを登録してソリューションを作成する

テナントの作成

チュートリアル: Azure Active Directory B2C テナントの作成」のガイダンスに従って、AAD B2C テナントを作成します。 使用するテナントを作成または特定した直後に、この記事に戻ります。

AAD B2C インスタンスを記録しておきます (例: 末尾にスラッシュが含まれている https://contoso.b2clogin.com/)。 インスタンスは、Azure B2C アプリの登録のスキームとホストです。これは、Azure portal で [アプリの登録] ページから [エンドポイント] ウィンドウを開くことによって見つけることができます。

サーバー API アプリを登録する

"サーバー API アプリ" 用の AAD B2C アプリを登録します。

  1. Azure portal で [Azure Active Directory] に移動します。 サイドバーで [アプリの登録] を選択します。 [新規登録] ボタンを選択します。
  2. アプリの [名前] を指定します (例: Blazor Server AAD B2C)。
  3. [サポートされているアカウントの種類] で、マルチテナント オプションを選択します: ID プロバイダーまたは組織ディレクトリのアカウント (ユーザー フローでユーザーを認証するため)
  4. "サーバー API アプリ" の場合、このシナリオでは [リダイレクト URI] は必要ないので、ドロップダウンは [Web] に設定されたままにして、リダイレクト URI は入力しません。
  5. 未確認の発行元ドメインを使用している場合は、 [アクセス許可]>[openid と offline_access アクセス許可に対して管理者の同意を付与します] が選択されていることを確認します。 発行元ドメインが検証済みの場合、このチェックボックスは表示されません。
  6. [登録] を選択します。

次の情報を記録しておきます。

  • "サーバー API アプリ" のアプリケーション (クライアント) ID (例: 41451fa7-82d9-4673-8fa5-69eff5a761fd)
  • AAD プライマリ、パブリッシャー、テナント ドメイン (contoso.onmicrosoft.com など):ドメインは、Azure portal で登録されているアプリに対する [ブランド] ブレードの [パブリッシャー ドメイン] として使用できます。

[API の公開] で:

  1. [Scope の追加] を選択します。
  2. [Save and continue](保存して続行) を選択します。
  3. [スコープ名] を指定します (例: API.Access)。
  4. [管理者の同意の表示名] を指定します (例: Access API)。
  5. [管理者の同意の説明] を指定します (例: Allows the app to access server app API endpoints.)。
  6. [状態][有効] に設定されていることを確認します。
  7. [スコープの追加] を選択します。

次の情報を記録しておきます。

  • アプリ ID の URI (例: api://41451fa7-82d9-4673-8fa5-69eff5a761fdhttps://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd、または指定したカスタム値)
  • スコープ名 (例: API.Access)

クライアント アプリを登録する

"クライアント アプリ" 用の AAD B2C アプリを登録します。

  1. Azure portal で [Azure Active Directory] に移動します。 サイドバーで [アプリの登録] を選択します。 [新規登録] ボタンを選択します。
  2. アプリの [名前] を指定します (例: Blazor クライアント AAD B2C)。
  3. [サポートされているアカウントの種類] で、マルチテナント オプションを選択します: ID プロバイダーまたは組織ディレクトリのアカウント (ユーザー フローでユーザーを認証するため)
  4. [リダイレクト URI] ドロップダウンを [シングルページ アプリケーション (SPA)] に設定し、次のリダイレクト URI を指定します: https://localhost/authentication/login-callback。 Azure の既定のホスト (たとえば azurewebsites.net) またはカスタム ドメイン ホスト (たとえば contoso.com) の運用リダイレクト URI がわかっている場合は、localhost リダイレクト URI を提供するのと同時に運用リダイレクト URI を追加することもできます。 追加する運用リダイレクト URI には、ポート:443 以外のポートのポート番号を必ず含めてください。
  5. 未確認の発行元ドメインを使用している場合は、 [アクセス許可]>[openid と offline_access アクセス許可に対して管理者の同意を付与します] が選択されていることを確認します。 発行元ドメインが検証済みの場合、このチェックボックスは表示されません。
  6. [登録] を選択します。

Note

localhost AAD B2C リダイレクト URI のポート番号を指定する必要はありません。 詳細については、「リダイレクト URI (応答 URL) に関する制約と制限」の「Localhost 例外」(Azure ドキュメント) を参照してください。

アプリケーション (クライアント) ID を記録しておきます (例: 4369008b-21fa-427c-abaa-9b53bf58e538)。

[認証]>[プラットフォーム構成]>[シングルページ アプリケーション (SPA)] で次のようにします。

  1. [リダイレクト URI]https://localhost/authentication/login-callback であることを確認します。
  2. [暗黙の付与] セクションで、[アクセス トークン][ID トークン] のチェックボックスが選択されていないことを確認します。
  3. アプリの残りの既定値は、このエクスペリエンスで使用可能です。
  4. [保存] ボタンを選択します。

[API のアクセス許可] で:

  1. [アクセス許可の追加] を選択し、 [自分の API] を選択します。
  2. [名前] 列で "サーバー API アプリ" を選択します (例: Blazor Server AAD B2C)。
  3. [API] の一覧を開きます。
  4. API へのアクセスを有効にします (例: API.Access)。
  5. [アクセス許可の追加] を選択します.
  6. [<テナント名> に管理者の同意を与えます] ボタンを選択します。 [はい] を選択して確定します。

重要

アプリの使用に対する同意がユーザーに委任されたため、API アクセス許可の構成の最後の手順でテナントに管理者の同意を付与する権限を持っていなかった場合は、次の追加の手順を実行する必要があります。

  • アプリでは、信頼された発行元ドメインを使用する必要があります。
  • Azure portal の Server アプリの構成で、[API の公開] を選択します。 [認可済みのクライアント アプリケーション] で、[クライアント アプリケーションの追加] ボタンを選択します。 Client アプリのアプリケーション (クライアント) ID を追加します (例: 4369008b-21fa-427c-abaa-9b53bf58e538)。

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}" --api-client-id "{SERVER API APP CLIENT ID}" --app-id-uri "{SERVER API APP ID URI}" --client-id "{CLIENT APP CLIENT ID}" --default-scope "{DEFAULT SCOPE}" --domain "{TENANT DOMAIN}" -ho -o {APP NAME} -ssp "{SIGN UP OR SIGN IN POLICY}"

警告

OIDC アプリ識別子の形成を妨げるダッシュ (-) をアプリ名 {APP NAME} に使用しないでください。 Blazor WebAssembly プロジェクト テンプレート内のロジックでは、ソリューションの構成内の OIDC アプリ識別子にプロジェクト名を使用します。 パスカル ケース (BlazorSample) またはアンダースコア (Blazor_Sample) は許容可能な代替手段です 詳細については、ホストされた Blazor WebAssembly プロジェクト名に含まれるダッシュによって OIDC のセキュリティが破られる (dotnet/aspnetcore #35337)を参照してください。

プレースホルダー Azure portal での名前
{AAD B2C INSTANCE} インスタンス https://contoso.b2clogin.com/ (末尾のスラッシュを含む)
{APP NAME} BlazorSample
{CLIENT APP CLIENT ID} Client アプリのアプリケーション (クライアント) ID 4369008b-21fa-427c-abaa-9b53bf58e538
{DEFAULT SCOPE} スコープ名 API.Access
{SERVER API APP CLIENT ID} "サーバー API アプリ" のアプリケーション (クライアント) ID 41451fa7-82d9-4673-8fa5-69eff5a761fd
{SERVER API APP ID URI} アプリケーション ID の URI† 41451fa7-82d9-4673-8fa5-69eff5a761fd
{SIGN UP OR SIGN IN POLICY} サインアップまたはサインインのユーザー フロー B2C_1_signupsignin1
{TENANT DOMAIN} プライマリ、パブリッシャー、テナント ドメイン contoso.onmicrosoft.com

dotnet new コマンドに渡されるアプリ ID URI 引数に、Blazor WebAssembly テンプレートによって api:// のスキームが自動的に追加されます。 {SERVER API APP ID URI} プレースホルダーでアプリ ID URI を指定し、スキームが api:// の場合は、上記の表の例の値に示すように、引数からスキーム (api://) を削除します。 アプリ ID URI がカスタム値の場合、または他の何らかのスキームである場合 (たとえば、https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd のような未確認の発行元ドメインhttps://) は、既定のスコープ URI を手動で更新し、テンプレートによって Client アプリが作成された後で、api:// スキームを削除する必要があります。 詳細については、「アクセス トークン スコープ」セクションの注を参照してください。 Blazor WebAssembly テンプレートは、このようなシナリオに対応するため、ASP.NET Core の今後のリリースで変更される可能性があります。 詳細については、「Blazor WASM テンプレートでのアプリ ID URI 用の二重スキーム (ホストされた、単一組織) (dotnet/aspnetcore #27417)」を参照してください。

-o|--output オプションで指定した出力場所にプロジェクト フォルダーが存在しない場合は作成されて、アプリの名前の一部になります。 OIDC アプリ識別子の形成を妨げるダッシュ (-) をアプリ名に使用しないでください (前述の警告を参照)。

注意

Blazor WebAssembly プロジェクト テンプレートによってホストされている Blazor WebAssembly ソリューションで設定されるスコープでは、アプリ ID URI ホストが繰り返される場合があります。 DefaultAccessTokenScopes コレクションに対して構成されたスコープが Client アプリの Program.cs で正しいことを確認します。

Server アプリの構成

"このセクションは、ソリューションの Server アプリに関連しています。 "

認証パッケージ

Microsoft Identity Platform での ASP.NET Core Web API の呼び出しの認証と承認のサポートは、Microsoft.Identity.Web パッケージによって提供されます。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。

Blazor WebAssembly テンプレートから作成された、ホストされている Blazor ソリューションの Server アプリには、既定で Microsoft.Identity.Web.UI パッケージが含まれます。 このパッケージでは、Web アプリでユーザー認証用の UI が追加され、Blazor フレームワークでは使用されません。 ユーザーの認証に Server アプリが直接使われない場合は、Server アプリのプロジェクト ファイルからパッケージ参照を削除しても安全です。

認証サービスのサポート

AddAuthentication メソッドにより、アプリ内での認証サービスが設定され、JWT ベアラー ハンドラーが既定の認証方法として構成されます。 AddMicrosoftIdentityWebApi メソッドによって、Microsoft Identity Platform v2.0 を使用して Web API を保護するようにサービスを構成できます。 このメソッドでは、認証オプションを初期化するために必要な設定で、アプリの構成の AzureAdB2C セクションが想定されます。

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAdB2C"));

UseAuthenticationUseAuthorization により、次のようになります。

  • アプリにより、受信要求のトークンの解析と検証が試みられます。
  • 適切な資格情報なしで保護されたリソースへのアクセスを試みた要求は失敗します。
app.UseAuthentication();
app.UseAuthorization();

User.Identity.Name

既定では、User.Identity.Name は設定されません。

name 要求の種類から値を受け取るようにアプリを構成するために、以下のようにします。

アプリの設定

appsettings.json ファイルには、アクセス トークンの検証に使用される JWT ベアラー ハンドラーを構成するためのオプションが含まれています。

{
  "AzureAdB2C": {
    "Instance": "https://{TENANT}.b2clogin.com/",
    "ClientId": "{SERVER API APP CLIENT ID}",
    "Domain": "{TENANT DOMAIN}",
    "SignUpSignInPolicyId": "{SIGN UP OR SIGN IN POLICY}"
  }
}

例:

{
  "AzureAdB2C": {
    "Instance": "https://contoso.b2clogin.com/",
    "ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd",
    "Domain": "contoso.onmicrosoft.com",
    "SignUpSignInPolicyId": "B2C_1_signupsignin1",
  }
}

WeatherForecast コントローラー

WeatherForecast コントローラー (Controllers/WeatherForecastController.cs) は、[Authorize] 属性 が適用されている保護された API をコントローラーに公開します。 次のことを理解しておくことが重要です。

  • この API コントローラーの [Authorize] 属性は、この API を不正アクセスから保護する唯一のものです。
  • Blazor WebAssembly アプリで使用される [Authorize] 属性は、アプリが正しく動作するにはユーザーを承認する必要がある、というアプリへのヒントとしてのみ機能します。
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        ...
    }
}

Client アプリの構成

"このセクションは、ソリューションの Client アプリに関連しています。 "

認証パッケージ

個人の 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 パッケージがアプリに推移的に追加されます。

認証サービスのサポート

サーバー プロジェクトへの要求を行うときのアクセス トークンが含まれる HttpClient インスタンスのサポートが追加されます。

Program.cs:

builder.Services.AddHttpClient("{APP ASSEMBLY}.ServerAPI", client => 
    client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
    .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
    .CreateClient("{APP ASSEMBLY}.ServerAPI"));

プレースホルダー {APP ASSEMBLY} は、アプリのアセンブリ名です (例: BlazorSample.Client)。

ユーザーの認証に対するサポートは、Microsoft.Authentication.WebAssembly.Msal パッケージによって提供される AddMsalAuthentication 拡張メソッドを使用して、サービス コンテナーに登録されます。 このメソッドでは、アプリが IdentityID プロバイダー (IP) とやり取りするために必要なサービスが設定されます。

Program.cs:

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication);
    options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});

AddMsalAuthentication メソッドでは、アプリを認証するために必要なパラメーターを構成するためのコールバックを受け入れます。 アプリを構成するために必要な値は、アプリを登録するときに Azure Portal の AAD の構成から取得できます。

構成は wwwroot/appsettings.json ファイルによって提供されます。

{
  "AzureAdB2C": {
    "Authority": "{AAD B2C INSTANCE}{TENANT DOMAIN}/{SIGN UP OR SIGN IN POLICY}",
    "ClientId": "{CLIENT APP CLIENT ID}",
    "ValidateAuthority": false
  }
}

前の構成では、{AAD B2C INSTANCE} の末尾にスラッシュが含まれています。

例:

{
  "AzureAdB2C": {
    "Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_signupsignin1",
    "ClientId": "4369008b-21fa-427c-abaa-9b53bf58e538",
    "ValidateAuthority": false
  }
}

アクセス トークン スコープ

既定のアクセス トークン スコープでは、次のようなアクセス トークン スコープの一覧が表されます。

  • サインイン要求に既定で含まれます。
  • 認証直後にアクセス トークンをプロビジョニングするために使用されます。

すべてのスコープは、Azure Active Directory の規則に従って同じアプリに属している必要があります。 必要に応じて追加の API アプリ用に追加のスコープを追加できます。

builder.Services.AddMsalAuthentication(options =>
{
    ...
    options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});

Note

dotnet new コマンドに渡されるアプリ ID URI 引数に、Blazor WebAssembly テンプレートによって api:// のスキームが自動的に追加されます。 Blazor プロジェクト テンプレートからアプリを生成するときは、既定のアクセス トークン スコープの値で、Azure portal で指定した正しいカスタム アプリ ID URI の値、または次のいずれかの形式の値が使用されていることを確認します。

  • ディレクトリの発行元ドメインが信頼されている場合は、通常、既定のアクセス トークンのスコープは次の例のような値になります。API.Access は既定のスコープ名です。

    options.ProviderOptions.DefaultAccessTokenScopes.Add(
        "api://41451fa7-82d9-4673-8fa5-69eff5a761fd/API.Access");
    

    二重スキーム (api://api://...) の値を調べます。 二重スキームが存在する場合は、最初の api:// スキームを値から削除します。

  • ディレクトリの発行元ドメインが信頼されていない場合は、通常、既定のアクセス トークンのスコープは次の例のような値になります。API.Access は既定のスコープ名です。

    options.ProviderOptions.DefaultAccessTokenScopes.Add(
        "https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd/API.Access");
    

    余分な api:// スキーム (api://https://contoso.onmicrosoft.com/...) の値を調べます。 余分な api:// スキームが存在する場合は、api:// スキームを値から削除します。

Blazor WebAssembly テンプレートは、このようなシナリオに対応するため、ASP.NET Core の今後のリリースで変更される可能性があります。 詳細については、「Blazor WASM テンプレートでのアプリ ID URI 用の二重スキーム (ホストされた、単一組織) (dotnet/aspnetcore #27417)」を参照してください。

AdditionalScopesToConsent を使用して追加のスコープを指定します。

options.ProviderOptions.AdditionalScopesToConsent.Add("{ADDITIONAL SCOPE URI}");

詳細については、"その他のシナリオ" に関する記事の次のセクションを参照してください。

ログイン モード

フレームワークは、既定ではポップアップ ログイン モードになり、ポップアップを開くことができない場合はリダイレクト ログイン モードに戻ります。 MsalProviderOptionsLoginMode プロパティを 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}.Client
@using {APPLICATION ASSEMBLY}.Client.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) を検証します。

    注意

    通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

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)}");
    }
}

ASP.NET Core 7.0 で、Blazor WebAssembly アプリでの認証のサポートが変更され、URL のクエリ文字列ではなく履歴状態に依存するようになりました。 その結果、クエリ文字列を介して戻り先 URL を渡すと、ログインの成功後に元のページへのリダイレクトが失敗します。 代わりに NavigateToLogin 拡張メソッドを使用してください。 詳細については、「破壊的変更: WebAssembly アプリでの認証」を参照してください。

@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Microsoft.Extensions.Options

@inject IOptionsSnapshot<RemoteAuthenticationOptions<ApiAuthorizationProviderOptions>> Options
@code {
    protected override void OnInitialized()
    {
        Navigation.NavigateToLogin(Options.Get(Microsoft.Extensions.Options.Options.DefaultName).AuthenticationPaths.LogInPath);
    }
}

LoginDisplay コンポーネント

LoginDisplay コンポーネント (Shared/LoginDisplay.razor) は MainLayout コンポーネント (Shared/MainLayout.razor) でレンダリングされます。このコンポーネントによって次の動作が管理されます。

  • 認証されたユーザーの場合:
    • 現在のユーザー名が表示されます。
    • アプリからログアウトするためのボタンが用意されます。
  • 匿名ユーザーの場合は、ログインするオプションが用意されます。

ASP.NET Core のリリースごとにフレームワークに違いがあるため、LoginDisplay コンポーネントの Razor マークアップは、このセクションでは説明しません。 特定のリリース向けのコンポーネントのマークアップを調べる場合は、次の方法の ''いずれか'' を使用してください。

  • 使用しようとしている ASP.NET Core のバージョン向けの既定の Blazor WebAssembly プロジェクト テンプレートから、認証のためにプロビジョニングされたアプリを作成します。 作成されたアプリで、LoginDisplay コンポーネントを検証します。

  • 参照元で、LoginDisplay コンポーネントを検証します。

    注意

    通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

認証コンポーネント

Authentication コンポーネント (Pages/Authentication.razor) によって生成されるページによって、さまざまな認証ステージを処理するために必要なルートが定義されます。

RemoteAuthenticatorView コンポーネント:

@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

<RemoteAuthenticatorView Action="@Action" />

@code {
    [Parameter]
    public string Action { get; set; }
}

FetchData コンポーネント

FetchData コンポーネントは次の方法を示します。

  • アクセス トークンをプロビジョニングする。
  • アクセス トークンを使用して、Server アプリで保護されたリソース API を呼び出す。

@attribute [Authorize] ディレクティブは、このコンポーネントにアクセスするためにユーザーを承認する必要があることを Blazor WebAssembly の承認システムに示します。 Client アプリに属性が存在しても、適切な資格情報を使用せずにサーバー上の API が呼び出されるのを防ぐことはできません。 また、Server アプリは、適切なエンドポイントでそれを正しく保護するために [Authorize] も使用する必要があります。

IAccessTokenProvider.RequestAccessToken は、API を呼び出すために要求に追加できるアクセス トークンの要求を処理します。 トークンがキャッシュされている場合、またはサービスがユーザーの操作なしで新しいアクセス トークンをプロビジョニングできる場合、トークン要求は成功します。 それ以外の場合、トークン要求は、try-catch ステートメントでキャッチされた AccessTokenNotAvailableException により失敗します。

要求に含める実際のトークンを取得するには、アプリが tokenResult.TryGetToken(out var token) を呼び出して、要求が成功したことを確認する必要があります。

要求が成功すると、トークン変数にアクセス トークンが設定されます。 トークンの AccessToken.Value プロパティは、Authorization 要求ヘッダーに含めるリテラル文字列を公開します。

ユーザーの操作なしでトークンをプロビジョニングできなかったために要求が失敗した場合:

  • ASP.NET Core 7.0 以降: 指定された AccessTokenResult.InteractionOptions を使用してアプリは AccessTokenResult.InteractiveRequestUrl に移動し、アクセス トークンの更新を許可します。
  • ASP.NET Core 6.0 以前: トークン結果にはリダイレクト URL が含まれます。 この URL に移動すると、認証が成功した後、ユーザーがログイン ページに移動してから、現在のページに戻ります。
@page "/fetchdata"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using {APP NAMESPACE}.Shared
@attribute [Authorize]
@inject HttpClient Http

...

@code {
    private WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }
}

アプリを実行する

サーバー プロジェクトからアプリを実行します。 Visual Studio を使用しているときは、次のいずれかを行います。

  • ツール バーの [スタートアップ プロジェクト] ドロップダウン リストを "サーバー API アプリ" に設定して、 [実行] ボタンを選択します。
  • ソリューション エクスプローラーでサーバー プロジェクトを選択し、ツール バーの [実行] ボタンを選択するか、 [デバッグ] メニューからアプリを開始します。

カスタム ユーザー フロー

Microsoft 認証ライブラリ (Microsoft.Authentication.WebAssembly.MsalNuGet パッケージ) は、既定で AAD B2C ユーザー フローをサポートしていません。 開発者コードでカスタム ユーザー フローを作成してください。

カスタム ユーザー フローのチャレンジを構築する方法の詳細については、「Azure Active Directory B2C のユーザー フロー」を参照してください。

トラブルシューティング

一般的なエラー

  • アプリまたは Identity プロバイダー (IP) の構成の誤り

    最も一般的なエラーの原因は、構成の誤りです。 以下に例を示します。

    • シナリオの要件によっては、権限、インスタンス、テナント ID、テナント ドメイン、クライアント ID、またはリダイレクト URI の欠落または誤りによって、アプリによるクライアントの認証ができなくなります。
    • アクセス トークン スコープが正しくないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
    • サーバー API のアクセス許可が正しくないか、存在しないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
    • Identity プロバイダーのアプリ登録のリダイレクト URI で構成されているものとは異なるポートでアプリが実行されています。

    この記事のガイダンスの構成セクションに、正しい構成の例を示します。 記事の各セクションを慎重に確認して、アプリと IP の構成の誤りを探してください。

    構成が正しい場合:

    • アプリケーション ログを分析します。

    • ブラウザーの開発者ツールを使用して、クライアント アプリと IP またはサーバー アプリの間のネットワーク トラフィックを確認します。 多くの場合、要求を行った後、IP またはサーバー アプリによって、問題の原因を特定する手掛かりを含む正確なエラー メッセージまたはメッセージがクライアントに返されます。 開発者ツールのガイダンスは、次の記事にあります。

    • 問題が発生している場所に応じて、クライアントの認証またはサーバー 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.

    このエラーを解決するには:

    1. Azure portal で、アプリのマニフェストにアクセスします。
    2. 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
    • [引数] フィールドに、ブラウザーをシークレットまたはプライベート モードで開くために使用するコマンドライン オプションを指定します。 ブラウザーによっては、アプリの 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 など) です。
    • [フレンドリ名] フィールドに名前を指定します。 たとえば、Firefox Auth Testing のようにします。
    • [OK] ボタンを選択します。
    • アプリでテストを繰り返すたびにブラウザー プロファイルを選択する必要がないようにするには、 [既定値として設定] ボタンでプロファイルを既定値として設定します。
    • アプリ、テスト ユーザー、またはプロバイダー構成が変更されるたびに、ブラウザーが IDE によって閉じられていることを確認します。

アプリのアップグレード

開発マシンで .NET Core SDK をアップグレードしたり、アプリ内のパッケージ バージョンを変更したりした直後に、機能しているアプリが失敗することがあります。 場合によっては、パッケージに統一性がないと、メジャー アップグレード実行時にアプリが破壊されることがあります。 これらの問題のほとんどは、次の手順で解決できます。

  1. コマンド シェルから dotnet nuget locals all --clear を実行して、ローカル システムの NuGet パッケージ キャッシュをクリアします。
  2. プロジェクトのフォルダー binobj を削除します。
  3. プロジェクトを復元してリビルドします。
  4. アプリを再展開する前に、サーバー上の展開フォルダー内のすべてのファイルを削除します。

Note

アプリのターゲット フレームワークと互換性のないパッケージ バージョンの使用はサポートされていません。 パッケージの詳細については、NuGet ギャラリーまたは FuGet パッケージ エクスプローラーを使用してください。

Server アプリを実行する

ホステッド Blazor WebAssemblyソリューションのテストとトラブルシューティングを行うときは、Server プロジェクトからアプリを実行していることをご確認ください。 たとえば、Visual Studio で、次のいずれかの方法を使用してアプリを起動する前に、Server プロジェクトがソリューション エクスプローラーで強調表示されていることを確認します。

  • [実行] ボタンを選択します。
  • メニューの、 [デバッグ]>[デバッグ開始] を使用します。
  • F5キーを押します。

ユーザーを検査する

ASP.NET Core フレームワークのテスト アセットには、トラブルシューティングに役立つ Blazor WebAssembly クライアント アプリUser コンポーネントが含まれます。 User コンポーネントは、アプリ内で直接使うことも、さらにカスタマイズするための基礎として使うこともできます。

dotnet/aspnetcore GitHub リポジトリの User テスト コンポーネント

注意

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

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]

その他の技術情報

AAD B2C でアプリを登録してソリューションを作成する

テナントの作成

チュートリアル: Azure Active Directory B2C テナントの作成」のガイダンスに従って、AAD B2C テナントを作成します。 使用するテナントを作成または特定した直後に、この記事に戻ります。

AAD B2C インスタンスを記録しておきます (例: 末尾にスラッシュが含まれている https://contoso.b2clogin.com/)。 インスタンスは、Azure B2C アプリの登録のスキームとホストです。これは、Azure portal で [アプリの登録] ページから [エンドポイント] ウィンドウを開くことによって見つけることができます。

サーバー API アプリを登録する

"サーバー API アプリ" 用の AAD B2C アプリを登録します。

  1. Azure portal で [Azure Active Directory] に移動します。 サイドバーで [アプリの登録] を選択します。 [新規登録] ボタンを選択します。
  2. アプリの [名前] を指定します (例: Blazor Server AAD B2C)。
  3. [サポートされているアカウントの種類] で、マルチテナント オプションを選択します: ID プロバイダーまたは組織ディレクトリのアカウント (ユーザー フローでユーザーを認証するため)
  4. "サーバー API アプリ" の場合、このシナリオでは [リダイレクト URI] は必要ないので、ドロップダウンは [Web] に設定されたままにして、リダイレクト URI は入力しません。
  5. 未確認の発行元ドメインを使用している場合は、 [アクセス許可]>[openid と offline_access アクセス許可に対して管理者の同意を付与します] が選択されていることを確認します。 発行元ドメインが検証済みの場合、このチェックボックスは表示されません。
  6. [登録] を選択します。

次の情報を記録しておきます。

  • "サーバー API アプリ" のアプリケーション (クライアント) ID (例: 41451fa7-82d9-4673-8fa5-69eff5a761fd)
  • AAD プライマリ、パブリッシャー、テナント ドメイン (contoso.onmicrosoft.com など):ドメインは、Azure portal で登録されているアプリに対する [ブランド] ブレードの [パブリッシャー ドメイン] として使用できます。

[API の公開] で:

  1. [Scope の追加] を選択します。
  2. [Save and continue](保存して続行) を選択します。
  3. [スコープ名] を指定します (例: API.Access)。
  4. [管理者の同意の表示名] を指定します (例: Access API)。
  5. [管理者の同意の説明] を指定します (例: Allows the app to access server app API endpoints.)。
  6. [状態][有効] に設定されていることを確認します。
  7. [スコープの追加] を選択します。

次の情報を記録しておきます。

  • アプリ ID の URI (例: api://41451fa7-82d9-4673-8fa5-69eff5a761fdhttps://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd、または指定したカスタム値)
  • スコープ名 (例: API.Access)

クライアント アプリを登録する

"クライアント アプリ" 用の AAD B2C アプリを登録します。

  1. Azure portal で [Azure Active Directory] に移動します。 サイドバーで [アプリの登録] を選択します。 [新規登録] ボタンを選択します。
  2. アプリの [名前] を指定します (例: Blazor クライアント AAD B2C)。
  3. [サポートされているアカウントの種類] で、マルチテナント オプションを選択します: ID プロバイダーまたは組織ディレクトリのアカウント (ユーザー フローでユーザーを認証するため)
  4. [リダイレクト URI] ドロップダウンを [シングルページ アプリケーション (SPA)] に設定し、次のリダイレクト URI を指定します: https://localhost/authentication/login-callback。 Azure の既定のホスト (たとえば azurewebsites.net) またはカスタム ドメイン ホスト (たとえば contoso.com) の運用リダイレクト URI がわかっている場合は、localhost リダイレクト URI を提供するのと同時に運用リダイレクト URI を追加することもできます。 追加する運用リダイレクト URI には、ポート:443 以外のポートのポート番号を必ず含めてください。
  5. 未確認の発行元ドメインを使用している場合は、 [アクセス許可]>[openid と offline_access アクセス許可に対して管理者の同意を付与します] が選択されていることを確認します。 発行元ドメインが検証済みの場合、このチェックボックスは表示されません。
  6. [登録] を選択します。

Note

localhost AAD B2C リダイレクト URI のポート番号を指定する必要はありません。 詳細については、「リダイレクト URI (応答 URL) に関する制約と制限」の「Localhost 例外」(Azure ドキュメント) を参照してください。

アプリケーション (クライアント) ID を記録しておきます (例: 4369008b-21fa-427c-abaa-9b53bf58e538)。

[認証]>[プラットフォーム構成]>[シングルページ アプリケーション (SPA)] で次のようにします。

  1. [リダイレクト URI]https://localhost/authentication/login-callback であることを確認します。
  2. [暗黙の付与] セクションで、[アクセス トークン][ID トークン] のチェックボックスが選択されていないことを確認します。
  3. アプリの残りの既定値は、このエクスペリエンスで使用可能です。
  4. [保存] ボタンを選択します。

[API のアクセス許可] で:

  1. [アクセス許可の追加] を選択し、 [自分の API] を選択します。
  2. [名前] 列で "サーバー API アプリ" を選択します (例: Blazor Server AAD B2C)。
  3. [API] の一覧を開きます。
  4. API へのアクセスを有効にします (例: API.Access)。
  5. [アクセス許可の追加] を選択します.
  6. [<テナント名> に管理者の同意を与えます] ボタンを選択します。 [はい] を選択して確定します。

重要

アプリの使用に対する同意がユーザーに委任されたため、API アクセス許可の構成の最後の手順でテナントに管理者の同意を付与する権限を持っていなかった場合は、次の追加の手順を実行する必要があります。

  • アプリでは、信頼された発行元ドメインを使用する必要があります。
  • Azure portal の Server アプリの構成で、[API の公開] を選択します。 [認可済みのクライアント アプリケーション] で、[クライアント アプリケーションの追加] ボタンを選択します。 Client アプリのアプリケーション (クライアント) ID を追加します (例: 4369008b-21fa-427c-abaa-9b53bf58e538)。

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}" --api-client-id "{SERVER API APP CLIENT ID}" --app-id-uri "{SERVER API APP ID URI}" --client-id "{CLIENT APP CLIENT ID}" --default-scope "{DEFAULT SCOPE}" --domain "{TENANT DOMAIN}" -ho -o {APP NAME} -ssp "{SIGN UP OR SIGN IN POLICY}"

警告

OIDC アプリ識別子の形成を妨げるダッシュ (-) をアプリ名 {APP NAME} に使用しないでください。 Blazor WebAssembly プロジェクト テンプレート内のロジックでは、ソリューションの構成内の OIDC アプリ識別子にプロジェクト名を使用します。 パスカル ケース (BlazorSample) またはアンダースコア (Blazor_Sample) は許容可能な代替手段です 詳細については、ホストされた Blazor WebAssembly プロジェクト名に含まれるダッシュによって OIDC のセキュリティが破られる (dotnet/aspnetcore #35337)を参照してください。

プレースホルダー Azure portal での名前
{AAD B2C INSTANCE} インスタンス https://contoso.b2clogin.com/
{APP NAME} BlazorSample
{CLIENT APP CLIENT ID} Client アプリのアプリケーション (クライアント) ID 4369008b-21fa-427c-abaa-9b53bf58e538
{DEFAULT SCOPE} スコープ名 API.Access
{SERVER API APP CLIENT ID} "サーバー API アプリ" のアプリケーション (クライアント) ID 41451fa7-82d9-4673-8fa5-69eff5a761fd
{SERVER API APP ID URI} アプリケーション ID の URI† 41451fa7-82d9-4673-8fa5-69eff5a761fd
{SIGN UP OR SIGN IN POLICY} サインアップまたはサインインのユーザー フロー B2C_1_signupsignin1
{TENANT DOMAIN} プライマリ、パブリッシャー、テナント ドメイン contoso.onmicrosoft.com

dotnet new コマンドに渡されるアプリ ID URI 引数に、Blazor WebAssembly テンプレートによって api:// のスキームが自動的に追加されます。 {SERVER API APP ID URI} プレースホルダーでアプリ ID URI を指定し、スキームが api:// の場合は、上記の表の例の値に示すように、引数からスキーム (api://) を削除します。 アプリ ID URI がカスタム値の場合、または他の何らかのスキームである場合 (たとえば、https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd のような未確認の発行元ドメインhttps://) は、既定のスコープ URI を手動で更新し、テンプレートによって Client アプリが作成された後で、api:// スキームを削除する必要があります。 詳細については、「アクセス トークン スコープ」セクションの注を参照してください。 Blazor WebAssembly テンプレートは、このようなシナリオに対応するため、ASP.NET Core の今後のリリースで変更される可能性があります。 詳細については、「Blazor WASM テンプレートでのアプリ ID URI 用の二重スキーム (ホストされた、単一組織) (dotnet/aspnetcore #27417)」を参照してください。

-o|--output オプションで指定した出力場所にプロジェクト フォルダーが存在しない場合は作成されて、アプリの名前の一部になります。 OIDC アプリ識別子の形成を妨げるダッシュ (-) をアプリ名に使用しないでください (前述の警告を参照)。

注意

Blazor WebAssembly プロジェクト テンプレートによってホストされている Blazor WebAssembly ソリューションで設定されるスコープでは、アプリ ID URI ホストが繰り返される場合があります。 DefaultAccessTokenScopes コレクションに対して構成されたスコープが Client アプリの Program.cs で正しいことを確認します。

Server アプリの構成

"このセクションは、ソリューションの Server アプリに関連しています。 "

認証パッケージ

Microsoft Identity Platform での ASP.NET Core Web API の呼び出しの認証と承認のサポートは、Microsoft.Identity.Web パッケージによって提供されます。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。

Blazor WebAssembly テンプレートから作成された、ホストされている Blazor ソリューションの Server アプリには、既定で Microsoft.Identity.Web.UI パッケージが含まれます。 このパッケージでは、Web アプリでユーザー認証用の UI が追加され、Blazor フレームワークでは使用されません。 ユーザーの認証に Server アプリが直接使われない場合は、Server アプリのプロジェクト ファイルからパッケージ参照を削除しても安全です。

認証サービスのサポート

AddAuthentication メソッドにより、アプリ内での認証サービスが設定され、JWT ベアラー ハンドラーが既定の認証方法として構成されます。 AddMicrosoftIdentityWebApi メソッドによって、Microsoft Identity Platform v2.0 を使用して Web API を保護するようにサービスを構成できます。 このメソッドでは、認証オプションを初期化するために必要な設定で、アプリの構成の AzureAdB2C セクションが想定されます。

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAdB2C"));

UseAuthenticationUseAuthorization により、次のようになります。

  • アプリにより、受信要求のトークンの解析と検証が試みられます。
  • 適切な資格情報なしで保護されたリソースへのアクセスを試みた要求は失敗します。
app.UseAuthentication();
app.UseAuthorization();

User.Identity.Name

既定では、User.Identity.Name は設定されません。

name 要求の種類から値を受け取るようにアプリを構成するために、以下のようにします。

アプリの設定

appsettings.json ファイルには、アクセス トークンの検証に使用される JWT ベアラー ハンドラーを構成するためのオプションが含まれています。

{
  "AzureAdB2C": {
    "Instance": "https://{TENANT}.b2clogin.com/",
    "ClientId": "{SERVER API APP CLIENT ID}",
    "Domain": "{TENANT DOMAIN}",
    "SignUpSignInPolicyId": "{SIGN UP OR SIGN IN POLICY}"
  }
}

例:

{
  "AzureAdB2C": {
    "Instance": "https://contoso.b2clogin.com/",
    "ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd",
    "Domain": "contoso.onmicrosoft.com",
    "SignUpSignInPolicyId": "B2C_1_signupsignin1",
  }
}

WeatherForecast コントローラー

WeatherForecast コントローラー (Controllers/WeatherForecastController.cs) は、[Authorize] 属性 が適用されている保護された API をコントローラーに公開します。 次のことを理解しておくことが重要です。

  • この API コントローラーの [Authorize] 属性は、この API を不正アクセスから保護する唯一のものです。
  • Blazor WebAssembly アプリで使用される [Authorize] 属性は、アプリが正しく動作するにはユーザーを承認する必要がある、というアプリへのヒントとしてのみ機能します。
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        ...
    }
}

Client アプリの構成

"このセクションは、ソリューションの Client アプリに関連しています。 "

認証パッケージ

個人の 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 パッケージがアプリに推移的に追加されます。

認証サービスのサポート

サーバー プロジェクトへの要求を行うときのアクセス トークンが含まれる HttpClient インスタンスのサポートが追加されます。

Program.cs:

builder.Services.AddHttpClient("{APP ASSEMBLY}.ServerAPI", client => 
    client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
    .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
    .CreateClient("{APP ASSEMBLY}.ServerAPI"));

プレースホルダー {APP ASSEMBLY} は、アプリのアセンブリ名です (例: BlazorSample.Client)。

ユーザーの認証に対するサポートは、Microsoft.Authentication.WebAssembly.Msal パッケージによって提供される AddMsalAuthentication 拡張メソッドを使用して、サービス コンテナーに登録されます。 このメソッドでは、アプリが IdentityID プロバイダー (IP) とやり取りするために必要なサービスが設定されます。

Program.cs:

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication);
    options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});

AddMsalAuthentication メソッドでは、アプリを認証するために必要なパラメーターを構成するためのコールバックを受け入れます。 アプリを構成するために必要な値は、アプリを登録するときに Azure Portal の AAD の構成から取得できます。

構成は wwwroot/appsettings.json ファイルによって提供されます。

{
  "AzureAdB2C": {
    "Authority": "{AAD B2C INSTANCE}{TENANT DOMAIN}/{SIGN UP OR SIGN IN POLICY}",
    "ClientId": "{CLIENT APP CLIENT ID}",
    "ValidateAuthority": false
  }
}

例:

{
  "AzureAdB2C": {
    "Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_signupsignin1",
    "ClientId": "4369008b-21fa-427c-abaa-9b53bf58e538",
    "ValidateAuthority": false
  }
}

アクセス トークン スコープ

既定のアクセス トークン スコープでは、次のようなアクセス トークン スコープの一覧が表されます。

  • サインイン要求に既定で含まれます。
  • 認証直後にアクセス トークンをプロビジョニングするために使用されます。

すべてのスコープは、Azure Active Directory の規則に従って同じアプリに属している必要があります。 必要に応じて追加の API アプリ用に追加のスコープを追加できます。

builder.Services.AddMsalAuthentication(options =>
{
    ...
    options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});

Note

dotnet new コマンドに渡されるアプリ ID URI 引数に、Blazor WebAssembly テンプレートによって api:// のスキームが自動的に追加されます。 Blazor プロジェクト テンプレートからアプリを生成するときは、既定のアクセス トークン スコープの値で、Azure portal で指定した正しいカスタム アプリ ID URI の値、または次のいずれかの形式の値が使用されていることを確認します。

  • ディレクトリの発行元ドメインが信頼されている場合は、通常、既定のアクセス トークンのスコープは次の例のような値になります。API.Access は既定のスコープ名です。

    options.ProviderOptions.DefaultAccessTokenScopes.Add(
        "api://41451fa7-82d9-4673-8fa5-69eff5a761fd/API.Access");
    

    二重スキーム (api://api://...) の値を調べます。 二重スキームが存在する場合は、最初の api:// スキームを値から削除します。

  • ディレクトリの発行元ドメインが信頼されていない場合は、通常、既定のアクセス トークンのスコープは次の例のような値になります。API.Access は既定のスコープ名です。

    options.ProviderOptions.DefaultAccessTokenScopes.Add(
        "https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd/API.Access");
    

    余分な api:// スキーム (api://https://contoso.onmicrosoft.com/...) の値を調べます。 余分な api:// スキームが存在する場合は、api:// スキームを値から削除します。

Blazor WebAssembly テンプレートは、このようなシナリオに対応するため、ASP.NET Core の今後のリリースで変更される可能性があります。 詳細については、「Blazor WASM テンプレートでのアプリ ID URI 用の二重スキーム (ホストされた、単一組織) (dotnet/aspnetcore #27417)」を参照してください。

AdditionalScopesToConsent を使用して追加のスコープを指定します。

options.ProviderOptions.AdditionalScopesToConsent.Add("{ADDITIONAL SCOPE URI}");

詳細については、"その他のシナリオ" に関する記事の次のセクションを参照してください。

ログイン モード

フレームワークは、既定ではポップアップ ログイン モードになり、ポップアップを開くことができない場合はリダイレクト ログイン モードに戻ります。 MsalProviderOptionsLoginMode プロパティを 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}.Client
@using {APPLICATION ASSEMBLY}.Client.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) を検証します。

    注意

    通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

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)}");
    }
}

ASP.NET Core 7.0 で、Blazor WebAssembly アプリでの認証のサポートが変更され、URL のクエリ文字列ではなく履歴状態に依存するようになりました。 その結果、クエリ文字列を介して戻り先 URL を渡すと、ログインの成功後に元のページへのリダイレクトが失敗します。 代わりに NavigateToLogin 拡張メソッドを使用してください。 詳細については、「破壊的変更: WebAssembly アプリでの認証」を参照してください。

@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Microsoft.Extensions.Options

@inject IOptionsSnapshot<RemoteAuthenticationOptions<ApiAuthorizationProviderOptions>> Options
@code {
    protected override void OnInitialized()
    {
        Navigation.NavigateToLogin(Options.Get(Microsoft.Extensions.Options.Options.DefaultName).AuthenticationPaths.LogInPath);
    }
}

LoginDisplay コンポーネント

LoginDisplay コンポーネント (Shared/LoginDisplay.razor) は MainLayout コンポーネント (Shared/MainLayout.razor) でレンダリングされます。このコンポーネントによって次の動作が管理されます。

  • 認証されたユーザーの場合:
    • 現在のユーザー名が表示されます。
    • アプリからログアウトするためのボタンが用意されます。
  • 匿名ユーザーの場合は、ログインするオプションが用意されます。

ASP.NET Core のリリースごとにフレームワークに違いがあるため、LoginDisplay コンポーネントの Razor マークアップは、このセクションでは説明しません。 特定のリリース向けのコンポーネントのマークアップを調べる場合は、次の方法の ''いずれか'' を使用してください。

  • 使用しようとしている ASP.NET Core のバージョン向けの既定の Blazor WebAssembly プロジェクト テンプレートから、認証のためにプロビジョニングされたアプリを作成します。 作成されたアプリで、LoginDisplay コンポーネントを検証します。

  • 参照元で、LoginDisplay コンポーネントを検証します。

    注意

    通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

認証コンポーネント

Authentication コンポーネント (Pages/Authentication.razor) によって生成されるページによって、さまざまな認証ステージを処理するために必要なルートが定義されます。

RemoteAuthenticatorView コンポーネント:

@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

<RemoteAuthenticatorView Action="@Action" />

@code {
    [Parameter]
    public string Action { get; set; }
}

FetchData コンポーネント

FetchData コンポーネントは次の方法を示します。

  • アクセス トークンをプロビジョニングする。
  • アクセス トークンを使用して、Server アプリで保護されたリソース API を呼び出す。

@attribute [Authorize] ディレクティブは、このコンポーネントにアクセスするためにユーザーを承認する必要があることを Blazor WebAssembly の承認システムに示します。 Client アプリに属性が存在しても、適切な資格情報を使用せずにサーバー上の API が呼び出されるのを防ぐことはできません。 また、Server アプリは、適切なエンドポイントでそれを正しく保護するために [Authorize] も使用する必要があります。

IAccessTokenProvider.RequestAccessToken は、API を呼び出すために要求に追加できるアクセス トークンの要求を処理します。 トークンがキャッシュされている場合、またはサービスがユーザーの操作なしで新しいアクセス トークンをプロビジョニングできる場合、トークン要求は成功します。 それ以外の場合、トークン要求は、try-catch ステートメントでキャッチされた AccessTokenNotAvailableException により失敗します。

要求に含める実際のトークンを取得するには、アプリが tokenResult.TryGetToken(out var token) を呼び出して、要求が成功したことを確認する必要があります。

要求が成功すると、トークン変数にアクセス トークンが設定されます。 トークンの AccessToken.Value プロパティは、Authorization 要求ヘッダーに含めるリテラル文字列を公開します。

ユーザーの操作なしでトークンをプロビジョニングできなかったために要求が失敗した場合:

  • ASP.NET Core 7.0 以降: 指定された AccessTokenResult.InteractionOptions を使用してアプリは AccessTokenResult.InteractiveRequestUrl に移動し、アクセス トークンの更新を許可します。
  • ASP.NET Core 6.0 以前: トークン結果にはリダイレクト URL が含まれます。 この URL に移動すると、認証が成功した後、ユーザーがログイン ページに移動してから、現在のページに戻ります。
@page "/fetchdata"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using {APP NAMESPACE}.Shared
@attribute [Authorize]
@inject HttpClient Http

...

@code {
    private WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }
}

アプリを実行する

サーバー プロジェクトからアプリを実行します。 Visual Studio を使用しているときは、次のいずれかを行います。

  • ツール バーの [スタートアップ プロジェクト] ドロップダウン リストを "サーバー API アプリ" に設定して、 [実行] ボタンを選択します。
  • ソリューション エクスプローラーでサーバー プロジェクトを選択し、ツール バーの [実行] ボタンを選択するか、 [デバッグ] メニューからアプリを開始します。

カスタム ユーザー フロー

Microsoft 認証ライブラリ (Microsoft.Authentication.WebAssembly.MsalNuGet パッケージ) は、既定で AAD B2C ユーザー フローをサポートしていません。 開発者コードでカスタム ユーザー フローを作成してください。

カスタム ユーザー フローのチャレンジを構築する方法の詳細については、「Azure Active Directory B2C のユーザー フロー」を参照してください。

トラブルシューティング

一般的なエラー

  • アプリまたは Identity プロバイダー (IP) の構成の誤り

    最も一般的なエラーの原因は、構成の誤りです。 以下に例を示します。

    • シナリオの要件によっては、権限、インスタンス、テナント ID、テナント ドメイン、クライアント ID、またはリダイレクト URI の欠落または誤りによって、アプリによるクライアントの認証ができなくなります。
    • アクセス トークン スコープが正しくないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
    • サーバー API のアクセス許可が正しくないか、存在しないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
    • Identity プロバイダーのアプリ登録のリダイレクト URI で構成されているものとは異なるポートでアプリが実行されています。

    この記事のガイダンスの構成セクションに、正しい構成の例を示します。 記事の各セクションを慎重に確認して、アプリと IP の構成の誤りを探してください。

    構成が正しい場合:

    • アプリケーション ログを分析します。

    • ブラウザーの開発者ツールを使用して、クライアント アプリと IP またはサーバー アプリの間のネットワーク トラフィックを確認します。 多くの場合、要求を行った後、IP またはサーバー アプリによって、問題の原因を特定する手掛かりを含む正確なエラー メッセージまたはメッセージがクライアントに返されます。 開発者ツールのガイダンスは、次の記事にあります。

    • 問題が発生している場所に応じて、クライアントの認証またはサーバー 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.

    このエラーを解決するには:

    1. Azure portal で、アプリのマニフェストにアクセスします。
    2. 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
    • [引数] フィールドに、ブラウザーをシークレットまたはプライベート モードで開くために使用するコマンドライン オプションを指定します。 ブラウザーによっては、アプリの 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 など) です。
    • [フレンドリ名] フィールドに名前を指定します。 たとえば、Firefox Auth Testing のようにします。
    • [OK] ボタンを選択します。
    • アプリでテストを繰り返すたびにブラウザー プロファイルを選択する必要がないようにするには、 [既定値として設定] ボタンでプロファイルを既定値として設定します。
    • アプリ、テスト ユーザー、またはプロバイダー構成が変更されるたびに、ブラウザーが IDE によって閉じられていることを確認します。

アプリのアップグレード

開発マシンで .NET Core SDK をアップグレードしたり、アプリ内のパッケージ バージョンを変更したりした直後に、機能しているアプリが失敗することがあります。 場合によっては、パッケージに統一性がないと、メジャー アップグレード実行時にアプリが破壊されることがあります。 これらの問題のほとんどは、次の手順で解決できます。

  1. コマンド シェルから dotnet nuget locals all --clear を実行して、ローカル システムの NuGet パッケージ キャッシュをクリアします。
  2. プロジェクトのフォルダー binobj を削除します。
  3. プロジェクトを復元してリビルドします。
  4. アプリを再展開する前に、サーバー上の展開フォルダー内のすべてのファイルを削除します。

Note

アプリのターゲット フレームワークと互換性のないパッケージ バージョンの使用はサポートされていません。 パッケージの詳細については、NuGet ギャラリーまたは FuGet パッケージ エクスプローラーを使用してください。

Server アプリを実行する

ホステッド Blazor WebAssemblyソリューションのテストとトラブルシューティングを行うときは、Server プロジェクトからアプリを実行していることをご確認ください。 たとえば、Visual Studio で、次のいずれかの方法を使用してアプリを起動する前に、Server プロジェクトがソリューション エクスプローラーで強調表示されていることを確認します。

  • [実行] ボタンを選択します。
  • メニューの、 [デバッグ]>[デバッグ開始] を使用します。
  • F5キーを押します。

ユーザーを検査する

ASP.NET Core フレームワークのテスト アセットには、トラブルシューティングに役立つ Blazor WebAssembly クライアント アプリUser コンポーネントが含まれます。 User コンポーネントは、アプリ内で直接使うことも、さらにカスタマイズするための基礎として使うこともできます。

dotnet/aspnetcore GitHub リポジトリの User テスト コンポーネント

注意

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

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]

その他の技術情報

AAD B2C でアプリを登録してソリューションを作成する

テナントの作成

チュートリアル: Azure Active Directory B2C テナントの作成」のガイダンスに従って、AAD B2C テナントを作成します。 使用するテナントを作成または特定した直後に、この記事に戻ります。

AAD B2C インスタンスを記録しておきます (例: 末尾にスラッシュが含まれている https://contoso.b2clogin.com/)。 インスタンスは、Azure B2C アプリの登録のスキームとホストです。これは、Azure portal で [アプリの登録] ページから [エンドポイント] ウィンドウを開くことによって見つけることができます。

サーバー API アプリを登録する

"サーバー API アプリ" 用の AAD B2C アプリを登録します。

  1. Azure portal で [Azure Active Directory] に移動します。 サイドバーで [アプリの登録] を選択します。 [新規登録] ボタンを選択します。
  2. アプリの [名前] を指定します (例: Blazor Server AAD B2C)。
  3. [サポートされているアカウントの種類] で、マルチテナント オプションを選択します: ID プロバイダーまたは組織ディレクトリのアカウント (ユーザー フローでユーザーを認証するため)
  4. "サーバー API アプリ" の場合、このシナリオでは [リダイレクト URI] は必要ないので、ドロップダウンは [Web] に設定されたままにして、リダイレクト URI は入力しません。
  5. 未確認の発行元ドメインを使用している場合は、 [アクセス許可]>[openid と offline_access アクセス許可に対して管理者の同意を付与します] が選択されていることを確認します。 発行元ドメインが検証済みの場合、このチェックボックスは表示されません。
  6. [登録] を選択します。

次の情報を記録しておきます。

  • "サーバー API アプリ" のアプリケーション (クライアント) ID (例: 41451fa7-82d9-4673-8fa5-69eff5a761fd)
  • AAD プライマリ、パブリッシャー、テナント ドメイン (contoso.onmicrosoft.com など):ドメインは、Azure portal で登録されているアプリに対する [ブランド] ブレードの [パブリッシャー ドメイン] として使用できます。

[API の公開] で:

  1. [Scope の追加] を選択します。
  2. [Save and continue](保存して続行) を選択します。
  3. [スコープ名] を指定します (例: API.Access)。
  4. [管理者の同意の表示名] を指定します (例: Access API)。
  5. [管理者の同意の説明] を指定します (例: Allows the app to access server app API endpoints.)。
  6. [状態][有効] に設定されていることを確認します。
  7. [スコープの追加] を選択します。

次の情報を記録しておきます。

  • アプリ ID の URI (例: api://41451fa7-82d9-4673-8fa5-69eff5a761fdhttps://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd、または指定したカスタム値)
  • スコープ名 (例: API.Access)

クライアント アプリを登録する

"クライアント アプリ" 用の AAD B2C アプリを登録します。

  1. Azure portal で [Azure Active Directory] に移動します。 サイドバーで [アプリの登録] を選択します。 [新規登録] ボタンを選択します。
  2. アプリの [名前] を指定します (例: Blazor クライアント AAD B2C)。
  3. [サポートされているアカウントの種類] で、マルチテナント オプションを選択します: ID プロバイダーまたは組織ディレクトリのアカウント (ユーザー フローでユーザーを認証するため)
  4. [リダイレクト URI] ドロップ ダウンの設定を [Web] のままとし、次のリダイレクト URI を指定します: https://localhost/authentication/login-callback。 Azure の既定のホスト (たとえば azurewebsites.net) またはカスタム ドメイン ホスト (たとえば contoso.com) の運用リダイレクト URI がわかっている場合は、localhost リダイレクト URI を提供するのと同時に運用リダイレクト URI を追加することもできます。 追加する運用リダイレクト URI には、ポート:443 以外のポートのポート番号を必ず含めてください。
  5. 未確認の発行元ドメインを使用している場合は、 [アクセス許可]>[openid と offline_access アクセス許可に対して管理者の同意を付与します] が選択されていることを確認します。 発行元ドメインが検証済みの場合、このチェックボックスは表示されません。
  6. [登録] を選択します。

Note

localhost AAD B2C リダイレクト URI のポート番号を指定する必要はありません。 詳細については、「リダイレクト URI (応答 URL) に関する制約と制限」の「Localhost 例外」(Azure ドキュメント) を参照してください。

アプリケーション (クライアント) ID を記録しておきます (例: 4369008b-21fa-427c-abaa-9b53bf58e538)。

[認証]>[プラットフォーム構成]>[Web] で、次を行います。

  1. [リダイレクト URI]https://localhost/authentication/login-callback であることを確認します。
  2. [暗黙の付与] セクションで、[アクセス トークン][ID トークン] のチェックボックスをオンにします。
  3. アプリの残りの既定値は、このエクスペリエンスで使用可能です。
  4. [保存] ボタンを選択します。

[API のアクセス許可] で:

  1. [アクセス許可の追加] を選択し、 [自分の API] を選択します。
  2. [名前] 列で "サーバー API アプリ" を選択します (例: Blazor Server AAD B2C)。
  3. [API] の一覧を開きます。
  4. API へのアクセスを有効にします (例: API.Access)。
  5. [アクセス許可の追加] を選択します.
  6. [<テナント名> に管理者の同意を与えます] ボタンを選択します。 [はい] を選択して確定します。

重要

アプリの使用に対する同意がユーザーに委任されたため、API アクセス許可の構成の最後の手順でテナントに管理者の同意を付与する権限を持っていなかった場合は、次の追加の手順を実行する必要があります。

  • アプリでは、信頼された発行元ドメインを使用する必要があります。
  • Azure portal の Server アプリの構成で、[API の公開] を選択します。 [認可済みのクライアント アプリケーション] で、[クライアント アプリケーションの追加] ボタンを選択します。 Client アプリのアプリケーション (クライアント) ID を追加します (例: 4369008b-21fa-427c-abaa-9b53bf58e538)。

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}" --api-client-id "{SERVER API APP CLIENT ID}" --app-id-uri "{SERVER API APP ID URI}" --client-id "{CLIENT APP CLIENT ID}" --default-scope "{DEFAULT SCOPE}" --domain "{TENANT DOMAIN}" -ho -o {APP NAME} -ssp "{SIGN UP OR SIGN IN POLICY}"

警告

OIDC アプリ識別子の形成を妨げるダッシュ (-) をアプリ名 {APP NAME} に使用しないでください。 Blazor WebAssembly プロジェクト テンプレート内のロジックでは、ソリューションの構成内の OIDC アプリ識別子にプロジェクト名を使用します。 パスカル ケース (BlazorSample) またはアンダースコア (Blazor_Sample) は許容可能な代替手段です 詳細については、ホストされた Blazor WebAssembly プロジェクト名に含まれるダッシュによって OIDC のセキュリティが破られる (dotnet/aspnetcore #35337)を参照してください。

プレースホルダー Azure portal での名前
{AAD B2C INSTANCE} インスタンス https://contoso.b2clogin.com/
{APP NAME} BlazorSample
{CLIENT APP CLIENT ID} Client アプリのアプリケーション (クライアント) ID 4369008b-21fa-427c-abaa-9b53bf58e538
{DEFAULT SCOPE} スコープ名 API.Access
{SERVER API APP CLIENT ID} "サーバー API アプリ" のアプリケーション (クライアント) ID 41451fa7-82d9-4673-8fa5-69eff5a761fd
{SERVER API APP ID URI} アプリケーション ID の URI† 41451fa7-82d9-4673-8fa5-69eff5a761fd
{SIGN UP OR SIGN IN POLICY} サインアップまたはサインインのユーザー フロー B2C_1_signupsignin1
{TENANT DOMAIN} プライマリ、パブリッシャー、テナント ドメイン contoso.onmicrosoft.com

dotnet new コマンドに渡されるアプリ ID URI 引数に、Blazor WebAssembly テンプレートによって api:// のスキームが自動的に追加されます。 {SERVER API APP ID URI} プレースホルダーでアプリ ID URI を指定し、スキームが api:// の場合は、上記の表の例の値に示すように、引数からスキーム (api://) を削除します。 アプリ ID URI がカスタム値の場合、または他の何らかのスキームである場合 (たとえば、https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd のような未確認の発行元ドメインhttps://) は、既定のスコープ URI を手動で更新し、テンプレートによって Client アプリが作成された後で、api:// スキームを削除する必要があります。 詳細については、「アクセス トークン スコープ」セクションの注を参照してください。 Blazor WebAssembly テンプレートは、このようなシナリオに対応するため、ASP.NET Core の今後のリリースで変更される可能性があります。 詳細については、「Blazor WASM テンプレートでのアプリ ID URI 用の二重スキーム (ホストされた、単一組織) (dotnet/aspnetcore #27417)」を参照してください。

-o|--output オプションで指定した出力場所にプロジェクト フォルダーが存在しない場合は作成されて、アプリの名前の一部になります。 OIDC アプリ識別子の形成を妨げるダッシュ (-) をアプリ名に使用しないでください (前述の警告を参照)。

注意

Blazor WebAssembly プロジェクト テンプレートによってホストされている Blazor WebAssembly ソリューションで設定されるスコープでは、アプリ ID URI ホストが繰り返される場合があります。 DefaultAccessTokenScopes コレクションに対して構成されたスコープが Client アプリの Program.cs で正しいことを確認します。

Server アプリの構成

"このセクションは、ソリューションの Server アプリに関連しています。 "

認証パッケージ

ASP.NET Core Web API の呼び出しの認証と承認のサポートは、Microsoft.AspNetCore.Authentication.AzureADB2C.UI パッケージによって提供されます。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。

認証サービスのサポート

AddAuthentication メソッドにより、アプリ内での認証サービスが設定され、JWT ベアラー ハンドラーが既定の認証方法として構成されます。 AddAzureADB2CBearer メソッドにより、Azure Active Directory B2C によって送信されるトークンを検証するために必要な JWT ベアラー ハンドラーの特定のパラメーターが設定されます。

services.AddAuthentication(AzureADB2CDefaults.BearerAuthenticationScheme)
    .AddAzureADB2CBearer(options => Configuration.Bind("AzureAdB2C", options));

UseAuthenticationUseAuthorization により、次のようになります。

  • アプリにより、受信要求のトークンの解析と検証が試みられます。
  • 適切な資格情報なしで保護されたリソースへのアクセスを試みた要求は失敗します。
app.UseAuthentication();
app.UseAuthorization();

User.Identity.Name

既定では、User.Identity.Name は設定されません。

name 要求の種類から値を受け取るようにアプリを構成するために、以下のようにします。

アプリの設定

appsettings.json ファイルには、アクセス トークンの検証に使用される JWT ベアラー ハンドラーを構成するためのオプションが含まれています。

{
  "AzureAdB2C": {
    "Instance": "https://{TENANT}.b2clogin.com/",
    "ClientId": "{SERVER API APP CLIENT ID}",
    "Domain": "{TENANT DOMAIN}",
    "SignUpSignInPolicyId": "{SIGN UP OR SIGN IN POLICY}"
  }
}

例:

{
  "AzureAdB2C": {
    "Instance": "https://contoso.b2clogin.com/",
    "ClientId": "41451fa7-82d9-4673-8fa5-69eff5a761fd",
    "Domain": "contoso.onmicrosoft.com",
    "SignUpSignInPolicyId": "B2C_1_signupsignin1",
  }
}

WeatherForecast コントローラー

WeatherForecast コントローラー (Controllers/WeatherForecastController.cs) は、[Authorize] 属性 が適用されている保護された API をコントローラーに公開します。 次のことを理解しておくことが重要です。

  • この API コントローラーの [Authorize] 属性は、この API を不正アクセスから保護する唯一のものです。
  • Blazor WebAssembly アプリで使用される [Authorize] 属性は、アプリが正しく動作するにはユーザーを承認する必要がある、というアプリへのヒントとしてのみ機能します。
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        ...
    }
}

Client アプリの構成

"このセクションは、ソリューションの Client アプリに関連しています。 "

認証パッケージ

個人の 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 パッケージがアプリに推移的に追加されます。

認証サービスのサポート

サーバー プロジェクトへの要求を行うときのアクセス トークンが含まれる HttpClient インスタンスのサポートが追加されます。

Program.cs:

builder.Services.AddHttpClient("{APP ASSEMBLY}.ServerAPI", client => 
    client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
    .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
    .CreateClient("{APP ASSEMBLY}.ServerAPI"));

プレースホルダー {APP ASSEMBLY} は、アプリのアセンブリ名です (例: BlazorSample.Client)。

ユーザーの認証に対するサポートは、Microsoft.Authentication.WebAssembly.Msal パッケージによって提供される AddMsalAuthentication 拡張メソッドを使用して、サービス コンテナーに登録されます。 このメソッドでは、アプリが IdentityID プロバイダー (IP) とやり取りするために必要なサービスが設定されます。

Program.cs:

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication);
    options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});

AddMsalAuthentication メソッドでは、アプリを認証するために必要なパラメーターを構成するためのコールバックを受け入れます。 アプリを構成するために必要な値は、アプリを登録するときに Azure Portal の AAD の構成から取得できます。

構成は wwwroot/appsettings.json ファイルによって提供されます。

{
  "AzureAdB2C": {
    "Authority": "{AAD B2C INSTANCE}{TENANT DOMAIN}/{SIGN UP OR SIGN IN POLICY}",
    "ClientId": "{CLIENT APP CLIENT ID}",
    "ValidateAuthority": false
  }
}

例:

{
  "AzureAdB2C": {
    "Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_signupsignin1",
    "ClientId": "4369008b-21fa-427c-abaa-9b53bf58e538",
    "ValidateAuthority": false
  }
}

アクセス トークン スコープ

既定のアクセス トークン スコープでは、次のようなアクセス トークン スコープの一覧が表されます。

  • サインイン要求に既定で含まれます。
  • 認証直後にアクセス トークンをプロビジョニングするために使用されます。

すべてのスコープは、Azure Active Directory の規則に従って同じアプリに属している必要があります。 必要に応じて追加の API アプリ用に追加のスコープを追加できます。

builder.Services.AddMsalAuthentication(options =>
{
    ...
    options.ProviderOptions.DefaultAccessTokenScopes.Add("{SCOPE URI}");
});

Note

dotnet new コマンドに渡されるアプリ ID URI 引数に、Blazor WebAssembly テンプレートによって api:// のスキームが自動的に追加されます。 Blazor プロジェクト テンプレートからアプリを生成するときは、既定のアクセス トークン スコープの値で、Azure portal で指定した正しいカスタム アプリ ID URI の値、または次のいずれかの形式の値が使用されていることを確認します。

  • ディレクトリの発行元ドメインが信頼されている場合は、通常、既定のアクセス トークンのスコープは次の例のような値になります。API.Access は既定のスコープ名です。

    options.ProviderOptions.DefaultAccessTokenScopes.Add(
        "api://41451fa7-82d9-4673-8fa5-69eff5a761fd/API.Access");
    

    二重スキーム (api://api://...) の値を調べます。 二重スキームが存在する場合は、最初の api:// スキームを値から削除します。

  • ディレクトリの発行元ドメインが信頼されていない場合は、通常、既定のアクセス トークンのスコープは次の例のような値になります。API.Access は既定のスコープ名です。

    options.ProviderOptions.DefaultAccessTokenScopes.Add(
        "https://contoso.onmicrosoft.com/41451fa7-82d9-4673-8fa5-69eff5a761fd/API.Access");
    

    余分な api:// スキーム (api://https://contoso.onmicrosoft.com/...) の値を調べます。 余分な api:// スキームが存在する場合は、api:// スキームを値から削除します。

Blazor WebAssembly テンプレートは、このようなシナリオに対応するため、ASP.NET Core の今後のリリースで変更される可能性があります。 詳細については、「Blazor WASM テンプレートでのアプリ ID URI 用の二重スキーム (ホストされた、単一組織) (dotnet/aspnetcore #27417)」を参照してください。

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}.Client
@using {APPLICATION ASSEMBLY}.Client.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) を検証します。

    注意

    通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

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)}");
    }
}

ASP.NET Core 7.0 で、Blazor WebAssembly アプリでの認証のサポートが変更され、URL のクエリ文字列ではなく履歴状態に依存するようになりました。 その結果、クエリ文字列を介して戻り先 URL を渡すと、ログインの成功後に元のページへのリダイレクトが失敗します。 代わりに NavigateToLogin 拡張メソッドを使用してください。 詳細については、「破壊的変更: WebAssembly アプリでの認証」を参照してください。

@inject NavigationManager Navigation
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Microsoft.Extensions.Options

@inject IOptionsSnapshot<RemoteAuthenticationOptions<ApiAuthorizationProviderOptions>> Options
@code {
    protected override void OnInitialized()
    {
        Navigation.NavigateToLogin(Options.Get(Microsoft.Extensions.Options.Options.DefaultName).AuthenticationPaths.LogInPath);
    }
}

LoginDisplay コンポーネント

LoginDisplay コンポーネント (Shared/LoginDisplay.razor) は MainLayout コンポーネント (Shared/MainLayout.razor) でレンダリングされます。このコンポーネントによって次の動作が管理されます。

  • 認証されたユーザーの場合:
    • 現在のユーザー名が表示されます。
    • アプリからログアウトするためのボタンが用意されます。
  • 匿名ユーザーの場合は、ログインするオプションが用意されます。

ASP.NET Core のリリースごとにフレームワークに違いがあるため、LoginDisplay コンポーネントの Razor マークアップは、このセクションでは説明しません。 特定のリリース向けのコンポーネントのマークアップを調べる場合は、次の方法の ''いずれか'' を使用してください。

  • 使用しようとしている ASP.NET Core のバージョン向けの既定の Blazor WebAssembly プロジェクト テンプレートから、認証のためにプロビジョニングされたアプリを作成します。 作成されたアプリで、LoginDisplay コンポーネントを検証します。

  • 参照元で、LoginDisplay コンポーネントを検証します。

    注意

    通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

認証コンポーネント

Authentication コンポーネント (Pages/Authentication.razor) によって生成されるページによって、さまざまな認証ステージを処理するために必要なルートが定義されます。

RemoteAuthenticatorView コンポーネント:

@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

<RemoteAuthenticatorView Action="@Action" />

@code {
    [Parameter]
    public string Action { get; set; }
}

FetchData コンポーネント

FetchData コンポーネントは次の方法を示します。

  • アクセス トークンをプロビジョニングする。
  • アクセス トークンを使用して、Server アプリで保護されたリソース API を呼び出す。

@attribute [Authorize] ディレクティブは、このコンポーネントにアクセスするためにユーザーを承認する必要があることを Blazor WebAssembly の承認システムに示します。 Client アプリに属性が存在しても、適切な資格情報を使用せずにサーバー上の API が呼び出されるのを防ぐことはできません。 また、Server アプリは、適切なエンドポイントでそれを正しく保護するために [Authorize] も使用する必要があります。

IAccessTokenProvider.RequestAccessToken は、API を呼び出すために要求に追加できるアクセス トークンの要求を処理します。 トークンがキャッシュされている場合、またはサービスがユーザーの操作なしで新しいアクセス トークンをプロビジョニングできる場合、トークン要求は成功します。 それ以外の場合、トークン要求は、try-catch ステートメントでキャッチされた AccessTokenNotAvailableException により失敗します。

要求に含める実際のトークンを取得するには、アプリが tokenResult.TryGetToken(out var token) を呼び出して、要求が成功したことを確認する必要があります。

要求が成功すると、トークン変数にアクセス トークンが設定されます。 トークンの AccessToken.Value プロパティは、Authorization 要求ヘッダーに含めるリテラル文字列を公開します。

ユーザーの操作なしでトークンをプロビジョニングできなかったために要求が失敗した場合:

  • ASP.NET Core 7.0 以降: 指定された AccessTokenResult.InteractionOptions を使用してアプリは AccessTokenResult.InteractiveRequestUrl に移動し、アクセス トークンの更新を許可します。
  • ASP.NET Core 6.0 以前: トークン結果にはリダイレクト URL が含まれます。 この URL に移動すると、認証が成功した後、ユーザーがログイン ページに移動してから、現在のページに戻ります。
@page "/fetchdata"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using {APP NAMESPACE}.Shared
@attribute [Authorize]
@inject HttpClient Http

...

@code {
    private WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }
}

アプリを実行する

サーバー プロジェクトからアプリを実行します。 Visual Studio を使用しているときは、次のいずれかを行います。

  • ツール バーの [スタートアップ プロジェクト] ドロップダウン リストを "サーバー API アプリ" に設定して、 [実行] ボタンを選択します。
  • ソリューション エクスプローラーでサーバー プロジェクトを選択し、ツール バーの [実行] ボタンを選択するか、 [デバッグ] メニューからアプリを開始します。

カスタム ユーザー フロー

Microsoft 認証ライブラリ (Microsoft.Authentication.WebAssembly.MsalNuGet パッケージ) は、既定で AAD B2C ユーザー フローをサポートしていません。 開発者コードでカスタム ユーザー フローを作成してください。

カスタム ユーザー フローのチャレンジを構築する方法の詳細については、「Azure Active Directory B2C のユーザー フロー」を参照してください。

トラブルシューティング

一般的なエラー

  • アプリまたは Identity プロバイダー (IP) の構成の誤り

    最も一般的なエラーの原因は、構成の誤りです。 以下に例を示します。

    • シナリオの要件によっては、権限、インスタンス、テナント ID、テナント ドメイン、クライアント ID、またはリダイレクト URI の欠落または誤りによって、アプリによるクライアントの認証ができなくなります。
    • アクセス トークン スコープが正しくないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
    • サーバー API のアクセス許可が正しくないか、存在しないと、クライアントがサーバー Web API エンドポイントにアクセスできなくなります。
    • Identity プロバイダーのアプリ登録のリダイレクト URI で構成されているものとは異なるポートでアプリが実行されています。

    この記事のガイダンスの構成セクションに、正しい構成の例を示します。 記事の各セクションを慎重に確認して、アプリと IP の構成の誤りを探してください。

    構成が正しい場合:

    • アプリケーション ログを分析します。

    • ブラウザーの開発者ツールを使用して、クライアント アプリと IP またはサーバー アプリの間のネットワーク トラフィックを確認します。 多くの場合、要求を行った後、IP またはサーバー アプリによって、問題の原因を特定する手掛かりを含む正確なエラー メッセージまたはメッセージがクライアントに返されます。 開発者ツールのガイダンスは、次の記事にあります。

    • 問題が発生している場所に応じて、クライアントの認証またはサーバー 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.

    このエラーを解決するには:

    1. Azure portal で、アプリのマニフェストにアクセスします。
    2. 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
    • [引数] フィールドに、ブラウザーをシークレットまたはプライベート モードで開くために使用するコマンドライン オプションを指定します。 ブラウザーによっては、アプリの 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 など) です。
    • [フレンドリ名] フィールドに名前を指定します。 たとえば、Firefox Auth Testing のようにします。
    • [OK] ボタンを選択します。
    • アプリでテストを繰り返すたびにブラウザー プロファイルを選択する必要がないようにするには、 [既定値として設定] ボタンでプロファイルを既定値として設定します。
    • アプリ、テスト ユーザー、またはプロバイダー構成が変更されるたびに、ブラウザーが IDE によって閉じられていることを確認します。

アプリのアップグレード

開発マシンで .NET Core SDK をアップグレードしたり、アプリ内のパッケージ バージョンを変更したりした直後に、機能しているアプリが失敗することがあります。 場合によっては、パッケージに統一性がないと、メジャー アップグレード実行時にアプリが破壊されることがあります。 これらの問題のほとんどは、次の手順で解決できます。

  1. コマンド シェルから dotnet nuget locals all --clear を実行して、ローカル システムの NuGet パッケージ キャッシュをクリアします。
  2. プロジェクトのフォルダー binobj を削除します。
  3. プロジェクトを復元してリビルドします。
  4. アプリを再展開する前に、サーバー上の展開フォルダー内のすべてのファイルを削除します。

Note

アプリのターゲット フレームワークと互換性のないパッケージ バージョンの使用はサポートされていません。 パッケージの詳細については、NuGet ギャラリーまたは FuGet パッケージ エクスプローラーを使用してください。

Server アプリを実行する

ホステッド Blazor WebAssemblyソリューションのテストとトラブルシューティングを行うときは、Server プロジェクトからアプリを実行していることをご確認ください。 たとえば、Visual Studio で、次のいずれかの方法を使用してアプリを起動する前に、Server プロジェクトがソリューション エクスプローラーで強調表示されていることを確認します。

  • [実行] ボタンを選択します。
  • メニューの、 [デバッグ]>[デバッグ開始] を使用します。
  • F5キーを押します。

ユーザーを検査する

ASP.NET Core フレームワークのテスト アセットには、トラブルシューティングに役立つ Blazor WebAssembly クライアント アプリUser コンポーネントが含まれます。 User コンポーネントは、アプリ内で直接使うことも、さらにカスタマイズするための基礎として使うこともできます。

dotnet/aspnetcore GitHub リポジトリの User テスト コンポーネント

注意

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

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]

その他の技術情報