AWS Cognitoを使用したSSO実装

業務でSSO開発を行ったので、備忘録。

# 対象者
- Cognitoを使用してSSO連携したい人
- SAML認証を使用してSSO連携したい人
- IdPを簡潔に設定してSSO連携の動きを知りたい人

# SSOとは
Single Sign-Onの略で、ユーザーが複数のサービスに一度のログインでアクセスできるようにする技術です。これにより、ユーザーエクスペリエンスが向上し、パスワード管理のオーバーヘッドも削減されます。

# SAMLとは
Security Assertion Markup Languageの略で、SSOのためのXMLベースのオープンスタンダードです。SAMLは、異なるドメイン間での認証と承認データの交換を可能にします。

# AWS Cognitoとは
Amazon Web Services (AWS) が提供する認証・認可サービスです。Cognitoを使用すると、Webアプリケーションやモバイルアプリケーションに簡単にユーザー管理と認証機能を追加することができます。

# 実装の流れ
今回は下図を構築していきます。App部分は後日時間があれば別記事にします。
SAML IdPはKeycloakを使用しています。オープンソースのアイデンティティ・アクセス管理ソフトウェアなのでローカル環境で構築できます。

1. Cognito設定(ユーザープール作成)
2. IdP設定（Keycloak構築)
3. Cognitoのアプリケーションクライアント構築
4. 動作確認(Cognito アプリケーションクライアントのホストされたUIから確認)  

![スクリーンショット 2023-09-24 22.01.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/c569490a-1d7a-9d7f-a7a1-7be59f432da5.png)

# 構築
## Cognito設定
AWSマネコン > AWS Cognito > ユーザープール作成

### ユーザープール作成

SSO連携させたいので「フェデレーテッドアイデンティティプロバイダー」チェック
![スクリーンショット 2023-09-24 20.57.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/279e07ae-3c17-0dc8-b92a-5ff97fc51238.png)
SSO連携時のマッピングをemailで行うので「Eメール」チェック
フェデレーティッドサインインのオプション：SAML

![スクリーンショット 2023-09-24 20.57.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/54157fb7-efdb-9373-94bc-c94dd0fc8327.png)

この辺は適宜設定してください。（今回に影響なし）
パスワードポリシー：Cognitoのデフォルト
![スクリーンショット 2023-09-24 20.58.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/996cb3f5-f1eb-d151-7d1e-ec8fd6884fb4.png)

MFAなし
![スクリーンショット 2023-09-24 20.58.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/04f4998d-5b74-3bfe-38a8-8690776c8922.png)
![スクリーンショット 2023-09-24 20.59.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/55980e6e-8dba-358a-f896-694479f822b9.png)
![スクリーンショット 2023-09-24 20.59.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/804686ea-be0f-9010-5cf7-beef2de687cf.png)

「CognitoでEメールを送信」チェック
![スクリーンショット 2023-09-24 21.00.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/2fbc082d-2137-bc11-9e9b-5209c973b5e7.png)

IdP(keycloak)設定後に設定するので「後で」クリック
![スクリーンショット 2023-09-24 23.52.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/ee6c25aa-74e7-a661-e737-add0d99d7220.png)


ユーザープール名：任意の値
![スクリーンショット 2023-09-24 21.01.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/bf05adc4-a204-19de-e3df-aa6a2b6f9524.png)

ドメイン名はSSO連携で必要になるため「Cognitoドメインを使用する」にチェック
ドメイン名は任意の値
![スクリーンショット 2023-09-24 21.04.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/770bfbde-559f-c5d3-edd7-c8cb67378cd4.png)

「パブリッククライアント」チェック
アプリケーションクライアント名：任意の値
クライアントのシークレットを生成しない：チェック
許可されているコールバックURL：https://jwt.io →後から説明します。
![スクリーンショット 2023-09-24 21.04.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/adddca99-7421-597a-81d3-49a15b921a47.png)
![スクリーンショット 2023-09-24 21.05.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/5d307388-9f81-6e3f-3e47-85c273076464.png)

作成できました!!ユーザープールIDはkeycloak設定で使用します。
![スクリーンショット 2023-09-24 21.06.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/fcbbd1db-2557-cbc2-fea0-abfb4c79d589.png)


### IdP設定（Keycloak構築)
前提：dockerをローカルPCに構築済
今回IdPはローカル環境内に構築していきます。Dockerを使用するので各自構築お願いします。

docker-compose.yaml
```
version: '3'
services:
  keycloak:
    image: quay.io/keycloak/keycloak:latest
    container_name: keycloak
    tty: true
    stdin_open: true
    ports:
      - "18080:8080" # 8080は被りやすいので別のポートに設定
    volumes:
      - .keycloak:/opt/keycloak/data # DB情報等が格納されます
    environment:
      KEYCLOAK_ADMIN: admin # 管理ユーザーIDを設定
      KEYCLOAK_ADMIN_PASSWORD: admin # 管理ユーザーのパスワードを設定
    command:
      - start-dev --http-relative-path /auth # 開発モードで起動
```

