Azure AD B2C を使用して Web アプリの認証オプションを有効にする

この記事では、Web アプリケーションの Azure Active Directory B2C (Azure AD B2C) 認証エクスペリエンスの有効化、カスタマイズ、および拡張を行う方法について説明します。

開始する前に、次の記事をよく理解しておくことが重要です。

カスタム ドメインの使用

カスタム ドメインを使用すると、認証 URL を完全にブランド化できます。 ユーザーの観点からは、認証プロセスの間、ユーザーは Azure AD B2C b2clogin.com ドメイン名にリダイレクトされるのではなく、ドメインにとどまります。

URL 内の "b2c" へのすべての参照を削除するために、認証要求 URL の B2C テナント名 contoso.onmicrosoft.com をテナント ID GUID に置換することもできます。 たとえば、https://fabrikamb2c.b2clogin.com/contoso.onmicrosoft.com/https://account.contosobank.co.uk/<tenant ID GUID>/ に変更できます。

認証 URL でカスタム ドメインとテナント ID を使用するには、カスタム ドメインを有効にする方法に関するページのガイダンスに従ってください。 プロジェクトのルート フォルダーで、appsettings.json ファイルを開きます。 このファイルには、Azure AD B2C ID プロバイダーに関する情報が含まれています。

appsettings.json ファイルで、次の操作を行います。

次の JSON は、変更前のアプリ設定を示しています。

"AzureAdB2C": {
  "Instance": "https://contoso.b2clogin.com",
  "Domain": "tenant-name.onmicrosoft.com",
  ...
}

次の JSON は、変更後のアプリ設定を示しています。

"AzureAdB2C": {
  "Instance": "https://login.contoso.com",
  "Domain": "00000000-0000-0000-0000-000000000000",
  ...
}

高度なシナリオをサポートする

Microsoft ID プラットフォーム API の AddMicrosoftIdentityWebAppAuthentication メソッドを使用すると、開発者は高度な認証シナリオ用のコードを追加したり、OpenIdConnect イベントをサブスクライブしたりできます。 たとえば、OnRedirectToIdentityProvider をサブスクライブすると、アプリから Azure AD B2C に送信される認証要求をカスタマイズできます。

高度なシナリオをサポートするには、Startup.cs ファイルを開き、ConfigureServices 関数で AddMicrosoftIdentityWebAppAuthentication を次のコード スニペットに置き換えます。

// Configuration to sign-in users with Azure AD B2C

//services.AddMicrosoftIdentityWebAppAuthentication(Configuration, "AzureAdB2C");

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(options =>
{
    Configuration.Bind("AzureAdB2C", options);
    options.Events ??= new OpenIdConnectEvents();
    options.Events.OnRedirectToIdentityProvider += OnRedirectToIdentityProviderFunc;
});

上のコードでは、OnRedirectToIdentityProviderFunc メソッドへの参照を含む OnRedirectToIdentityProvider イベントを追加しています。 Startup.cs クラスに、次のコード スニペットを追加します。

private async Task OnRedirectToIdentityProviderFunc(RedirectContext context)
{
    // Custom code here
    
    // Don't remove this line
    await Task.CompletedTask.ConfigureAwait(false);
}

コンテキスト パラメーターを使用して、コントローラーと OnRedirectToIdentityProvider 関数の間でパラメーターを渡すことができます。

サインイン名を事前入力する

サインイン ユーザー体験中に、アプリが特定のユーザーをターゲットにする場合があります。 アプリがユーザーを対象とする場合は、認証要求にユーザーのサインイン名を含む login_hint クエリ パラメーターを指定できます。 Azure AD B2C によってサインイン名が自動的に入力されるので、ユーザーはパスワードを入力するだけで済みます。

サインイン名を事前入力するには、次の手順を実行します。

  1. カスタム ポリシーを使用している場合は、直接サインインの設定に関する記事の説明に従って、必要な入力要求を追加します。

  2. 高度なシナリオをサポートする」の手順を完了します。

  3. OnRedirectToIdentityProvider 関数に次のコード行を追加します。

    private async Task OnRedirectToIdentityProviderFunc(RedirectContext context)
    {
      context.ProtocolMessage.LoginHint = "emily@contoso.com";
    
      // More code
      await Task.CompletedTask.ConfigureAwait(false);
    }
    

