Azure AD B2C カスタムポリシーのスターターパック (LocalAccounts) の解説

# 1. はじめに
[スターターパック](https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack) は Azure AD B2C のカスタムポリシー構成を始めるにおいて最も重要なリソースの一つです。
しかし、残念ながら現状においては、日本語ではこのスターターパック自体を解説する情報はあまりありません。そのため、この記事を投稿することにしました。
本記事ではカスタムポリシーの読み方をおさらいしたうえで、実際にスターターパックの [LocalAccounts](https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/tree/main/LocalAccounts) を読み解く内容を提供します。

:::note warn
本記事をより理解していただくために、[チュートリアル](https://docs.microsoft.com/ja-jp/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy)を事前に実施していただくことをお勧めします。
:::
:::note warn
また本記事は個人的な検証 / 見解を基に記載しており、特定の団体を代表した内容ではございません。あらかじめご了承ください。
:::

# 2. 本記事で得られるものと対象者
本記事を読むことで以下が得られます。
・カスタムポリシーの基本的な文法や読み方が理解できる
・スターターパックを読むことができ、その記述理解できるようになる
また上記 2 つを理解することにより[サンプル集](https://github.com/azure-ad-b2c/samples)のための基礎を固めることができます。

:::note info
[サンプル集](https://github.com/azure-ad-b2c/samples)とは、様々なシナリオに合わせたカスタムポリシーの記載例が集められた GitHub のリポジトリです。サンプル集を活用できれば、ご自身の要件に合わせた独自実装もかなり楽になります。
:::
なお、本記事の以下のようなかたを想定し、記載しております。
* Azure AD B2C のカスタムポリシーの基礎が知りたい方
* [チュートリアル](https://docs.microsoft.com/ja-jp/azure/active-directory-b2c/tutorial-create-user-flows?pivots=b2c-custom-policy)を触ったが次に何をしていいか分からない方
* [公開情報:Azure AD B2C カスタム ポリシーの概要](https://docs.microsoft.com/ja-jp/azure/active-directory-b2c/custom-policy-overview) を読んだがピンとこなかった方

また、これから Azure AD B2C を始める方や初めてまだ間もない方は、以下も参照いただけますと幸いです。私の経験をもとに学習パスを記載したものになります。
[Azure AD B2C 入門のメモ書き](https://qiita.com/skmk/items/52eee28517756be61b14)

# 3. まずはカスタムポリシーの基本文法や概念をおさらい
カスタムポリシーはサインイン / サインインアップなど認証にかかわる処理や 
SNS のアカウントによる認証などを自由にカスタマイズできる機能です。
カスタムポリシーには独特な特徴が 2 つあります。
* xml でコードを書く
* カスタムポリシー特有の用語が頻出する

この 2 点が、分かりずらさや、難しさを感じる原因になっていると思います。
しかしながら、実は一般的なプログラミング言語と基本的な文法や概念はほぼ同じです。
なので、カスタムポリシー特有の用語と一般的なプログラミング言語で共通する考え方の
紐づけさえできれば、どうということはありません。

上述のことをまずは理解していただくために、次の章からの流れで説明します。
* 1.カスタムポリシーの処理の流れと合わせて、カスタムポリシー特有のそれぞれの用語を解説
* 2.[スターターパック](https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack) の詳細を解説

## 3.1 カスタムポリシーの処理の流れについて
処理の順番は通常のプログラミング言語とそう大きく変わりません。
簡単に図示すると以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/bd8249a8-4cfb-282a-ecfa-342b902f428a.png)
つまり、実行される User Journey について、 Ortchestraiton Step を順番に読よみ、
必要に応じて、 Technical Profile の定義元の記述を見れば、
どのような処理が、どのような順番で実行されているのかということが理解できます。

:::note info
つまり、カスタムポリシー特有の用語は、結局以下のことを意味しています。
・User Journey = main 文
・Orchestration Step = main 文のステップ、 1 から順番に実行される
・Claim Provider = クラス
・Technical Profile = クラスのメソッド (関数)
・Claim = 変数
:::

このように カスタムポリシーでは User Journey だの Technical Profile など難しそうな用語が出てきますが、結局のところやっていることは、一般的なプログラミング言語と大差ありません。

## 3.2 カスタムポリシーのファイル構成について
記述したい内容は 3.1 の通りなのですが、実際のスターターパックのカスタムポリシーでは 4 つのファイルに分割してコードが記載されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/e2009915-cddf-119b-6d93-bdb912a5b7d8.png)

| ファイルの種類 | 役割 | ファイル名 | 記述の変更 |
|:-:|:-:|:-:|:-:|
| Base ファイル | このファイルは Microsoft 社によって記載されているものであり、カスタムポリシーに基本的に必要な記述のすべてが記載されます | TrustFrameworkBase.xml | 非推奨 |
| Localization ファイル | 多言語対応に関する記述を行うファイルです。| TrustFrameworkLocalization.xml | OK |
|  Extensions ファイル | Base ファイルでは足りない部分や独自のカスタマイズを記載するためのファイルです。| TrustFrameworkExtensions.xml | OK |
| 証明書利用者 (RP) ファイル | アプリと、カスタムポリシーをつなぐインターフェースの役割を果たすファイルです。カスタムポリシーへアクセスするためのエンドポイントを用意したり、どのような ID トークンを返すのか (含める Claim や有効期限など) といった内容を設定するファイルになります。 | SignUpOrSignin.xml, ProfileEdit.xml, PasswordReset.xml | OK |


他のプログラミング言語でも管理やデバック、再利用などの都合で、1 つのファイルではなく、複数のファイルに分けてコーディングするのがあるあるだと思います。
それと同様に、カスタムポリシーにおいても、役割や機能ごとに 4 つのファイルに分割してコードを記載するスタイルを採用しています。


## 3.3 カスタムポリシーの継承について
カスタムポリシーには継承という機能があり、どのレベルの子ポリシーでも、親ポリシーから継承することができ、新しい要素を追加することによって拡張する (オーバライドする) ことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/b2442ea5-8e2e-d0ec-8941-a3a154678395.png)
この継承機能により、Base ファイルの記述内容を変更したいというシナリオにおいて、
Base ファイルには一切触らずに、変更点のみを子ポリシー側である Extensions ファイルにに記載するといった手法を可能にしています。

※ Base ファイルは MS ファイルで変更を推奨されないいわば神的なファイルです
なので、 Base ファイル以外にカスタマイズしたい内容を記載するのがベストプラクティスです。
[公開情報 : 継承モデル](https://learn.microsoft.com/ja-jp/azure/active-directory-b2c/custom-policy-overview#inheritance-model)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/59d7fa26-5535-005e-f1f5-352e2a9518ee.png)

# 4. カスタムポリシーのスターターパック (LocalAccounts) を読む
前置きが長くなりましたが、[スターターパック (LocalAccounts)](https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/tree/main/LocalAccounts) の中身を見ていきます。
カスタムポリシーを読むうえで [VS Code の拡張機能 Azure AD B2C](https://marketplace.visualstudio.com/items?itemName=AzureADB2CTools.aadb2c) は必須なので、まだインストールしてなければぜひインストールしておきましょう！


## 4.1 まずは、 RP ファイル SignUpOrSignin.xml から見る
カスタムポリシーは、まず RP ファイルを見るところから始まります。
RP ファイルを見ることで、どの UserJourney が起動されるのがを把握できるからです。
今回はサインインサインアップの動作を見たいので SignUpOrSignin.xml を見ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/c2c1c6e1-3266-b53f-9c87-3a205c89034f.png)
上記の記述により、アプリがサインインサインアップの RP ファイルにアクセスすると
Base ファイルにある User Journey の SignUpOrSignIn が起動されることがわかります。
なので、次は Base ファイルにある SignUpOrSignIn の詳細を見ていきます。
※ VS Code の拡張機能 Azure AD B2Cにより、マウスをホーバー & 1 クリックで、定義元の確認とジャンプができるのでとても便利です。

## 4.2 Base ファイルの User Journey SignUpOrSignIn を見る
各詳細を見る前に、いったん Orchestration Step の全体を見てみる。
命名則がわかりやすくなっているので、大体の流れを読み取ることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/e6a641c5-0329-9275-f5ac-5243861f2ac8.png)
全体を見たところで、 Orchestration Step 1 から順に詳細を見てみましょう

## 4.3 Orchestration Step 1 の詳細
Orchestration Step 1 はサインイン画面を出し、認証を行うステップになります。
このステップで最も重要なのは SelfAsserted-LocalAccountSignin-Email という Technical Profile です。この Techcnical Profile が ID/Password の入力や、認証処理を行ってくれています。
各種設定の詳細については必要に応じて [(公開情報) UserJourneys](https://learn.microsoft.com/ja-jp/azure/active-directory-b2c/userjourneys) をご参照ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/c79a046f-dc0a-9ece-656f-bcca54d09a8e.png)
今度はさらに、SelfAsserted-LocalAccountSignin-Email の定義にジャンプし、その詳細を見てみましょう

SelfAsserted-LocalAccountSignin-Email 入力画面を構成する Technical Profile です。
入力項目やサインインボタンを押したときにどのようは処理を呼び出すのかの定義が記載されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/e54b6078-a9af-1355-5096-8e46003a0eef.png)
実際のサインインの処理は login-NonInteractive で行われていますので、
さらに login-NonInteractive へジャンプしその詳細を確認していきます。

login-NonInteractive という Technical Profile は Azure AD への認証要求に関する処理が定義されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/2eeb584c-ac07-fbca-2915-23f528272964.png)
Azure AD B2C という製品は、実は Azure AD をベースに拡張されたサービスであり、
認証処理などについては、 Azure AD の 機能を使っています。
この login-NonInteractive では Azure AD B2C のベースとなっている Azure AD に対して
OIDC の ROPC フローという認証の要求を行うこと、そして認証の結果得られたユーザーの Object Id といった属性値を Claim に保存する、ということが行われています。

ここまでの処理が、Orchestration Step 1 で行われています。
## 4.4 Orchestration Step 2 の詳細
Orchestration Step 2 ではサインアップをを行うステップになります。
Step 1 でサインインを行ったときには Step 2 はスキップされ
サインインを行っていない = サインアップということで、 Step 2 はサインアップを行っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/c0497108-01ed-fc6f-c4f4-20ab931821cc.png)
実際の処理は、LocalAccountSignUpWithLogonEmail にて行われていますので、
早速その定義へジャンプします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/505deccd-cd84-d21c-47e3-e958c12e58be.png)
このように、LocalAccountSignUpWithLogonEmail はサインアップ画面の攻勢についての定義が記載されてます。サインアップの処理の詳細をさらに確認するために、 AAD-UserWriteUsingLogonEmail の定義も確認してみましょう。
AAD-UserWriteUsingLogonEmail は Azure AD の書き込み API を使用する Technical Profile になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/8c5dd83a-caf0-4c1a-d2d0-20ff37d2c134.png)
主にユーザーの ID となる email やパスワード、表示名に関するデータとともに
Azure AD へアカウントを作成する要求を行っています。
アカウント作成の結果、Azure AD からユーザーの識別子 (ObjectID) などが返されるので、それらの情報を Claim に保存しています。
詳細については、[公開情報 Azure Active Directory B2C カスタム ポリシーで Azure Active Directory 検証技術プロファイルを定義します](https://learn.microsoft.com/ja-jp/azure/active-directory-b2c/active-directory-technical-profile) にも記載がありますので詳細はこちらをどうぞ。

# 4.5 Orchestration Step 3 の詳細
Orchestration Step 3 では、サインインしたユーザー、もしくはサインアップしたユーザーに関する詳細なデーター (属性値) を Azure AD から読み出すステップになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/d3863c89-5ada-14bd-3e99-dd16b02418c5.png)
このステップでは単純に Azure AD の情報を読み出す Technical Profile、 AAD-UserReadUsingObjectId を呼び出しています。

