OktaとAWS Cognito連携 ~SAML編~

# はじめに

下記YouTube動画のやってみた記事になります。
理解が難しかった部分をメモに残しながら記事にして行こうと考えています。

https://www.youtube.com/watch?v=O-HuJqPwsTc&t=701s

OktaはOkta Developerを使っています。

https://developer.okta.com/

### 動画との差分

- 【Okta】Attribute Statements
    - ログイン時に取得出来るユーザー属性を変更

# イメージ
1. ホストされたUIにアクセス（※ログイン画面ページ）
1. OktaまたはCognitoのユーザーでログイン出来るページ
1. 下図②のokta-samlをクリックするとOktaログインページに飛ぶ
1. ログインするとログイン後のリダイレクト先として設定したページに飛ぶ（※）
1. ログインユーザー情報が取れる

※ここではテスト用に（ログイン後にアクセストークンを取得してユーザー情報が取れることを確認したいたために）*https\://jwt.io*をログイン後のリダイレクト先として設定しています。

![result.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/ad9e649d-8a25-63d1-5dad-d10f7dad8fa8.jpeg)

上記を作った上で、Okta✖️Cognitoを実際にフロント（React）に組み込む方法については別途記事にしたので、もし、そっちの方が興味あるよー、と言う方は良かったら見て下さい。

https://qiita.com/gossan/items/c2352c6696c9527f1327

# Cognito設定①

AWSマネコン > AWS Cognito > ユーザープール作成
## サインインエクスペリエンスを設定
![c_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/76c8407c-f027-a8ee-64e0-509ceee53631.png)
## セキュリティ要件を設定

- パスワードポリシーモード：Cognito のデフォルト
- MFA の強制：MFAなし

![c_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/6133b403-5a68-68ca-8caf-da1a4390af99.png)

### ユーザーアカウントの復旧

![c_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/343bbb61-89d5-b3c6-d89c-fd25aee345ac.png)


## サインアップエクスペリエンスを設定

- 「自己登録を有効化」のチェックを外す

![c_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/659a7c19-09a9-4b94-fc14-b4dddaad5e25.png)
![c_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/2dd110b6-0e2e-3904-eb74-8a251fc93f65.png)
![c_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/f8547ad2-8b5c-e5e5-7c7c-13082c75f7fb.png)

## メッセージ配信を設定

- 「Cognito で E メールを送信」を選択する

![c_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/99a2ca4d-a8d0-1d7b-8541-e4e0e21b0601.png)

## アプリケーションを統合

- ユーザープール名:okta-sso-20230301（※任意のもの）
- ホストされた認証ページ：CognitoのホストされたUIを使用にチェック

![c_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/d5374933-40ef-eb9d-7a10-394c9330cc77.png)

- ドメインタイプ：Cognitoドメインを使用する
- Cognitoドメイン：okta-sso-20230301（※任意のもの）

![c_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/9d7ffc60-abca-6394-2e83-9a5306df81ad.png)

- アプリケーションクライアント名：okta-sso-20230301-client（※任意のもの）
- クライアントのシークレット：生成しないにチェック
- 許可されているコールバックURL（※）：*https://jwt.io*

※ログイン後にリダイレクトされるページ。jwt.ioを設定するのはあくまでテスト用。ログインユーザーの情報が取得出来ているかなど確認するのに便利。

![c_11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/cced592f-22ac-45c7-7130-b919896de079.jpeg)

- OAuth 2.0 許可タイプ（※）：**暗黙的な付与**
- OpenID 接続スコープ：OpenIDのみ選択

![スクリーンショット 2023-03-08 17.25.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/288c5de4-9ef8-4687-2f0a-2321d7e28271.png)

※「暗黙的な付与」について

"暗黙的な付与"をすると、ログイン後、リダイレクトされるhttps\://jwt.io に対してアクセストークンをURLのパラメーターで渡せるようになる。今回はパラメーターで受け取ったトークンをパースしてユーザー情報が取れているかなど確認したいため"暗黙的な付与"を選択している。本来は、“認証コード付与”を選択する方が安全。