ID プロバイダーを事前に選択する

Facebook、LinkedIn、Google などのソーシャル アカウントを含むようにアプリケーションのサインイン プロセスを構成した場合は、domain_hint パラメーターを指定できます。 このクエリ パラメーターは、サインインに使用する必要があるソーシャル ID プロバイダーに関するヒントを Azure AD B2C に提供します。 たとえば、アプリケーションで domain_hint=facebook.com を指定した場合、サインイン フローで Facebook のサインイン ページに直接移動します。

外部 ID プロバイダーにユーザーをリダイレクトするには、以下を実行します。

  1. 外部 ID プロバイダーのドメイン名を確認します。 詳細については、「サインインをソーシャル プロバイダーにリダイレクトする」を参照してください。

  2. 高度なシナリオをサポートする」の手順を完了します。

  3. OnRedirectToIdentityProviderFunc 関数で、OnRedirectToIdentityProvider 関数に次のコード行を追加します。

    private async Task OnRedirectToIdentityProviderFunc(RedirectContext context)
    {
      context.ProtocolMessage.DomainHint = "facebook.com";
    
      // More code
      await Task.CompletedTask.ConfigureAwait(false);
    }
    

UI 言語を指定する

Azure AD B2C の言語のカスタマイズを使用すると、ユーザー フローで、顧客のニーズに合わせてさまざまな言語に対応できます。 詳細については、言語のカスタマイズに関する記事を参照してください。

優先する言語を設定するには、次のようにします。

  1. 言語のカスタマイズを構成します

  2. 高度なシナリオをサポートする」の手順を完了します。

  3. OnRedirectToIdentityProvider 関数に次のコード行を追加します。

    private async Task OnRedirectToIdentityProviderFunc(RedirectContext context)
    {
      context.ProtocolMessage.UiLocales = "es";
    
      // More code
      await Task.CompletedTask.ConfigureAwait(false);
    }
    

カスタム クエリ文字列パラメーターを渡す

カスタム ポリシーを利用するとき、カスタム クエリ文字列パラメーターを渡すことができます。 ページ コンテンツを動的に変化させるときにお勧めです。

カスタム クエリ文字列パラメーターを渡すには、次の手順に従います。

  1. ContentDefinitionParameters 要素を構成します。

  2. 高度なシナリオをサポートする」の手順を完了します。

  3. OnRedirectToIdentityProvider 関数に次のコード行を追加します。

    private async Task OnRedirectToIdentityProviderFunc(RedirectContext context)
    {
      context.ProtocolMessage.Parameters.Add("campaignId", "123");
    
      // More code
      await Task.CompletedTask.ConfigureAwait(false);
    }
    

ID トークン ヒントを渡す

証明書利用者アプリケーションからは、OAuth2 認可要求の一部としてインバウンド JSON Web トークン (JWT) を送信できます。 インバウンド トークンは、ユーザーまたは認可要求に関するヒントです。 Azure AD B2C によってトークンが検証された後、クレームが抽出されます。

認証要求に ID トークン ヒントを含めるには、次のようにします。

  1. 高度なシナリオをサポートする」の手順を完了します。

  2. カスタム ポリシーで、ID トークン ヒントの技術プロファイルを定義します。

  3. OnRedirectToIdentityProvider 関数に次のコード行を追加します。

    private async Task OnRedirectToIdentityProviderFunc(RedirectContext context)
    {
      // The idTokenHint variable holds your ID token 
      context.ProtocolMessage.IdTokenHint = idTokenHint
    
      // More code
      await Task.CompletedTask.ConfigureAwait(false);
    }
    

アカウント コントローラー

SignInSignUp、または SignOut アクションをカスタマイズする場合は、独自のコントローラーを作成することをお勧めします。 独自のコントローラーを使用すると、コントローラーと認証ライブラリの間でパラメーターを渡すことができます。 AccountController は、サインインおよびサインアウト アクションを処理する Microsoft.Identity.Web.UI NuGet パッケージの一部です。 その実装は、Microsoft Identity Web ライブラリで確認できます。

