Amazon Cognitoの外部IdP(SAML)として、AzureADを使う

# はじめに

Amazon Cognito は、ウェブおよびモバイルアプリの認証、承認、およびユーザー管理機能を提供します。ゼロから認証機能の実装するのは大変なので、実装の負担などを軽減できます。

今回の記事は、Cognito の IdP として、Azure AD を利用して、Hosted UI を利用する方法を紹介します。Azure AD は SAML を利用できるため、SAML を使った方法となります。SAML を利用できる他の IdP も、もちろん連携可能です。



# 前提条件と確認

Cognito UserPool の基本的な設定は完了している状態で進めていきます。

Azure AD との連携を進める際に、いくつかの値をメモっておくと便利です。後の手順で使っていきます。



User Pool ID

![image-20220124182529491.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/86910f06-ffba-b920-68fe-5c82361114c6.png)



Cognito Domain 

![image-20220124182636564.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/301323ac-650d-80cf-e852-35841a1398b0.png)







# Azure AD の設定

まず、Azure AD の設定を進めていき、Cognito と SAML のやりとりを出来るようにします。Azure AD を開きます。

![image-20210525011457865.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/2dda919a-6399-0365-bf0a-68d4d770174b.png)



エンタープライズアプリケーションを選択します。

![image-20210525012234220.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/3a6ff3bc-c6af-d823-f804-56307d9c20d6.png)



新しいアプリケーションを選択します。

![image-20210525012253772.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/05ff2b75-2d14-aee3-84d3-0d992f4a2d41.png)



独自のアプリケーションの作成を選びます。

![image-20210525012354046.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/c0f8f61e-d6c6-3c8e-7c3d-71d5f2aa8271.png)



適当な名前を入れて、作成を押します。

![image-20220123211918326.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/5564efca-6058-1908-4de0-ea5cff2f4117.png)



シングルサインオンのメニューから、SAML を選択します。

![image-20210525012807732.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/54276a8b-28ce-fd1a-5a2a-e80300322299.png)



基本的な SAML 構成の個所で、編集を押します。

![image-20220123212027799.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/3d3a11d6-66f8-ef5b-83f1-531f981774a6.png)



次のパラメータを入れて保存を押します。「前提条件と確認」で確認した Cognito UserPool ID や、Domain の値を使っていきます。

**識別子**

```
# フォーマット
urn:amazon:cognito:sp:UserPoolID

# 入れる値
urn:amazon:cognito:sp:ap-northeast-1_exksQ29lq
```



**応答URL**

```
# フォーマット
https://yourDomainPrefix.auth.yourRegion.amazoncognito.com/saml2/idpresponse

# 入れる値
https://sugi01-test.auth.ap-northeast-1.amazoncognito.com/saml2/idpresponse
```

![image-20210525013144079.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/545866a3-62aa-ccad-0d76-d49a2241bb62.png)



設定が反映されます。

![image-20210525013241892.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/c7f88c21-6519-3507-6dae-95727f0ef408.png)



フェデレーションメタデータ XML をダウンロードします。

![image-20220123212312442.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/dcb3071c-9cbd-04c8-7ac7-486ca34d7f6b.png)



ユーザーの追加を押します。

![image-20220123212405827.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/c86f709f-ed55-c816-0f07-b1db4f7c5b8d.png)





Azure AD 上のユーザーを選択します。

![image-20220123212508278.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/96367440-42b1-8dc2-1704-586996b2fc56.png)



追加完了です。

![image-20220123212531776.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/4d19ec31-c4e6-0f3d-ef27-3baeb097856a.png)



# Cognito UserPool に IdP の追加

Cognito UserPool の画面を開き、Add identity provider を選択します。

![image-20220123211655357.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/eb737968-df6f-dc75-7120-7509870afca0.png)



Azure AD との連携に SAML を利用するため、SAML を選択します。

![image-20220123212642736.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/4122cbbb-2a92-92f0-806d-a445b596d843.png)



