BEACHSIDE BLOG

Azure と GitHub と C# が好きなエンジニアの個人メモ ( ・ㅂ・)و ̑̑

Azure AD B2C の ID プロバイダー ( IdP ) に AWS Cognito を追加する

Azure AD B2C は ID プロバイダー(Identity Provider, IdP, また OpenID Provider, OP)として使うことができます。

雑にいうとユーザーのパスワードは AAD B2C で管理されている状態です。

また、Azure AD B2C を Relying Party (RP) として使うこともできます。

ID プロバイダー は別のどこか(Facebook や Twitter とか Open ID Connect の仕様にそったとこだったら OK)に指定することができます。雑にいうとユーザーのパスワードは別の ID プロバイダー側で管理されていて、Azure AD B2C は認証とそのアプリの利用を繋ぐハブになっている状態です。

今回は以下図のように Azure AD B2C は Relying Party として使い、ID プロバイダーに AWS の Cognito に設定するのを試したメモです。

f:id:beachside:20200309182115p:plain

ってかこの記事、1月ごろに試したけど問題なくできたので雑な下書きで放置プレイしてたのを2月にちょっときれいにして...結局中途半端なまま公開を忘れてて5月になってしまいました。Cognito の UI とか既に変わってたらその時差の影響です。

(このブログの裏側でそんな放置記事がたくさん眠っています😅)

AWS Cognito のリソース作成

Cognito には 2つの管理があります。Azure AD B2C との OIDC での接続以外に興味ないので詳しくは調べてないですが、ざっくりこんな感じでしょうか。

  • ユーザープール: ユーザーとその認証を管理するところです。IdP ですね。こちらを使って Azure AD B2C と接続します。
  • ID プール: AWS のリソースへの管理ができるものです。ユーザープールで認証、ID プールで AWS へのリソースへのアクセスを認可するって位置づけでしょうか。今回は使いません。

f:id:beachside:20200306143952p:plain

ユーザープールの作成

AWS のマネジメントコンソールで Cognito を開く > ユーザープールの管理 をクリック > ユーザープールの作成をする をクリックします。
プール名を適当に入力して、今回は デフォルトを確認する をクリックします。

f:id:beachside:20200306145549p:plain

いくつか設定を見てみましょう。

属性

この画面では、サインインする ID を何にするか決めれます。任意のユーザー名か Eメールか電話かってやつですね。今回は無難に Eメールにしてみます。 あとは、属性として何が必要かを決めれます。とりあえずメールと名前くらいを設定してみました。
カスタム属性も作れますが今回私には不要です。

f:id:beachside:20200306150633p:plain

アプリクライアント

Azure AD B2C と接続するためのクライアント ID / シークレットを生成します。以下画面のように設定しました。認証フロー は雰囲気で「ユーザー名パスワードベースの認証を有効にする」を選びました。ドキュメントのリンクにとんでも "Client Side Authentication Flow" というタイトルのリンクに飛ぶので、これだよねってのは察せれますが、明確にそうは書いてない点が非常に悩ましいドキュメントやなと感じてます。他のチェックは必要に応じて付けますが、今回の検証で私の場合不要です。

とりあえずこれで アプリクライアントの作成 をクリックします。

f:id:beachside:20200306152032p:plain

確認

後は特に設定したいものはないので、画面左側の 確認 をクリックして、プールの作成をクリックして作成を完了させます。
作成を完了したら、引き続きこの Cognito の画面で設定をしていきます。

アプリ統合の設定

プールを作成したらアプリ統合のメニューが出てきます。この配下を設定していきましょう。

アプリクライアントの設定

次は、アプリ統合 > アプリクライアントの設定 を開き、以下の図のように設定します。

f:id:beachside:20200309085953p:plain

上図の赤の四角について簡単に説明します。

  • 有効な ID プロバイダ: チェックを付けます。

  • コールバック URL:ここは重要です。Azure AD B2C のコールバック URL を入力します。公式ドキュメントのここら辺を参考にして、https://<your-B2C-tenant-name>.b2clogin.com/<your-B2C-tenant-name.onmicrosoft.com>/oauth2/authresp って値を入れます。具体的な例としてはまず Azure ポータルの Azure AD B2C のリソースの 概要 を開いて、ドメイン名を確認しましょう。
    f:id:beachside:20200309091516p:plain:w400
    ドメイン名の値が例えば sample.onmicrosoft.com であれば、AWS Cognito で入力するコールバック URL は、https://sample.b2clogin.com/sample.onmicrosoft.com/oauth2/authresp となります。あとはカンマ区切りで複数の URL を登録できますので Cognito 単独でログインの確認をする際の検証用に https://jwt.io を入力しています。

  • 許可されている OAuth フロー: これは AAD B2C でどのフローを使うか次第です。Client credentials は使わないので、私の場合はこの二つをチェックしています。

  • 許可されている OAuth スコープ: 使うものを適当にチェックします。

最後に画面右下の方にある 変更の保存 ボタンをクリックして保存します。

Cognito 側の設定はこんなもんで、次は Azure AD B2C の設定をします。Cognito の情報もコピペで使うので画面はそのまま開いておきます。