アカウント コントローラーを追加する

Visual Studio プロジェクトで、Controllers フォルダーを右クリックし、新しいコントローラーを追加します。 [MVC - Empty Controller]\(MVC - 空のコントローラー\) を選択し、MyAccountController.cs という名前を指定します。

次のコード スニペットは、SignIn アクションでのカスタム MyAccountController を示しています。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;


namespace mywebapp.Controllers
{
    [AllowAnonymous]
    [Area("MicrosoftIdentity")]
    [Route("[area]/[controller]/[action]")]
    public class MyAccountController : Controller
    {

        [HttpGet("{scheme?}")]
        public IActionResult SignIn([FromRoute] string scheme)
        {
            scheme ??= OpenIdConnectDefaults.AuthenticationScheme;
            var redirectUrl = Url.Content("~/");
            var properties = new AuthenticationProperties { RedirectUri = redirectUrl };
            return Challenge(properties, scheme);
        }

    }
}

_LoginPartial.cshtml ビューで、コントローラーへのサインイン リンクを変更します。

<form method="get" asp-area="MicrosoftIdentity" asp-controller="MyAccount" asp-action="SignIn">

Azure AD B2C ポリシー ID を渡す

次のコード スニペットは、SignInSignUp アクションでのカスタム MyAccountController を示しています。 このアクションでは、policy という名前のパラメーターを認証ライブラリに渡します。 これにより、特定のアクションに対して正しい Azure AD B2C ポリシー ID を指定できます。

public IActionResult SignIn([FromRoute] string scheme)
{
    scheme ??= OpenIdConnectDefaults.AuthenticationScheme;
    var redirectUrl = Url.Content("~/");
    var properties = new AuthenticationProperties { RedirectUri = redirectUrl };
    properties.Items["policy"] = "B2C_1_SignIn";
    return Challenge(properties, scheme);
}

public IActionResult SignUp([FromRoute] string scheme)
{
    scheme ??= OpenIdConnectDefaults.AuthenticationScheme;
    var redirectUrl = Url.Content("~/");
    var properties = new AuthenticationProperties { RedirectUri = redirectUrl };
    properties.Items["policy"] = "B2C_1_SignUp";
    return Challenge(properties, scheme);
}

_LoginPartial.cshtml ビューで、サインアップやプロファイルの編集など、他のすべての認証リンクに対して asp-controller 値を MyAccountController に変更します。

カスタム パラメーターを渡す

次のコード スニペットは、SignIn アクションでのカスタム MyAccountController を示しています。 このアクションでは、campaign_id という名前のパラメーターを認証ライブラリに渡します。

public IActionResult SignIn([FromRoute] string scheme)
{
    scheme ??= OpenIdConnectDefaults.AuthenticationScheme;
    var redirectUrl = Url.Content("~/");
    var properties = new AuthenticationProperties { RedirectUri = redirectUrl };
    properties.Items["policy"] = "B2C_1_SignIn";
    properties.Items["campaign_id"] = "1234";
    return Challenge(properties, scheme);
}

高度なシナリオをサポートする」の手順を完了してから、OnRedirectToIdentityProvider メソッドでカスタム パラメーターを読み取ります。

private async Task OnRedirectToIdentityProviderFunc(RedirectContext context)
{
    // Read the custom parameter
    var campaign_id = context.Properties.Items.FirstOrDefault(x => x.Key == "campaign_id").Value;

    // Add your custom code here
    if (campaign_id != null)
    {
        // Send parameter to authentication request
        context.ProtocolMessage.SetParameter("campaign_id", campaign_id);
    }
    
    await Task.CompletedTask.ConfigureAwait(false);
}

ログアウトのリダイレクトをセキュリティで保護する

ログアウト後、ユーザーは、アプリケーションに対して指定されている応答 URL に関係なく、post_logout_redirect_uri パラメーターに指定された URI にリダイレクトされます。 ただし、有効な id_token_hint が渡され、 [ログアウト要求に ID トークンが必要] が有効になっている場合、Azure AD B2C では、リダイレクトの実行前に、post_logout_redirect_uri の値がいずれかのアプリケーションの構成済みのリダイレクト URI と一致するかどうかが検証されます。 一致する応答 URL がアプリケーションで構成されていない場合は、エラー メッセージが表示され、ユーザーはリダイレクトされません。