分かりやすい名前を入れて、Choose file を選び、Azure AD からダウンロードしてきた「フェデレーションメタデータ XML」をアップロードします。

![image-20220123212714549.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/1f68d35b-e2f3-715d-3505-05a716aaa755.png)



SAML attribute に、次の文字列を選択して、Add identity provider を選びます。

```
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
```

![image-20220123212942012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/fe2fcb53-8be1-2d9a-37d4-b54c6592b597.png)



設定が追加されました。

![image-20220123213006784.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/22258e8f-68ae-8e7d-3be5-dd8f97eb721b.png)



# Cognito で Hosted UI の設定

追加した Azure AD の設定を Hosted UI で利用するために設定変更をしていきます。App Integration を選択します。

![image-20220123213324315.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e7c0703f-8bf4-46ba-e43b-682e5488d870.png)



事前に設定していた、App Client を選択します。

![image-20220123213359346.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/8aa998a0-1775-a6f6-40e2-32acc3ee0eff.png)



Edit を押します。

![image-20220124183847013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/51460ae6-98e3-eb72-14d0-2a7f88571ce2.png)


Allowed callback URLs には、元々持っているアプリケーション側で用意しているコールバックを受け取る URL を指定します。基本的には、アプリ側で独自実装する部分です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/d35d3338-c2e8-c81b-93d7-63b9e3e0dab3.png)



Identity Provider の個所で、Azure AD を追加して、Save Changes を押します。

![image-20220123213623548.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/5f88315e-a12f-04fb-2d2c-18f9ee9c1462.png)



追加されています。

![image-20220123213650462.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/9f162e88-7ad3-0699-7f7d-99e6b315f7a3.png)



# 動作確認

ここまでで設定が完了しました。Cognito の Hosted UI と連携しているページから、Hosted UI を呼びだしてみましょう。

Hosted UI の画面を呼び出すには、次のように適切なパラメータを指定した Cognito Domain を指定します。

```
https://sugi01-test.auth.ap-northeast-1.amazoncognito.com/login?response_type=code&client_id=xxxxxxxxxxxxxxxx&redirect_uri=https://yourwebsite/cognito_callback/callback
```

![image-20220124184218837.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/f02e946b-7687-3ca7-9aa4-d4c823f5bd6e.png)



Azure AD を選択します。

![image-20220124184248981.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/67a32c9b-8a98-f897-79da-cbc36849e7fa.png)



選択した User名をいれて、次へを押します。

![image-20220124184338244.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/1f1fe7dc-2d31-3f87-0a00-30caf5e8952b.png)



パスワードを入れます。

![image-20220124184359725.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/91ff8f8f-7671-88f8-ded2-fd169024c13a.png)



用意している動作確認用 Web アプリケーションで、ログイン完了が確認できました。

![image-20220124184434284.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e6ddb032-d9aa-f104-6114-0055fb65b742.png)



今回の動作確認用 Web アプリケーションでは、Cognito から発行された ID Token などは、Cookie に保存しています。

![image-20220124184603901.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/0ee99d41-5927-caa0-6fb5-e0de46d934f9.png)





ID Token などは、JSON Web Token となっており、人間が読みやすい形式にデコード可能です。

クリティカルな情報を扱っていない場合は、こういったサイトでデコードをしてみるといいでしょう。

https://jwt.io/



実際のデコードした例です。秘密な情報は一部マスクをしています。ユーザーの認証元の Identity Provider に付けた任意の名前や、メールアドレスなどが確認できますね。JWT が改ざんされていないか確認したうえで、この情報を活用しながら認可を実装する方法もあると思います。

