Azure AD B2C を使用して独自の Web API で認証を有効にする

Web API へのアクセスを認可するには、Azure Active Directory B2C (Azure AD B2C) によって発行された有効なアクセス トークンが含まれる要求のみを処理します。 この記事では、Web API に対して Azure AD B2C を有効にする方法を示します。 この記事の手順を完了すると、有効なアクセス トークンを取得したユーザーのみが、Web API エンドポイントの呼び出しを認可されるようになります。

前提条件

開始する前に、Web API を呼び出すアプリの認証を構成する方法について説明している、以下のいずれかの記事を読みます。 次に、この記事の手順に従って、サンプル Web API を独自の Web API に置き換えます。

概要

トークンベースの認証により、Web API への要求に有効なアクセス トークンが確実に含まれるようになります。

アプリでは以下の手順が行われます。

  1. Azure AD B2C を使用してユーザーを認証します。

  2. Web API エンドポイントで必要とされるアクセス許可 (スコープ) を持つアクセス トークンを取得します。

  3. HTTP 要求の認証ヘッダーで、次の形式を使用してベアラー トークンとしてのアクセス トークンを渡します。

    Authorization: Bearer <access token>
    

Web API では以下の手順が行われます。

  1. HTTP 要求の認可ヘッダーからベアラー トークンを読み取ります。

  2. トークンを検証します。

  3. トークン内のアクセス許可 (スコープ) を検証します。

  4. トークン内にエンコードされている要求を読み取ります (省略可能)。

  5. HTTP 要求に応答します。

アプリ登録の概要

アプリで Azure AD B2C を使用してサインインし、Web API を呼び出せるようにするには、Azure AD B2C ディレクトリに 2 つのアプリケーションを登録する必要があります。

  • "Web、モバイル、または SPA アプリケーション" の登録により、アプリで Azure AD B2C を使用してサインインできるようになります。 アプリの登録プロセスによって、アプリケーションを一意に識別する "アプリケーション ID" ("クライアント ID" とも呼ばれます) が生成されます (たとえば "アプリ ID: 1")。

  • Web API を登録すると、保護された Web API をアプリで呼び出すことができます。 この登録により、Web API のアクセス許可 (スコープ) が公開されます。 アプリの登録プロセスによって、Web API を一意に識別する "アプリケーション ID" が生成されます (たとえば "アプリ ID: 2")。 アプリ (アプリ ID: 1) のアクセス許可を Web API スコープ (アプリ ID: 2) に付与します。

次の図で、アプリケーションの登録とアプリケーション アーキテクチャについて説明しています。

Diagram of the application registrations and the application architecture for an app with web API.

開発環境を準備する

次のセクションでは、新しい Web API プロジェクトを作成します。 プログラミング言語として ASP.NET Core または Node.js を選択してください。 次のソフトウェアのいずれかを実行しているコンピューターがあることを確認してください。

手順 1: 保護された Web API を作成する

新しい Web API プロジェクトを作成します。 まず、使用するプログラミング言語として、ASP.NET Core または Node.js を選択します。

dotnet new コマンドを使用します。 dotnet new コマンドで、Web API プロジェクトのアセットが含まれる TodoList という名前の新しいフォルダーを作成します。 ディレクトリを開いてから、Visual Studio Code を開きます。

dotnet new webapi -o TodoList
cd TodoList
code . 

"必要な資産をプロジェクトに追加する" よう求めるダイアログが表示されたら、 [はい] を選択します。

手順 2: 依存関係をインストールする

認証ライブラリを Web API プロジェクトに追加します。 認証ライブラリでは、HTTP 認証ヘッダーの解析、トークンの検証、要求の抽出が行われます。 詳細については、このライブラリのドキュメントを確認してください。

認証ライブラリを追加するには、次のコマンドを実行してパッケージをインストールします。

dotnet add package Microsoft.Identity.Web

手順 3: 認証ライブラリを開始する

認証ライブラリを開始するために必要なコードを追加します。

Startup.cs を開いてから、クラスの先頭に以下の using 宣言を追加します。

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;

ConfigureServices(IServiceCollection services) 関数を検索します。 次に、コードの services.AddControllers(); 行の前に以下のコード スニペットを追加します。

public void ConfigureServices(IServiceCollection services)
{
    // Adds Microsoft Identity platform (Azure AD B2C) support to protect this Api
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddMicrosoftIdentityWebApi(options =>
    {
        Configuration.Bind("AzureAdB2C", options);

        options.TokenValidationParameters.NameClaimType = "name";
    },
    options => { Configuration.Bind("AzureAdB2C", options); });
    // End of the Microsoft Identity platform block    

    services.AddControllers();
}

Configure 関数を検索します。 次に、コードの app.UseRouting(); 行の直後に以下のコード スニペットを追加します。

app.UseAuthentication();

変更後、コードは次のスニペットのようになっているはずです。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();
    
    // Add the following line 
    app.UseAuthentication();
    // End of the block you add
    
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

手順 4: エンドポイントを追加する

Web API に 2 つのエンドポイントを追加します。

  • 匿名の /public エンドポイント。 このエンドポイントからは、現在の日付と時刻が返されます。 これは、匿名呼び出しを使用して Web API をデバッグするために使用します。
  • 保護された /hello エンドポイント。 このエンドポイントからは、アクセス トークン内の name 要求の値が返されます。