## 確認および作成
確認して問題なければ「ユーザープールを作成」する。

# Oktaの設定
## ユーザー属性設定
認証をかけるアプリでのログイン時に取得したいユーザー情報を設定する。

「Directory」>「People」よりユーザーを選択、Profileタブを開く。
「Edit」をクリックして下記を設定する（※未設定の場合のみ）。

- First name(firstName)
- Last name(lastName)
- Display name(displayName)
- Nickname(nichname)

![okta_user.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/40655322-4178-c4c2-a4bb-b56ef6961424.jpeg)


## アプリケーション設定

Applications > Applications > 「Create App Integration」
![o_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/32b7e63c-de6e-7f52-1f28-b5cb2e6e2a3b.png)
SAML 2.0を選択する。
![o_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/10d7f107-dc46-5077-8272-e39ed14503fb.png)

App name：okta-sso-saml（※任意で大丈夫）

![o_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/abe26a24-726a-6ec5-fd35-a8257e10e9e7.png)

Okta側からCognitoにアクセスするための設定をして行く。

### Single sign-on URL

CognitoがOktaからの認証レスポンスを受け取るためのURL。Cognitoがユーザープール毎に用意してくれている。下記URLの書式で指定する。

**自分のCognitoドメイン/saml2/idpresponse**

```
// 例
https://okta-sso-20230301.auth.ap-northeast-1.amazoncognito.com/saml2/idpresponse
```

Cognitoドメインはマネコンから確認。
![スクリーンショット 2023-03-04 11.14.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/e4ae4a8f-71b5-4d94-77bd-3f2934e79a9f.png)

### Audience URI(SP Entity ID)

**urn:amazon:cognito:sp:ユーザープール ID**

```
// 例
urn:amazon:cognito:sp:ap-northeast-1_123ABC456
```

![o_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/ff237f86-ba34-c7f4-8dc4-a9503f91b072.png)

### Attribute Statements
ログイン時に取得したいOktaユーザーの属性を指定をする。
|Name|Value  |
|---|---|
|firstname  |user.firstName  |
|lastname  |user.lastName  |
|displayname  |user.displayName  |
|nickname  |user.nickName  |
|email  |user.email  |


emailのみ必須で、残りは取得したい属性を指定。Valueはuser.firstNameのようにフォーマットに従う必要があるが、Nameは任意に指定してOK。このNameでOktaユーザーのこの属性を取得したいという紐付けをしている。

この後、CognitoでこのName（firstnameとかlastnameとか）を使いCognito側でOktaユーザーの属性を取得出来るように設定する。

![o_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/ba8f9d0e-82cd-9fdc-4b28-8c6e8d4f59b8.png)
Attribute Statementsの設定が出来たら「Next」をクリック。
![o_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/79840799-06dc-0d83-4322-7fd0ee7010a6.png)
「I'm a software vendor.I'd like to integrate my app with Okta」にチェックを入れて「Finish」する。
![o_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/e44e150d-b688-94a0-38b1-9aa00f1db95c.png)

### アプリを使うユーザーをアサインする

Oktaユーザーのうち誰がこの認証のシステムを使うかを決める。

「Assignments」タブ>「Assign」>Assign to People

![スクリーンショット 2023-03-04 8.47.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/1e44a5d3-d3da-3f07-5ad5-0d596e847dff.png)

ダイアログが現れるので、ユーザーを「Assign」する。

![okta_profile.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/959cb726-7801-13e0-834d-5fce7d49663d.jpeg)


### metadataを取得する

Cognitoに渡す**自分の取り扱い説明書**を取得してCognitoにアップロードします。

「Sign On」タブの下部の「SAML Signing Certificates」の項目までスクロール。
テーブル中でStatusがActiveのものの「Actions」>「View Idp Metadata」をクリック。

![o_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/a7bd163e-e461-84d4-ee5f-0039d06607d2.png)

下記のようなXMLが表示されるので、ローカルPCに保存する。

![o_9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/b76fcd3d-76ac-7e3f-1c14-46e91e9e30f2.jpeg)