```
{
  "at_hash": "_k1sneTM4Pij2BWd60qyyQ",
  "sub": "618a7bf0-0653-47a9-82fe-cc0a7d0abe9e",
  "cognito:groups": [
    "ap-northeast-1_exksQ29lq_AzureAD",
    "GeneralGroup"
  ],
  "email_verified": false,
  "cognito:preferred_role": "arn:aws:iam::xxxxxxxxxxxx:role/Cognito_IdentityPoolTestAuth_Role",
  "iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_exksQ29lq",
  "cognito:username": "azuread_testuser01@yourgmail.onmicrosoft.com",
  "nonce": "4qqibhEcSYhORT7BcszM3LjalVGYP9YhHITM30YXyAzmryQRHyP47uPRUUddWBwC1kGssesBuTnH7Au4PHlR09slq1MYcoHOjJ8Z5s_PUP1L95OpPP7WbYNNrgbcpt4bJ-AeeElg1EZQ9g9LCJ-cG2fYcJDfHyj9cUmGyWUtpac",
  "origin_jti": "e2eaba2a-ddf7-4c81-8dd2-8f5116034fb4",
  "cognito:roles": [
    "arn:aws:iam::xxxxxxxxxxxx:role/Cognito_IdentityPoolTestAuth_Role"
  ],
  "aud": "5v9cdqqgua1imohsovur3bt7e4",
  "identities": [
    {
      "userId": "testuser01@yourgmail.onmicrosoft.com",
      "providerName": "AzureAD",
      "providerType": "SAML",
      "issuer": "https://sts.windows.net/54d4fb23-4655-46de-ab3a-4698ab819886/",
      "primary": "true",
      "dateCreated": "1642941543991"
    }
  ],
  "token_use": "id",
  "auth_time": 1642941545,
  "exp": 1642945145,
  "iat": 1642941545,
  "jti": "1637b57b-6c5f-4bd7-a6d6-878c8ee2d474",
  "email": "testuser01@test.com"
}
```



# ログインで自動生成されるもの

Azure AD(SAML) を使って Cognito にログインしたときに、いくつか自動生成されるものがあります。

まず、グループです。Azure AD(SAML)で連携したことが自動的に判別されて、Group が作成されています。

![image-20220124185842840.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/c1f04df5-5934-9054-e9ca-8eab4ec8d1df.png)



つぎに、ユーザーです。Azure AD 上の名前などを基に、Cognito 上でユーザーが作成されます。

![image-20220124185715137.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/cd02f413-3a57-d9a7-9d0a-bb49f4ceaf5e.png)



なお、このユーザーは自動的にグループに所属しています。

![image-20220124185757439.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e3a7be99-3ec4-08a5-f4f9-70e749f0e790.png)



# Azure AD に直接ログイン

Azure AD を使ったログインは、Hosted UI を経由する方法を動作確認で行いました。この方法でもいいのですが、Hosted UI 上のボタンのリンクを取得してくることで、これをそのまま直接ログインに利用できます。

Hosted UI 上で、どの IdP を利用するか選択する画面に移動します。

![image-20220124190104722.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/74e2ac84-86fa-45f9-f8dc-fe12bb612ba6.png)



Chrome で Developer Tools を開いて、マウス選択が出来るボタンを押します。

![image-20220124190316919.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/520c0fa9-330b-372c-5a8d-37d62c2cca19.png)



Azure AD のログインボタンをマウスで重ねると、HTML タグを確認できます。ここにある href で指定されている URL をコピーしてきます。

![image-20220124190539550.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/9c20d313-5d98-d8a9-ddf3-8329d7b0fa77.png)



半角スペースは「+」に変換しつつ、URL を整理します。一部マスクしていますが、こんな感じですね。

```
https://yourdomain.auth.ap-northeast-1.amazoncognito.com/oauth2/authorize?identity_provider=AzureAD&redirect_uri=https://secret/callback&response_type=CODE&client_id=secret&scope=aws.cognito.signin.user.admin+email+openid+phone+profile
```



この URL を HTML タグに埋め込むと、直接の Azure AD ログインへのリンクが生成できます。



# 参考URL

【AWS】Cognito ユーザプールをAzure ADをIdPとして構築する(後編)
https://qiita.com/kei1-dev/items/c8ae68e975dccb2902be