Cognito 組み込みWebページ＋S3だけで動的サイトを作る

#Cognito 組み込みWebページとは
ログイン機能のSaasって感じ。つまりWebサイトのログイン部分のコーディングは不要。
・認証に必要なUI（表裏）は用意してくれる
・利用者は、不特定多数のユーザを想定している感じ。
・認証後のトークンを使えば、ログインユーザがAWS認証して各種APIを使える

とりあえず、ここではCognitoで認証して、S3公開サイト側で認証結果を表示するところまで作る
所用時間10分程度

#やること
Cognitoで作れる認証サイトでログインを行った後、S3の公開サイト内の自作マイページに行き
自作マイページ内で、AWS認証を実施する。
#作る
##Cognitoの設定
###ユーザプールの作成
（▶で展開できます）

------------------------------
<details><summary>  1. ユーザプールを作ります
</summary><div>
Cognitoの **ユーザプール** を新規作成する。
適当なプール名を入力して『デフォルトを確認する』を押す
<img border="1" src="https://qiita-image-store.s3.amazonaws.com/0/185989/7a99e72e-2927-4606-1b42-b3294ea47bce.png" width=70% />
属性は一度作成したら修正できないので修正する
**必須の属性** パネルの右上えんぴつアイコンで、**属性**ページが表示される
![ユーザプール属性の変更１](https://qiita-image-store.s3.amazonaws.com/0/185989/0dda5027-6f10-5477-f647-de961bb69438.png)
**E メールアドレスおよび電話番号**を選択し、**E メールアドレスを許可**を選択する
<img border="1" src="https://qiita-image-store.s3.amazonaws.com/0/185989/27cb78d4-6584-948b-61d5-125f74d0d908.png" width=70% />
最後のページまで進んで、**プールの作成** ボタンを押す
</div></details>
『ユーザプールID』が発行されます。こんな感じ⇨*ap-northeast-1_TT9tttTtT*。あとで使います。

--------------------------------

<details><summary>  ２.アプリケーションクライアントを作る
</summary><div>
**全体設定→アプリクライアント** を選択して、**アプリクライアントの追加**をクリック
<img border="1" src="https://qiita-image-store.s3.amazonaws.com/0/185989/c5a826f0-48ac-1546-adc6-eb0393996f61.png" width=70% />
適当な名前を付けます
**クライアントシークレットを生成** →チェックはOFFにしておく**※ここ重要※**
**アプリクライアントの作成**ボタンをクリックして終わる
<img border="1" src="https://qiita-image-store.s3.amazonaws.com/0/185989/e9df3b58-c653-5ae3-4ad0-2610f1946e30.png" width=70%  />
</div></details>
『アプリクライアントID』が発行されます。こんな感じ⇨*44hikineet8hoge0et6pgcmrgp*。あとで使います。

---------------------------------

<details><summary>  ３.アプリの統合：ログインページを作る的な感じ
</summary><div>
![アプリクライアントの統合１](https://qiita-image-store.s3.amazonaws.com/0/185989/bafdb6e1-85a7-bfaf-fc8a-6d0293973bbe.png)
左側ペインで、 **アプリの統合→アプリクライアントの設定** を選択して、
・有効なIDプロバイダ として、Cognito User Pool にチェックする
・コールバックURLとして、https://www.amazon.com としておく(あとで直します)
・許可されている OAuth フロー/許可されている OAuth スコープに下図のようにチェック入れる（よくわからない。。ﾊﾅﾎｼﾞ
![アプリクライアントの統合２](https://qiita-image-store.s3.amazonaws.com/0/185989/e5cbbbad-9e1a-79f2-7825-5d799804858e.png)


左側ペインで、**アプリの統合→ドメイン名**を選択して、
適当なサブドメインを入力して、**使用可能かチェック**ボタンを押して、**変更の保存**ボタン
![ドメインの選択](https://qiita-image-store.s3.amazonaws.com/0/185989/e5bff3ad-45e2-3112-1c7b-22b0618bf279.png)
</div></details>
『コールバックURL』を設定しました。
『Cognitoドメイン』が作成されます。こんな感じ⇨*ttps://gatineet4hikineet.auth.ap-northeast-1.amazoncognito.com*。あとで使います。

-----------------------------------
###とりあえず動くかどうかのテスト
[公式サイトのこのあたり](https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/login-endpoint.html)に書かれています

『Cognitoドメイン』/login?response_type=token&client_id=『アプリクライアントID』&redirect_uri=『コールバックURL』
⬇︎こんな感じ
https\://gatineet4hikineet.auth.ap-northeast-1.amazoncognito.com/login?response_type=token&client_id= 44hikineet8hoge0et6pgcmrgp&redirect_uri=<span>https:</span>//<span>www</span>.amazon.com/
![ログインページ](https://qiita-image-store.s3.amazonaws.com/0/185989/62d3ef0e-6c79-8305-5d69-27e049695a1c.png)
おーできました。
作りたてなので、早速ユーザを登録する必要があります。
SignUpリンクをクリックすれば、登録ページが出て来て、検証メールが来て、登録される感じです。
このあたりはやって見りゃわかります。
ユーザプール管理画面の”ユーザとグループ”あたりを見てると、ユーザの状態が変わるので、合わせてご確認を。
ログインが成功すると、指定通り<span>https:</span>//<span>www</span>.amazon.comに遷移します。
ロゴとか設定できるので、いじってみるとテンション上がります

はい。次は遷移先に自作マイページを設置して、飛んでくるパラメータを使います。

##自作マイページの準備
…の前に、IDプールするもの（）を作ります。
説明は後でします（いつかします。たぶんします。質問禁止です。自分で調べろください）
<details><summary>  4.フェデレーテッドアイデンティティの作成
</summary><div>
IDプール名は適当なものを
![IDプールID１](https://qiita-image-store.s3.amazonaws.com/0/185989/2c97a363-7195-ebdf-b2e2-bfdf3ddadfd4.png)
認証プロバイダは、Cognitoタブを選択して、『ユーザプールID』と『アプリクライアントID』を設定します
![IDプールID２](https://qiita-image-store.s3.amazonaws.com/0/185989/c4857d59-88a0-581a-146f-717d25950561.png)
**プールの作成** ボタンを押します
・・・と、何やらロールが云々と出て来ます。
ログインが成功した場合と、そうでない場合のIAMロール設定の様子。
![IDプールIDのIAM](https://qiita-image-store.s3.amazonaws.com/0/185989/455b0bc3-e537-33ba-924f-41b1462fa625.png)
とりあえずそのまま進めます。**許可**ボタンを押すます。
この時点でIAMロールが新規作成されていますので、やり直ししたいときは、このロールも削除した方が良いです。

</div></details>
『IDプールのID』が作成されます。こんな感じ⇨*ap-northeast-1:0f4cdc1f-999x-xxx9-9999-999xx0xx4x08*。あとで使います。

------------------------------
<details><summary>  5.自作マイページの作成
</summary><div>
S3のサイト公開設定して、自作マイページ用htmlファイル（認証用JavaScript入り）を準備するます
事前にCognito用 JavaScriptファイルを取得する必要があるます
https://github.com/amazon-archives/amazon-cognito-identity-js/tree/master/dist
このあたりにある
aws-cognito-sdk.min.js
amazon-cognito-identity.min.js
の２ファイルです

下記ソースの変更箇所は、『ユーザプールID』と『IDプールID』の２点のみです

```html:hogemypage.html
<html>
<head>
    <meta charset='utf-8'>
    <title>hogeAuth サンプル</title>
    <script src='https://code.jquery.com/jquery-2.1.4.min.js'></script>
    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.259.1.min.js"></script>

    <!-- https://github.com/amazon-archives/amazon-cognito-identity-js/tree/master/dist　このあたりからもってくる -->
    <script src="./aws-cognito-sdk.min.js"></script>
    <script src="./amazon-cognito-identity.min.js"></script>

    <script type='text/javascript'>
        //セッション取得系で必要なパラメータ
        const UserPoolId = '『ユーザプールID』';
        const IdPoolId = '『IDプールID』';
　　　　　const params = new URLSearchParams(location.hash.slice(1));
        
        //URL中のパラメータからトークンを取り出し、AWS.config.credentials を設定する
        checkSession = function () {
            var widToken = params.get('id_token');
            $('#message').text(widToken);

            AWS.config.region = 'ap-northeast-1';
            AWS.config.credentials = new AWS.CognitoIdentityCredentials({
                IdentityPoolId: IdPoolId,
                Logins: {
                    ['cognito-idp.ap-northeast-1.amazonaws.com/' + UserPoolId] : widToken
                }
            });

            AWS.config.credentials.refresh(function(err) {
                if (err) {
                    $('#message').text('エラー：' + err + '\n\n' + widToken);
                } else {
                    $('#message').text('正常！：アイデンティティ IDはこれです → ' + AWS.config.credentials.identityId);
                }
            });
        }
    </script>
</head>

<body>
    <h5>マイページ</h5>
    <div id="message" ></div>
    <button onclick="checkSession()">再チェック</button>
    <!-- 起動時にcheckSession関数を呼び出す -->
    <script type='text/javascript'>$(window).ready(checkSession);</script> 
</body>
</html>
```

※JavaScriptは本業ではないので、適当に書いています。
ようするにやりたいことは、Cognito認証が成功すると、QueryStringの「id_token」にトークンらしき文字列がやってくる
AWS.config.credentialsに↓の形で渡せば、AWS各種サービスが使える状態になる（ただしIAMロールで絞っている）

```AWS.config.credentials
{
   IdentityPoolId: 『IDプールID』,
   Logins: {
     cognito-idp.ap-northeast-1.amazonaws.com/『ユーザプールID』 : Cognitoログインページで発行されたトークン
   }
}
```
</div></details>
作成したファイルを「公開設定されているS3バケット」に置き、フルパスを取得します
（別にS3じゃなくても、httpsで見えるサイトであればOKですが[^1]）



------------------------------
<details><summary>  6.ユーザプールの遷移先を修正します
</summary><div>
ユーザプールの、**アプリの統合→アプリクライアントの設定** を選択して、
『コールバック URL』に、上記自作マイページを置いたパスを設定してください。
httpsでないとダメみたいです[^1]
[^1]: localhostの場合、httpsじゃなくてもよいみたい

</div></details>



------------------------------
###で、動くかどうかのテスト
さっきのログインのためのURLでログインページを表示します。
・認証していない→ログインページが出てくる
・すでに認証済み→「認証済みだけど進める？ページが出てくる」
で、進めると
自作ページが出てきて、AWS.config.credentials.identityIdが出てくる
このIDは、フェデレーション（略）の管理ページにも出てます

明示的なログアウトは
[公式サイトのこのあたり](https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/logout-endpoint.html)に書かれています


#まとめ
##登場人物
| ID | 設定箇所 | メモ |
|---|---|---|
|ユーザプールID  |ユーザープール全体のID   | |
|アプリクライアントID  |ユーザープール→アプリクライアントのID  | |
|Cognitoドメイン  |アプリの統合→ドメイン名  |【ほげほげ】.auth.ap-northeast-1.amazoncognito.com |
|コールバックURL  |アプリの統合→アプリクライアントの設定  |自作マイページ（https必須）[^1] |
|IDプールID  |フェデレーティッドアイデンティティで作成  |ユーザプールIDとアプリクライアントIDを設定 |

##まとめ
とりあえずの足掛かりとして作ってみた。
こいつをいじっていけば、選択肢はかなり増えそう。
ちなみに、IDを公開しちゃって大丈夫なのか？という議論が[このあたり](https://github.com/amazon-archives/amazon-cognito-identity-js/issues/312)でされています。
まぁ大丈夫そうですが。。
とりあえず、かなりいろんな事ができそうですな。
ノシ