目次
初めに
今回は、AzureのサービスであるAD(Active Directory:以下AD)のさらに内部サービスであるAzure AD B2C(Active Directory Business to Consumer:以下AADB2C)を用いた認証済みページをReactで作成する方法についてのメモになります。今回構築したサンプルのリンクはこちらから。
どもども!順調に新卒期間を消費している龍ちゃんです。突然ですが、認証機能って難しいですよね。WEBアプリのレベルを一段階上げてくれる認証機能ですが、一から構成するのはだいぶ難しいです。でも、ログインしてユーザごとの機能を提供することはアプリの充実感をアップさせてくれます。フロントエンドとしては、外部サービスを使用してサクッと認証機能を実装することが正義だと思っています。前回は、Googleが出しているFirebaseを使用して認証済みルーティングを作成しました(前回記事)。僕が携わっているプロダクトでは、Azure上でサービスを構築することが多いので、認証もAzure上でやりたいということでAzure AD B2Cの技術検証をしました。その技術的メモです。
今回の記事で取り扱う内容としては、以下になります。
- Azure ADとB2Cの違いについて
- AADB2C(カスタム認証フロー)を使用するための準備
- Azure AD B2Cを使用してReact認証済ページの作成
今回参考にしたサイトについては以下になります。
- 公式:Azure Active Directory B2C とは
- 公式:Azure Active Directory B2C の技術と機能の概要
- Azure AD B2C のキホンとよくある質問
- 【丁寧解説】Azure AD B2C とは?
- Azure Active Directory B2C でユーザー認証を超簡単に実装しよう
それでは初めて行きましょう。
前提知識
ここでは、Azure AD(AAD)とAzure AD B2C(AADB2C)の違いについて説明をしてAzure AD B2Cでできることについてお話していきます。横文字がいっぱいあると混乱してしまいますよね。僕も最初調べた際に混同していて痛い目にあったのでしっかりと戦っていきたいと思います。
情報元のリンクを張っています。間違った情報を書かないように気を気を付けてはいますが、認識間違いもあるかもしれないので、盲目的に信じることだけはおやめください。
Azure ADとB2Cの違いについて
とりあえずAADとAADB2Cは異なるサービスであるということは頭に置いておきましょう。それぞれ公式のドキュメントを置いておきます。
ざっくりと呼んでみると以下の文言を見つけました。
Azure AD B2C は、Azure Active Directory (Azure AD) とは別のサービスです。 Azure AD と同じテクノロジをベースにして構築されていますが、目的が異なります。
どうやら目的が異なるだけで、内部機構は似ているようです。ではその目的の違いについて触れていきます。横文字のB2Cの意味は「Business to Consumer」の略で意訳をすると「企業が消費者に対して提供するサービスや商品」となります。この観点を含めてADとADB2Cの違いについて図化していきます。
大きく異なる点としては、認証基盤を利用するユーザが異なる点になります。AADB2Cでは、一般ユーザが使用します。UXの観点からも認証に使用するアカウントが外部サービス(Googleアカウント・GitHubアカウント・メールアドレス)と連携することが理想的です。また、ユーザ作成時に情報入力(会社情報・名前など)サービス利用規約の同意なども一括で済ませたいですよね。そういった認証における追加機能を一括で提供ができるのがAADB2Cです。
Azure AD B2Cを使えるようにするため
では、実際にAADB2Cを使えるために準備を進めていきましょう。必要な手順としては、以下になります。すでにテナントの準備などが完了していてReactのルーティングまで読みたい方は次章まで飛ばしてください。
- Azure Portal登録
- Azure ADテナント作成
- Azure AD B2Cアプリ登録
とか偉そうに書いていますが、ここは楽させていただきます。公式にチュートリアルもありますし、視覚的にとても分かりやすいサイトを見つけておいたのでそちらを参照してください。
公式もわかりやすいですが、こちらのサイトが視覚的にわかりやすく登録から初期設定まで紹介していますのでリンクを置いておきます。
React 認証済みページ構築
それでは構築を始めていきましょう。流れとしては以下になります。もし認証情報をどこから持ってくればよいか悩んでいる方がいれば、事前準備を下から読んでください。まとめてます。
- 事前準備
- ライブラリのインストール
- Azure AD B2Cテナント側での設定
- 認証情報の設定
- Reactでの認証情報設定と基本設定
- 認証に関係する処理をカスタムHooksにまとめる
- React認証ルーティングの定義
それでは初めて行きます。
事前準備
Reactで認証ページを利用するためにライブラリとして以下を使用します。
- react-router-dom
- @azure/msal-browser @azure/msal-react
「react-router-dom」に関しては、SPA構築には基本的に使用すると思うので問題なく入っているかと思います。下のライブラリに関しては、公式が使用を推奨しているので特別なこだわりがない限りは以下のコマンドをお願いします。
yarn add @azure/msal-browser @azure/msal-react
特別インストールが必要なライブラリとしては以上です。
次はAzure Portalを開きましょう。ここでする内容としては以下になります。
- ユーザーフローの作成
- アプリの登録
- 認証情報の収集
先ほどの事前準備と重複している部分もありますが、最後の認証情報の収集が複雑なのでしっかりと確認していきます。
Azure Portalを開いてAADB2Cのテナントに入ってください。以下のページまで来ていれば問題ありません。もし入れない方はこちらをクリックしてみてください。迷った方は以下の理由が考えられます。以下に原因と対処法を軽く書いておきます。
- 権限がないと表示される→右上の自分のアイコンをクリックしてディレクトリの切り替え
- Azureへようこそと表示→Azureサービスから「その他のサービス」をクリック「AADB2Cを検索」
赤枠で囲っている部分が後でクリックするところです。黒塗りの部分は見えたら困るところです。あとで見る必要がありますが今は気にしないでください。
ユーザーフロー作成
それではユーザーフローを作成していきましょう。ここで設定する内容としては、ユーザーに与える権限と認証時に収集する情報です。上のページのユーザーフローをクリックしてください。以下の画面に行けば問題ありません。
「新しいユーザーフロー」をクリックしてください。今回は、アプリから「サインアップ・サインイン」の両方を行います。なので、以下の画面の通りに選択してください。もし特定の動作だけをユーザに許可する場合は、追加で「ユーザーフロー」を作成してください。
作成を押すと以下の画面に移ります。画面には映っていませんが、「名前」と「IDプロバイダー」は入力お願いします。変な名前を付けないようにするのと「IDプロバイダー」では「Email signup」を設定しておけば問題ありません。ここでつけた名前は後で必要になりますが、参照は簡単なので使うということだけ頭に置いといてください。
スクロールしていくと「ユーザー属性とトークン要求」が出てきます。これはサインアップ画面で収集する情報とログイン時にアプリに返答する値を設定することができます。カスタムで設定することができますが、とりあえずは画面と同じものを設定しておいてください。
全てを埋めれば作成が完了します。
アプリの登録
次にアプリを登録していきましょう。ここでやることのイメージとしては、「Reactから認証を使用します」というのをAADB2Cに登録するというものです。「アプリの登録」をクリックして以下のページに飛んでください。そして「新規作成」をクリックしましょう。
ここで特に重要な点としては、リダイレクトURIの設定です。「シングルページアプリケーション(SPA)」を選択して「http://localhost/azure」と入力しておきましょう。
以上でアプリの登録は終了です。
認証情報の収集
お疲れ様です。Azure Portalの操作はこれで最後になります。一応公式の解説もあるので置いておきます。Reactで認証を使用するために必要な認証情報を収集していきます。収集するための情報としては以下になります。
順番に解説していきます。clientIdは登録したアプリを開きましょう。
赤枠で囲っている値がclientIdになります。次にauthorityですが、こちらの値は自分で作成する必要があります。以下が作成に伴う資料になります。
ユーザーフローは先ほどの手順で作成したユーザーフローです。「B2C_xxxxxxxxxx」となっているかと思います。ドメイン名に関しては、「概要」をクリックして表示されるページの赤枠で囲った部分です。そちらのドメイン名からテナント名もわかります。
次に「knownAuthorities」ですが、こちらは「テナント名.b2clogin.com」が入ります。最後に「redirectUri」です。こちらは、アプリケーションの登録の際に設定した値と一致させる必要があります。今回は特別な設定をしていなければ「http://localhost/azure」になっているかと思います。
Reactでの認証情報設定と基本設定
やっとでコーディングまでたどり着きました。ファイル構造については以下になります。
それでは、先ほど用意した認証情報をEnvファイルに書き込んでおきましょう。
VITE_AADB2C_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxx
VITE_AADB2C_AUTHORITY=https://テナント名.b2clogin.com/ドメイン名/ユーザーフロー
VITE_AADB2C_KNOWN_AUTHORITES=ドメイン名
次に初期設定に必要なファイルです。「hooks」ファイルの中に「authAzure.ts」というファイルを作成して以下のファイルをコピペしてください。
cacheに関してですが、これは認証情報をどこに保存するかの設定になります。デフォルトでは「sessionStorage」に保存されています。セキュリティ的には「localStorage」よりも「sessionStorage」が良いようです。この辺りはUXなど考量して変更しましょう。
突然出てきたloginRequestですが、これはログイン時にオプション(IDプロバイダーの指定・言語の設定)をいろいろ設定できるようです。公式のページを見つけたので置いておきます。設定上scopesの設定をしないとエラーになるのでとりあえず空配列でも定義はしておきましょう。
最後にライブラリを使用するための認証状態の反映を行うコンポーネントを作成します。「utilities」ファイルの中で「AzureConfigComponent.tsx」を作成して以下のファイルをコピペしてください。
上記のコードの使い方は、App.tsxファイル内で以下のように使用します。
以上で事前準備が終了しました。
認証に関する処理をカスタムHooksにまとめる
認証や情報の取得などもろもろの処理をカスタムHooksにまとめます。「hooks」内に「useAADB2CAuth.ts」というファイルを作成して、以下の内容をコピペしてください。
ここで特に紹介する必要があるのは「isAuthenticated 」と「inProgress」になります。「isAuthenticated 」は認証済みの場合はTRUEで未認証の場合はFALSEになります。「inProgress」はMSALの動きに連動して値が変わります。値に関してはこちらのサイトが参考になります。アプリが起動したばかりの場合では、認証済の場合でも「isAuthenticated 」はFALSEになります。アプリの起動が終了すると「inProgress」の値は「None」になり、認証状態のチェックは終了します。こちらの値を使用することで認証の際、画面がちらつくのを防ぐことができます。
「userId」はアカウント作成時に自動で割り振られるIdを取得します。ライブラリを通してアカウント情報を取得します。そこからこねくり回して「userId」のみを取得しています。もし、情報がない場合は、空文字を返答するようにしています。
React認証ルーティングの定義
今回の構成としては以下の図になります、全体としてはページ3枚、ルーティングコンポーネント2個追加となります。これとは別にReact-router用のファイルがあることは年頭に置いておいてください。
想定しているパターンとしては、以下になります。
- 認証トップページ:認証なしでも閲覧可能でログインボタンやログアウトボタンが配置
- マイページ:要認証でログインユーザの情報を表示
ルーティング用コンポーネントは、機能によって分割しています。ここは口頭よりもコードの方がわかりやすいと思うのでコードの解説を行っていきます。
ページの作成
ここでは、表示するページについて解説・作成をしていきます。機能としてはとても単純なページになります。「components」内の「page」に「AzureADB2CPage.tsx」と「MyPage.tsx」のファイルを作成してください。
「AzureADB2CPage.tsx」の内部には以下のコードをコピペしてください。
ここでは、ログイン・ログアウトボタンの表示を行っています。ここでは、ライブラリの機能である「AuthenticatedTemplate」と「UnauthenticatedTemplate」について紹介します。これは名前の通り、認証がの有無によって表示の有無が決定されます。
「MyPage.tsx」の内部には以下のコードをコピペしてください。
ここでは単に「userId」を取得して出力だけをしています。とっても単純ですね。
ルーティングコンポーネントの作成
ここでは、ルーティングコンポーネントの解説・作成をしていきます。「router」内部に「RouterAuthenticateConfigAADB2C.tsx」というファイルを作成して、以下のコードをコピペしてください。
「RouterAuthenticatedCheck」では、認証状態のチェックのみを目的としています。「inProgress」の値が、「Startup」と「HandleRedirect」の場合は認証状態が未チェックの状態なのでLoading画面を表示しています。状態がチェック済みになるとPropsで渡したコンポーネントが出力されます。
「RouterHasAuthenticated」では、認証済み状態のときはPropsで渡したコンポーネントが出力され、そうでない場合ではリダイレクトされます。このルートは「RouterAuthenticatedCheck」内で使用するので、「RouterHasAuthenticated」まで処理が落ちてくる時には認証はチェック済みとなっています。
ちなみに「RedirectComponent」の内部は以下のコードです。僕の場合は「utilities」内で定義しています。こういったコンポーネントは使いまわせるので便利ですね。
最後に大元のルーティングファイルを調整してページの構成は終了します。大元のルーティングファイルは以下のように構成しています。ルーティング設計は、上部の図の通りに構成しています。
機能としては以上となります。
終わりに
お疲れ様です。今回はReactでAADB2Cの認証済みルーティング設計を行いました。ADとAADB2Cは同じものだと思って手を動かしてから違うことが判明することがあるため、認識をしっかりと確認しておきましょう。認証機能を簡単に実装できるのは非常にありがたいことです。
FirebaseとAADB2Cを両方使用してみた感想ですが、軽度の認証に関しては、どちらも優位性は見られませんでした。認証時に取得できる情報に関しては、AADB2Cのほうが実装に関する情報が簡単に入手できる傾向にあります。コンソールの使い勝手に関しては、Firebaseが優れていると思います。最終的には、デプロイ先や構成、価格など、多くの観点を混ぜ合わせて計算し、決定する必要がありますね。
エンジニアとしては、どっちでも使えるようにしておくのが安牌だと思って検証しています。
さて!認証機能を実装したWebアプリの作成を進めていきましょう。
ではまた~