Microsoft Entra ID と CIAM でカスタムクレームプロバイダーを試してみた

Microsoft Security Advent Calendar 2023 の 8 日目を担当させていただきます。よろしくお願いいたします。
# クレーム(属性)とは？
OpenID Connect(以降OIDC) や SAML などの認証連携プロトコルを使用した際に ID プロバイダー(以降IdP)から発行されるトークンに含まれている属性のことをクレームと呼んでいます。
Microsoft Entra ID (以降Entra ID)も OIDC や SAML の IdP として、Entra ID 内のユーザー情報(属性)をクレームとしてトークンに挿入しアプリケーションに返却することが可能です。例えば、ユーザーの「email アドレス」や、「従業員番号」、「姓」、「名」などのユーザー属性をクレームとして使う事ができます。これらのクレームは、認証や認可の目的で使用します。アプリケーションはクレームの内容をチェックしエンドユーザーに提供するサービスを制限したり、逆に制限をなくすことも可能です。クレームをベースにサービスレベルをコントロールすることが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265935/4a8990ad-4032-4c42-31f8-323d42a05d4d.png)

ちなみに、Entra ID の OIDC の IDトークンに含まれているクレームは以下の表の通りです。全てのクレームがトークンに含まれるのではなく、アプリケーションが必要とする Entra ID に登録されている属性をトークンに挿入します。

参照元 https://learn.microsoft.com/ja-jp/entra/identity-platform/id-token-claims-reference
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265935/01f82c9e-e950-fa85-a540-1be783afcb05.png)

API などのリソースが使用するアクセストークンも IDトークンと同様に Entra ID に登録された属性をクレームとしてアクセストークンに挿入してアプリに返却します。詳細についてこちらを参照ください。

https://learn.microsoft.com/ja-jp/entra/identity-platform/access-token-claims-reference

さらにオプション要求を使うことで、Entra ID にある情報をクレームとして、IDトークンやアクセストークンに追加してアプリに渡すことが可能です。

https://learn.microsoft.com/ja-jp/entra/identity-platform/optional-claims-reference

今まで見てきたように、Entra ID ではクレームをカスタマイズしアプリに提供できるようになっているのですが、それでもアプリにとっては十分ではない場合があります。そんな時に登場するのがカスタムクレームプロバイダーです。

# カスタムクレームプロバイダーとは？
カスタムクレームプロバイダーは外部のクレーム提供サービスです。通常、Entra ID 内にある属性がクレームとしてトークンに挿入されてアプリケーションに返却されます。カスタムクレームプロバイダーを使用すると Entra ID 以外の LDAPサーバーや独自属性 DB 等からクレームを取得し、トークンに取得したクレームを追加してアプリに返却することが可能です。
以下の図にあるように Entra ID の外部にあるカスタムクレームプロバイダーを経由して属性 DB からクレームA、クレームB、クレームCを取り出してトークンに追加しアプリケーションに返却することが可能になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265935/b9361fb1-186e-f7d9-b5c9-c1dddc4abd6d.png)

# Entra ID でカスタムクレームプロバイダーを試してみた
カスタムクレームプロバイダーは現時点(2023年12月8日)ではプレビューですが実際に動作を確認することが可能です。既にいくつかのドキュメントが公開されています。私は以下のドキュメントを参考に Azure Functions を使って簡易的なカスタムクレームプロバイダーを作成してみました。

https://learn.microsoft.com/ja-jp/entra/identity-platform/custom-extension-get-started

https://jpazureid.github.io/blog/azure-active-directory/customize-your-authentication-flows-with-custom-claims-providers/

英語ですが YouTubeでも Azure Functions の設定から Entra ID の設定まで詳細に説明しておりとても参考になります。

https://www.youtube.com/watch?v=fxQGVIwX8_4

Azure Functions、Entra ID の構成が完了後、以下の URL をブラウザーに入力してテストを行います。
```
https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/authorize?client_id={App_to_enrich_ID}&response_type=id_token&redirect_uri=https://jwt.ms&scope=openid&state=12345&nonce=12345
```
Entra ID の認証画面が表示されますので、認証が成功すると Entra ID が発行した IDトークンをデコードするアプリ(https://jwt.ms) にリダイレクトします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265935/13e1f21c-625f-dd46-3d1f-297f1d059ac5.png)

以下のイメージはアプリによってデコードされた ID トークンです。Entra ID にはないクレーム(dateOfBirth、customRoles、apiVersion、correlationId)がカスタムクレームプロバイダーを使用することでトークンに追加されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265935/2a322049-c5e7-dd6f-2a32-b5aa699619ac.png)