セキュリティで保護されたログアウト リダイレクトを自分のアプリケーションでサポートするには、まず、アカウント コントローラー高度なシナリオのサポートに関するセクションの手順に従います。 次に、以下の手順に従ってください。

  1. MyAccountController.cs コントローラーで、次のコード スニペットを使用して SignOut アクションを追加します。

    [HttpGet("{scheme?}")]
    public async Task<IActionResult> SignOutAsync([FromRoute] string scheme)
    {
        scheme ??= OpenIdConnectDefaults.AuthenticationScheme;
    
        //obtain the id_token
        var idToken = await HttpContext.GetTokenAsync("id_token");
        //send the id_token value to the authentication middleware
        properties.Items["id_token_hint"] = idToken;            
    
        return SignOut(properties,CookieAuthenticationDefaults.AuthenticationScheme,scheme);
    }
    
  2. Startup.cs クラスで、id_token_hint 値を解析し、その値を認証要求に追加します。 次のコード スニペットは、id_token_hint 値を認証要求に渡す方法を示しています。

    private async Task OnRedirectToIdentityProviderForSignOutFunc(RedirectContext context)
    {
        var id_token_hint = context.Properties.Items.FirstOrDefault(x => x.Key == "id_token_hint").Value;
        if (id_token_hint != null)
        {
            // Send parameter to authentication request
            context.ProtocolMessage.SetParameter("id_token_hint", id_token_hint);
        }
    
        await Task.CompletedTask.ConfigureAwait(false);
    }
    
  3. ConfigureServices 関数で、コントローラーid_token 値にアクセスできるように SaveTokens オプションを追加します。

    services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(options =>
        {
            Configuration.Bind("AzureAdB2C", options);
            options.Events ??= new OpenIdConnectEvents();        
            options.Events.OnRedirectToIdentityProviderForSignOut += OnRedirectToIdentityProviderForSignOutFunc;
            options.SaveTokens = true;
        });
    
  4. appsettings.json 構成ファイルで、ログアウト リダイレクト URI パスを SignedOutCallbackPath キーに追加します。

    "AzureAdB2C": {
      "Instance": "https://<your-tenant-name>.b2clogin.com",
      "ClientId": "<web-app-application-id>",
      "Domain": "<your-b2c-domain>",
      "SignedOutCallbackPath": "/signout/<your-sign-up-in-policy>",
      "SignUpSignInPolicyId": "<your-sign-up-in-policy>"
    }
    

上記の例で、ログアウト要求に渡される post_logout_redirect_uri は、https://your-app.com/signout/<your-sign-up-in-policy> の形式になります。 この URL をアプリケーション登録の応答 URL に追加する必要があります。

ロール ベースのアクセス制御

ASP.NET Core での承認では、次のいずれかの方法を使用して、保護されたリソースへのアクセスがユーザーに許可されているかどうかを確認できます。

ConfigureServices メソッドで、承認モデルを追加する AddAuthorization メソッドを追加します。 次の例では、EmployeeOnly という名前のポリシーを作成します。 このポリシーでは、EmployeeNumber 要求が存在することを確認するためのチェックを実行します。 要求の値は、1、2、3、4、5 のいずれかの ID である必要があります。

services.AddAuthorization(options =>
    {
        options.AddPolicy("EmployeeOnly", policy =>
              policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
    });

ASP.NET Core での承認を制御するには、AuthorizeAttribute とそのさまざまなパラメーターを使用します。 最も基本的な形式では、コントローラー、アクション、または Razor ページに Authorize 属性を適用すると、そのコンポーネントの認証済みユーザーにアクセスが制限されます。

コントローラーにポリシーを適用するには、Authorize 属性とポリシー名を使用します。 次のコードでは、Claims アクションへのアクセスが、EmployeeOnly ポリシーによって認可されたユーザーに制限されます。

[Authorize(Policy = "EmployeeOnly")]
public IActionResult Claims()
{
    return View();
}

次の手順