ドメイン名の設定

アプリの統合 > ドメイン名 を開き、ドメインを適当に入力します。下の図は既にドメインを登録した状態の画面になります。

f:id:beachside:20200309152831p:plain

これがなぜ必要なのか(カスタマイズはできるにせよ、なぜなくてもデフォルトのURLのルールでログインできないのかとか)疑問がわいてるところです(そういうルールだって言われたらそれまでですが)が、作ってないとこんなエラーが出ます。ので、作りましょう。

{"code":"BadRequest","message":"The server did not understand the operation that was requested.","type":"client"}

ドメイン名を登録したら、Cognito 単独でログインやサインアップができるかの確認ができるようになります。ログインする URL のテンプレートは公式ドキュメントのここに書いていますが、今回は必要ないので飛ばします。

Azure AD B2C で ID プロバイダーの追加をする

ここからは Azure 側での設定です。

事前準備

Azure AD B2C のテナントの作成アプリケーション登録ユーザーフローの作成ができてる前提で話を進めます。できてない場合は以下のドキュメントのチュートリアルの1 B2Ctenanntono 作成から3のユーザーフローの作成をしましょう。

docs.microsoft.com

ID プロバイダーの追加

Azure ポータルで Azure AD B2C のリソースを開き、ID プロバイダー > 画面上部の 新しい OpenID Connect プロバイダー をクリックします。(ID プロバイダーの一覧で出てる Amazon は、ドキュメントを見る限り Amazon の EC サイトの方のアカウントの連携だと思います(試してないけど))。

f:id:beachside:20200309093644p:plain:w400

それぞれの値を入力します。スコープ以下は、必要に応じて選択したり入力したりするものなので、あくまで今回私がやりたい検証に合わせた値になります。

キー
名前 適当に入力します。
メタデータ URL 後述します。
クライアントID Cognito の 全般設定 > アプリクライアント の中のアプリクライアント ID の値。
クライアントシークレット Cognito の 全般設定 > アプリクライアント の中の アプリクライアントのシークレット の値。
スコープ 今回は openid
応答の種類 code/id_token どちらでも必要な方で。
応答モード form_post
ユーザー ID sub
表示名 name
電子メール email

補足1: メタデータ URL の入力

メタデータ URLは、Cognitoでは以下の形式です。<リージョン名> と<プールID> は自身の Cognito の値を入れる感じです。

https://cognito-idp.<リージョン名>.amazonaws.com/<プールID>/.well-known/openid-configuration

Cognito の 全般設定 を開くとプール ID がわかります。プール ID の値は、"リージョン名" + "_" + "ID" みたいな形式になってますね。

f:id:beachside:20200309100227p:plain:w600

例として プール ID が ap-northeast-1_ABCD123 であれば、こんな値になります。

https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_ABCD123/.well-known/openid-configuration

入力する前にブラウザーでメタデータが表示されるか試しておくとよいでしょう。

補足2: 属性マッピング

また、ユーザー ID、表示名、名、姓、電子メールとかの属性のマッピングについて、Cognito 側の属性は OpenID Connect の仕様に添ってるよーって以下のドキュメントの "Standard Attributes" ってとこあたりに書いてます 。マッピングのキー情報を見たいときはこちらを確認しましょう。

Azure AD B2C から動作確認

Azure ポータルの Azure AD B2C で左メニューのユーザーフロー をクリックし、今回実行するユーザーフローをクリックします。

f:id:beachside:20200309162951p:plain

ID プロバイダーをクリックします。

f:id:beachside:20200309163040p:plain

今回設定した Cognito の プロバイダーにチェックをして画面上部の保存をクリックします。私の場合、今回は赤枠で囲ってるやつが今回作ったやつです。

f:id:beachside:20200309163154p:plain

後は ユーザーフローを実行します をクリックします。アプリケーション や 応答 URL を確認してユーザーフローを実行します をクリックします。
ちなみに Azure AD B2C で検証用の応答 URL には https://jwt.ms を設定しておきました(jwt.io ではなく jwt.ms)。

f:id:beachside:20200309163716p:plain

対象の AWS -beachside cognito をクリックします。(私のこの場合、Cognito の検証してたせいで2つの Cognito があるのがちょっとややこしいですねw)

f:id:beachside:20200309163547p:plain

これで Cognito のログイン画面に遷移します。ログインできたら jwt.ms の画面に遷移します。
こんな感じで認証ができたことが確認できました。

f:id:beachside:20200309164106p:plain

トラブルシュート

An error was encountered with the requested page.

私の場合、Cognito の アプリの統合 > アプリクライアントの設定 にある コールバック URL の設定間違いで発生しました。見直したら改善しました。

f:id:beachside:20200306131809p:plain:w400]

Only custom auth

Cognito でログインすると Only custom auth と表示が。

f:id:beachside:20200309164437p:plain:w400

これは、Cognito の 全般設定 > アプリクライアント で、認証フローの設定が 「Lambdaトリガーベースのカスタム認証を....」ってやつしかチェックがついてないときに発生します。
「ユーザー名パスワードベースの認証を有効にする」にチェックをいれてあげましょう。

f:id:beachside:20200309164745p:plain