# REST API スキーマ情報
ドキュメントを見ながら比較的簡単にカスタムクレームプロバイダーの動作を確認することができます。しかしながら、実際にカスタムクレームプロバイダーを作るとなると、REST API の詳しい情報が必要になります。それらの情報は以下のドキュメントにありますのでこちらもご確認ください。

https://learn.microsoft.com/ja-jp/entra/identity-platform/custom-claims-provider-reference

# CIAM でカスタムクレームプロバイダーを試してみた
カスタムクレームプロバイダーは、Entra ID だけではなく、@daimat さんが12月1日のブログで紹介されていた「お客様向けの ID 管理サービス」(以降 CIAM)でも利用することが可能です。

以下のドキュメントを見ると CIAM も Entra ID とほぼ同じ構成で利用できそうです。既に作成済の Azure Functions のカスタムクレームプロバイダーも流用できるので、早速、以下のドキュメントを参考に構成し動作を確認してみました。

https://learn.microsoft.com/ja-jp/entra/identity-platform/custom-extension-get-started?context=/entra/external-id/customers/context/customers-context

# CIAM と Entra ID の差異
安易な気持ちでドキュメントを眺めながら始めましたがドキュメント通りにやるとエラーが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265935/309a406b-7d75-efbb-7196-b0b1e083b4d7.png)

実は、ドキュメントの「手順 6: アプリケーションをテストする」で記載されている URLでは上手く動作しません。CIAM 用には以下の URL を使用してテストする必要があります。

```
https://{CIAM_Domain}.ciamlogin.com/{tenant-id}/oauth2/v2.0/authorize?client_id={App_to_enrich_ID}&response_type=id_token&redirect_uri=https://jwt.ms&scope=openid&state=12345&nonce=12345
```
Azure Functions の認証設定も変更する必要があります。
Azure Functions を CIAM で認証するためには、OpenID Connect を ID プロバイダーとして構成する必要があります。ドキュメントの「5.1 OpenID Connect ID プロバイダーの使用」で設定方法が記載されています。しかしながら[メタデータ URL] で記載されている URL は CIAM 用ではありません。CIAM のメタデータ URL は以下になります。

```
https://{CIAM_Domain}.ciamlogin.com/{Tenant_id}/v2.0/.well-known/openid-configuration
```
これで大丈夫かなと思いましたが、CIAM でのユーザー認証成功後に以下のメッセージが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265935/d5c894a3-0e07-76ee-c3ed-76869e73a3a0.png)

実は、CIAM では登録したアプリケーション(https://jwt.ms) に対して事前に「委任されたアクセス許可」を付与しておく必要があります。CIAM での[委任されたアクセス許可] については以下のサイトに手順が記載されています。openid と offline_access の両方のアクセス許可を与えます。

https://learn.microsoft.com/ja-jp/entra/external-id/customers/how-to-register-ciam-app

アクセス許可を付与後に、CIAM 用のテスト URL をブラウザーに入力して実行すると認証成功後にIDトークンをデコードするアプリにリダイレクトし結果が表示されます。Entra ID でテストした結果と同じく、CIAM にはないクレーム(dateOfBirth、customRoles、apiVersion、correlationId)がトークンに追加されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2265935/6903ba0e-9f36-ad64-a510-ac2c77728394.png)

# まとめ
今回は現時点(2023年12月08日)ではプレビューである「カスタムクレームプロバイダー」について記載しました。 Entra ID と 顧客向けの ID 管理サービスである CIAM(プレビュー中) の両方でこの機能を使用することが可能です。Entra ID では社内アプリに対してクレームを追加して認可を行う事が可能になります。特に、今までアプリ側で必要な属性情報が足りないため Entra ID へ移行できなかったサービスはこの機能により移行が可能になります。

また、CIAM ではお客様向けのアプリに対してクレームを追加することでよりきめ細やかなサービスをお客様へ提供することが可能になります。

今回の記事では取り上げなかったのですが、Entra ID では OIDCトークンだけでなく、SAMLトークン(アサーション)に対しても同じようにカスタムクレームプロバイダーから取得したクレームを SAML トークンに追加する事が可能です。SAML アプリへのカスタムクレームプロバイダーによるクレーム追加は以下のサイトに説明があります。是非お試しください。

https://learn.microsoft.com/ja-jp/entra/identity-platform/custom-extension-configure-saml-app

:::note info
投稿内容は私個人の意見であり、所属企業・部門とは関係ありません。また、いかなる保証を与えるものでもありません。
:::