# Cognito設定②
## CognitoでOktaを登録
Cognitoのマネコン画面に戻り「サインインエクスペリエンス」>「アイデンティティプロバイダーを追加」する。
![c2_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/109e25e9-5480-6634-73de-515124de5ab6.png)

- SAMLを選択

![c2_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/78f60b88-b1c6-2bdb-da6a-eceaf58b4f88.png)

- プロバイダー名：okta-saml（任意）
- 識別子：okta-saml（任意。プロバイダー名と別でも問題ない）


![c2_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/82c5c5a6-92f5-e1f1-51e0-6f77421e60b6.png)

- メタデータドキュメントをアップロード：先ほど保存したXMLをアップロードする

![c2_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/a39b6e46-7ade-4e26-22bf-4aba2fc744fc.png)

- SAMLプロバイダーとユーザープールの間で属性をマッピング
    - email：email
    - given_name：firstname
    - family_name：lastname
    - nickname：nickname
    - name：displayname
  
![c2_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/9ad09cb5-fad8-3663-cb5a-5583bc3e0545.png)

「アイデンティティプロバイダーを追加」をクリックする。
## ログイン画面にOktaでのログインボタンを表示する
「アプリケーションの統合」タブを開く。
![スクリーンショット 2023-03-04 11.14.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/bacbeddf-9b63-fe2f-9f13-73dc8351ef70.png)
下部までスクロール、アプリケーションクライアントをクリックする。
![c2_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/77a2142a-8ec0-6cbd-390c-6ab5bd776c04.png)
ページ遷移後「ホストされたUI」までスクロールして「編集」する。
![c2_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/80593d4f-bcae-b6ee-5e4a-1be4e0ecb663.png)

- IDプロバイダー：okta-samlにチェック（※）

※アイデンティティプロバイダーを追加時に設定したプロバイダー名
![c2_8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/cfab82a5-f0b7-a327-8afb-6aef19478488.jpeg)
「変更を保存」する。

# ログインしてみる
「ホストされたUI」の項目の「ホストされたUIを表示」をクリックする。
![スクリーンショット 2023-03-08 18.50.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/52c2f53d-f71f-c9b6-6301-3d632682c7f3.png)
Cognitoが用意してくれたログイン画面が表示される。
左側にOktaでログインするボタンが現れている事を確認してクリックする。
![スクリーンショット 2023-03-08 17.01.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/dbf8edb3-2a77-0b21-4e06-5d21b45f981b.png)
Oktaのログイン画面に飛ぶのでOktaのユーザー＆パスワードでログインする。
![okta_login.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/636afc29-1247-158a-218e-e47ae3d280c2.jpeg)
ログインが成功すると「許可されているコールバックURL」で設定したURLにリダイレクトされる。
リダイレクトする際に、アクセストークンが付与される。
jwt.ioのサイトでは、渡って来たアクセストークン（jwt）をパースして表示してくれる。
![jwt.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349281/20e22885-fc37-9ed5-15f5-42037701d53e.jpeg)
このリダイレクト時にアクセストークンを渡す挙動は「OAuth2.0許可タイプ」の項目で”暗黙的な付与”を行なったことで行われる。一般的に、これはよろしくないらしいので、ここまで確認して、実際にアプリケーションにこのログインの仕組みを実装する段階になったら、設定の変更を考えるのが良さそう。

# Reactで使ってみる

次のステップとして、実際にフロント（React）でどう使ったらいいのか？

冒頭でも紹介しましたが、別記事に書いてみたので、良かったら見てみて下さいー。

https://qiita.com/gossan/items/c2352c6696c9527f1327

# おわりに

初めてSSOに取り組んでいます。

動画を見ながら（挙げて下さってる方、本当にありがたい）実装は出来たものの、CognitoとOktaとの行ったり来たりしながら設定が必要だったので、初学者の私にとっては複雑で、何をさせられているのか分からないまま手を動かしてた状態になってしまってました。

記事にしてみることでだいぶ頭の中を整理出来た気がします。