AAD-UserReadUsingObjectId の実際の定義では  Azure AD の読み込み API を使用する記述が記載されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/c96d5539-cdf2-09e1-9328-6b6f9973d071.png)
前のステップ (Orchestration step 1 のサインイン or Orchestration step 2) で取得したObjectID をキーに特定ユーザーの属性情報を取得します。
OutputClaim に Azure AD から取得したいユーザーの属性を指定しています。

# 4.6 Orchestration Step 4 の詳細
Orchestration Step 4 ではトークンの発行を行っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/40b176fc-4f2e-6b5f-8d98-737911052cfb.png)
Azure AD B2C が発行するトークンは JWT 形式となっており、この Technical Profile で
ID トークンやアクセストークンを発行します。

詳細については、[公開情報 Azure Active Directory B2C カスタム ポリシーで JWT トークン発行者用の技術プロファイルを定義する](https://learn.microsoft.com/ja-jp/azure/active-directory-b2c/jwt-issuer-technical-profile)にも記載がありますので詳細はこちらをどうぞ。

# 4.7 最後にRP ファイル SignUpOrSignin.xml に戻ってくる
ここまで認証とトークンの発行まで終わったので、アプリに渡すトークンの最終調整を RP ファイルで行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144326/63139df6-6962-c816-c6cf-d6204a8ed4e3.png)
今回のスターターパック LocalAccounts の記述では、 トークンに含める Claim の指定しか調整をしていませんが、[UserJourneyBehaviors](https://learn.microsoft.com/ja-jp/azure/active-directory-b2c/relyingparty#userjourneybehaviors) という記述を加えることで、シングルサインオンのセッションの設定 (有効期限など) も行うことができます

# 5. 次のステップ
ここまで読み進めていただければ、スターターパックの内 LocalAccounts のサインイン / サインアップの処理の大まかな流れや、カスタムポリシーをどの順番で読み進めるのか、どこに何が書いているのかある程度理解できたと思います。

この理解をベースにさらに、 スターターパックをさらに読み込んでみましょう。
長くなりすぎるので本記事では記載を活用しましたが、本記事と同じような流れで読めば理解ができるはずです。
* LocalAccounts の [プロファイル更新](hthttps://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/blob/main/LocalAccounts/ProfileEdit.xml)や[パスワードリセット](https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/blob/main/LocalAccounts/PasswordReset.xml)
* スターターパックの内の [SocialAndLocalAccounts](https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/tree/main/SocialAndLocalAccounts) や [SocialAndLocalAccountsWithMfa](https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/tree/main/SocialAndLocalAccountsWithMfa) 

ここまでやればスターターパックはほぼ理解できた状態になりますので、
次はスタータパックをベースに発展させた[サンプル集](https://github.com/azure-ad-b2c/samples) をいくつか試していただくのが良いかと思います。

※サンプル集は、様々なシナリオに合わせたExtensions ファイルや  RP ファイルの記載がされています。スターターパックをベースにどのようにカスタマイズしたらいいかが見えてくると思います。

# 6. 参考サイト
[(公開情報) Azure AD B2C カスタム ポリシーの概要](https://learn.microsoft.com/ja-jp/azure/active-directory-b2c/custom-policy-overview)
[(公開情報) Azure Active Directory B2C の推奨事項とベスト プラクティス](https://learn.microsoft.com/ja-jp/azure/active-directory-b2c/best-practices)
[(公開情報) UserJourneys](https://learn.microsoft.com/ja-jp/azure/active-directory-b2c/userjourneys)
[公開情報 Azure Active Directory B2C カスタム ポリシーで Azure Active Directory 検証技術プロファイルを定義します](https://learn.microsoft.com/ja-jp/azure/active-directory-b2c/active-directory-technical-profile)
[公開情報 Azure Active Directory B2C カスタム ポリシーで JWT トークン発行者用の技術プロファイルを定義する](https://learn.microsoft.com/ja-jp/azure/active-directory-b2c/jwt-issuer-technical-profile)

# 7. 参考動画
[6-6: Azure AD B2C 入門:今話題のD2C(Direct to Cosumer)向けの認証サービス入門 (Guest Speaker: Cloud Solution Architect)](https://www.youtube.com/watch?v=owiW1rxNW14)

# 8. 関連ツール
[スターターパック (LocalAccounts)](https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/tree/main/LocalAccounts)
[VS Code の拡張機能 Azure AD B2C](https://marketplace.visualstudio.com/items?itemName=AzureADB2CTools.aadb2c)