Docker起動
```
$ docker-compose up -d
```

Keycloak起動
ブラウザで「 http://localhost:18080/auth/ 」入力。以下のように表示されたら成功!!
![スクリーンショット 2023-09-24 20.53.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/84532902-465e-2305-0afb-d971417a8c4b.png)

今からKeycloakの設定を行なっていきます。
Keycloakの細かい内容を知りたい場合は公式ドキュメントを読んでください。
https://keycloak-documentation.openstandia.jp/

IdP側の設定
- レルム作成（多分テナント単位みたいなもの）
- レルムのロール作成
- クライアント作成（今回はCognito側の情報設定）
- IdP内にユーザー追加


「Administration Console >」クリック → Dockerファイルで設定した、ユーザー、PWを入力
![スクリーンショット 2023-09-24 20.53.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/d57b615d-0833-5d08-36c4-744056b166cb.png)

レルム作成
サイドメニュー「master」クリック→「Create Realm」クリック
![スクリーンショット 2023-09-24 20.53.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/954f5953-2949-c181-8a44-763be112ed03.png)
Realm name 「Test」入力、「Create」クリック
![スクリーンショット 2023-09-24 20.54.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/05550798-c74c-6c6a-0139-acbe9d0f02d5.png)
サイドメニューから「Realm roles」クリック、「Create role」クリック
![スクリーンショット 2023-09-24 20.54.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/0edb2e1a-d1d6-319a-1e3b-43cd3747fd46.png)
「Role name」に「Test-role」入力、「Save」クリック
![スクリーンショット 2023-09-24 20.55.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/c28e6db1-d5dd-bc9a-9eaf-c204bebb69d2.png)
サイドメニューから「Clients」クリック、「Create client」クリック
![スクリーンショット 2023-09-24 20.55.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/b98d5d19-5cf1-edfc-df33-ee1ac1fbbcd7.png)

下記設定：
Client Type: SAML
Client ID: urn:amazon:cognito:sp:<ユーザープールID>
※ユーザープールIDは各自作成したユーザープールで確認
![スクリーンショット 2023-09-24 21.08.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/3afc89c0-3a2b-beef-9f98-0d0804f37e50.png)

IdP(Keycloak)は、SAMLアサーションを使用して、このエンドポイントにユーザーをリダイレクトするので以下の設定が必要です。
Keycloak側でCognitoの帰り先を設定するイメージ。
Valid redirect URIs: 
https://< yourDomainPrefix >.auth.< region >.amazoncognito.com/saml2/idpresponse

※以下公式ドキュメント参考：https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-user-pools-saml-idp.html

「Save」クリック
![スクリーンショット 2023-09-24 21.11.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/48e03ba2-2f8c-fb5f-c63e-4ddea15d3ab5.png)

今回クライアント署名は必要ないため、OFFにします。
「Keys」タブ、「Client signature required」OFF
![スクリーンショット 2023-09-24 21.12.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/0a221bd4-6a3d-2824-e61a-bfe4a1b65fdd.png)

Service ProviderであるCognitoとIdp（Keycloak）をマッピングしていきます。
「Client scopes」タブから作成したクライアントをクリック、「Configure a new mapper」クリック
![スクリーンショット 2023-09-24 21.12.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/4ec859d4-1ab9-613f-1bcd-e45470f7b95c.png)
![スクリーンショット 2023-09-24 21.12.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/79283287-11b7-f716-a0f6-7572984ce987.png)

「User Property」クリック
![スクリーンショット 2023-09-24 21.13.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/85ac11b7-c89e-c7b4-641a-4d9c431ceac3.png)

Cognitoユーザープールでemailをサインインオプションに設定しているため
下記設定後、「Save」クリック
Name:email
Property:email
Fiendly name: email
SAML Attribute Name: email
![スクリーンショット 2023-09-24 21.13.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/5657e709-91ea-5c9f-0f60-59af920a6cc9.png)

サイドメニュー「Clients」から「Clients list」タブクリック、先ほど設定したリストをクリック
![スクリーンショット 2023-09-24 21.14.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/edf6e1c3-a9d0-48ab-02a8-a70bbc79260d.png)

SAML設定で認証連携を行うにはユーザーの識別子を連携する必要があります。
同じユーザーを表す際に永続的に同じ識別子が使われる場合、「persistent」となります。

Name ID format:persistent
Force name ID format:ON
![スクリーンショット 2023-09-24 21.16.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/bf1e34c3-e37e-5114-541d-0994d54c4cf7.png)