匿名エンドポイントを追加するには:

/Controllers フォルダーで PublicController.cs ファイルを追加してから、それを以下のコード スニペットに追加します。

using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace TodoList.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class PublicController : ControllerBase
    {
        private readonly ILogger<PublicController> _logger;

        public PublicController(ILogger<PublicController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public ActionResult Get()
        {
            return Ok( new {date = DateTime.UtcNow.ToString()});
        }
    }
}

保護されたエンドポイントを追加するには:

/Controllers フォルダーで HelloController.cs ファイルを追加してから、それを以下のコードに追加します。

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Identity.Web.Resource;

namespace TodoList.Controllers
{
    [Authorize]
    [RequiredScope("tasks.read")]
    [ApiController]
    [Route("[controller]")]
    public class HelloController : ControllerBase
    {

        private readonly ILogger<HelloController> _logger;
        private readonly IHttpContextAccessor _contextAccessor;

        public HelloController(ILogger<HelloController> logger, IHttpContextAccessor contextAccessor)
        {
            _logger = logger;
            _contextAccessor = contextAccessor;
        }

        [HttpGet]
        public ActionResult Get()
        {
            return Ok( new { name = User.Identity.Name});
        }
    }
}

HelloController コントローラーは、認証されたユーザーにのみアクセスを制限する AuthorizeAttribute で修飾されます。

コントローラーは、[RequiredScope("tasks.read")] によっても装飾されます。 RequiredScopeAttribute を指定すると、Web API が適切なスコープ tasks.read を使用して呼び出されたことが確認されます。

手順 5: Web サーバーを構成する

開発環境で、受信 HTTP または HTTPS 要求のポート番号をリッスンするように Web API を設定します。 この例では、HTTP ポート 6000 と HTTPS ポート 6001 を使用します。 Web API のベース URI は、HTTP の場合は http://localhost:6000、HTTPS の場合は https://localhost:6001 になります。

appsettings.json ファイルに次の JSON スニペットを追加します。

"Kestrel": {
    "EndPoints": {
      "Http": {
        "Url": "http://localhost:6000"
      },
      "Https": {
         "Url": "https://localhost:6001"   
        }
    }
  }

手順 6: Web API アプリを構成する

構成ファイルに構成を追加します。 このファイルには、Azure AD B2C ID プロバイダーに関する情報が含まれます。 Web API アプリではこの情報を使用して、Web アプリからベアラー トークンとして渡されるアクセス トークンが検証されます。

プロジェクトのルート フォルダーの下にある appsettings.json ファイルを開いてから、以下の設定を追加します。

{
  "AzureAdB2C": {
    "Instance": "https://contoso.b2clogin.com",
    "Domain": "contoso.onmicrosoft.com",
    "ClientId": "<web-api-app-application-id>",
    "SignedOutCallbackPath": "/signout/<your-sign-up-in-policy>",
    "SignUpSignInPolicyId": "<your-sign-up-in-policy>"
  },
  // More settings here
}

appsettings.json ファイルで、以下のプロパティを更新します。

Section キー
AzureAdB2C インスタンス Azure AD B2C テナント名の最初の部分 (例: https://contoso.b2clogin.com)。
AzureAdB2C Domain Azure AD B2C テナントの完全なテナント名 (例: contoso.onmicrosoft.com)。
AzureAdB2C ClientId Web API アプリケーション ID。 前の図で、これはアプリ ID: 2 であるアプリケーションでした。 Web API アプリケーションの登録 ID を取得する方法については、「前提条件」を参照してください。
AzureAdB2C SignUpSignInPolicyId ユーザー フローまたはカスタム ポリシー。 ユーザー フローまたはポリシーを取得する方法については、「前提条件」を参照してください。

手順 7: Web API を実行してテストする

最後に、Azure AD B2C 環境の設定を使用して Web API を実行します。

コマンド シェルで、次のコマンドを実行して Web アプリを起動します。

 dotnet run

次の出力が表示されるはずです。これは、アプリが起動して実行中であり、要求を受信する準備ができていることを意味します。

Now listening on: http://localhost:6000

プログラムを停止するには、コマンド シェルで Ctrl + C キーを押します。 node app.js コマンドを使用するとアプリを再実行できます。

ヒント

または、dotnet run コマンドを実行するために、Visual Studio Code デバッガーを使用できます。 Visual Studio Code の組み込みデバッガーを使用すると、編集、コンパイル、デバッグのループを加速できます。

ブラウザーを開き、http://localhost:6000/public に移動します。 ブラウザー ウィンドウには、現在の日付と時刻と共に、次のテキストが表示されるはずです。

手順 8: アプリから Web API を呼び出す

アクセス トークンを使用せずに、保護された Web API エンドポイントの呼び出しを試みます。 ブラウザーを開き、http://localhost:6000/hello に移動します。 API から、許可されていない HTTP のエラー メッセージが返されるので、Web API がベアラー トークンによって保護されていることを確認できます。

Web API を呼び出すために引き続きアプリを構成します。 ガイダンスについては、「前提条件」セクションを参照してください。

Azure AD B2C を API と統合する場合のベスト プラクティスについては、このビデオをご覧ください。

次のステップ

完全な例については GitHub で入手してください。