サイドメニュー「Realm setting」クリック、「Requlre SSL」：Noneに設定
![スクリーンショット 2023-09-24 21.17.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/bfe6099a-963f-6fda-a49e-db1fba73dbc6.png)

「SAML 2.0 Identity Provider Metadata 」をクリック、xmlファイルとしてローカルに保存しておきます。
後ほどCognito設定時にメタデータをアップロードする時に使用します。
![スクリーンショット 2023-09-24 21.17.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/841d1c2c-858b-176d-493a-24e59500ec0a.png)

ユーザー追加
サイドメニュー「Users」クリック、「Add user」クリック、以下設定後「Create」クリック

Username:test_keycloak
Email:任意の値
![スクリーンショット 2023-09-24 23.29.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/2a594d73-1a33-4606-dd02-1be323098b27.png)

「Credentials」タブクリック、「Set password」クリック
![スクリーンショット 2023-09-24 21.20.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/ac7cd70d-aee8-741a-f76f-ad7f1c0c7ec8.png)
任意のパスワード設定、Temporary:Offで「Save」クリック
![スクリーンショット 2023-09-24 21.20.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/e40fceb1-655b-4063-660c-3625f6894fcd.png)

ユーザーに対して、ロールをマッピングしていきます。
サイドメニュー「Users」クリック、「Role mapping」タブクリック、「Assign role」クリック
![スクリーンショット 2023-09-24 21.21.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/f7acb318-9412-2d95-390c-1a6567e1fe2e.png)

先ほど作成したロール「Test-role」を選択し、「Assign」クリック
![スクリーンショット 2023-09-24 21.21.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/05807224-5490-b246-f4aa-4c5a6871e59c.png)

keycloakの設定は以上です（長いですね。。。）
再度Cognito設定をしていきます。

### アプリケーションクライアントの設定
先ほど作成したユーザープールを選択してください。
IdPの設定を行なっていきます。

「サインインエクスペリエンス」タブクリック、「アイデンティティプロバイダーを追加」クリック
![スクリーンショット 2023-09-24 21.21.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/7dc506fd-258a-6903-96ba-8e553367f09c.png)
「SAML」チェック
![スクリーンショット 2023-09-24 21.22.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/b9449131-1999-7aad-043f-363035b8e74b.png)
メタデータドキュメントをアップロードで先ほどKeycloakでローカルに保存したxmlファイルをアップロード
![スクリーンショット 2023-09-24 21.22.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/3460b281-fc1c-b0e9-4146-13ff53e2d1c4.png)
SAML属性：email
![スクリーンショット 2023-09-24 21.22.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/a629c1fb-ba74-1df7-6d3f-77b7b857bba5.png)

「アプリケーションの統合」タブクリック、作成したアプリケーションクライアントクリック
![スクリーンショット 2023-09-24 21.23.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/b163993f-bba2-1d0b-090d-0f0947dbc652.png)

![スクリーンショット 2023-09-25 0.00.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/f9218dc4-4cfc-224c-2374-4ac26c2fdd5d.png)

許可されているコールバックURL:https://jwt.io

![スクリーンショット 2023-09-25 0.01.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/f278285d-043d-aa41-186c-2b5a77b78979.png)

IDプロバイダーに先ほど作成したIDプロバイダーを追加、保存
OAuth2.0許可タイプは今回「暗黙的な付与」にしています。
本来は「認可コード付与」を選択するのですが、リダイレクトされたhttps://jwt.io でアクセストークンの確認をしたいので設定しています。
![スクリーンショット 2023-09-25 0.01.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/4a8936ee-f6f4-3405-8733-7ed733821ea1.png)


### 動作確認
AWSマネコン > Amazon Cognito > ユーザープール > アプリケーションの統合 > ホストされたUIで「ホストされたUIを表示」クリック
![スクリーンショット 2023-09-25 0.00.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/3776ec74-8c6c-0c23-8e75-66402103b370.png)

「Keycloak」クリック
![スクリーンショット 2023-09-25 0.03.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/5ea72199-181c-5a9b-80d0-d94bae9fed98.png)

keycloakのログイン画面に飛びます。emailとPasswordを入力
![スクリーンショット 2023-09-25 0.04.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/af47e8e7-2eb1-b386-2848-90fa7f99fc3a.png)

ログインが成功すれば、許可されているコールバックURL：https://jwt.io で設定した画面に飛びます。
今回リダイレクトする際に、アクセストークンが付与されます。jwt.ioのサイトでは、渡ってきたアクセストークン(jwt）をパースして表示してくれます。
![スクリーンショット 2023-09-25 0.25.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660432/16f4b487-237f-6945-1425-7dd5a25b182d.png)


# 最後に
AWS CognitoとKeycloakを組み合わせて、SAMLベースのSSOを簡単に実装することができます。　初めてSSO連携を取り込む方はローカルで確認できるのでぜひやってみてください。