とりあえずAWS Cognito触ってみた

#§１．はじめに

##１．何のページ？
AWSの中で2021年2月7日時点で常に無料（？）なサービスである
Amazon Cognitoをとりあえず触ってみたときの備忘録的なものです。

無料枠の確認は[AWS　クラウド無料利用枠](https://aws.amazon.com/jp/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc)で行えます。

Cognitoは何？って人は検索してもらうか[Cognitoの紹介ページ](https://aws.amazon.com/jp/cognito/)をご覧ください。

AWS S3だけはアカウントを作って最初の１年は無料なのですがそれ以降は
お金がかかります（２０２１年３月７日現在では一月に１GBあたり0.025ドル）


##２．誰向け？
備忘録的なものなので自分向けですが、
AWSに興味があってとりあえず登録してみたけど何していいかわからない～って
人の参考になればいいかなと思ってます。
専門的な用語などはできるだけ解説したり実際の操作画面を貼り付けたりして、
できるだけわかりやすく解説していきたいと思います。

##３．免責事項
当ページを参考にして操作を実施した結果いかなる損害が発生しても同様に一切責任を負いません。
ご自身の判断で操作をお願いします。


#§２．前提

##１．作りたいシステムの構成


　![Cognito Otameshi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996038/fc50a917-280e-3311-7b8a-287db7154f4f.png)


今回はCognitoを触るのが目的なので上記のような単純な構成でいきます。
Amazon S3はファイルを保存しておくサービスなのですが、ウェブサイトを公開する機能があります。
今回はそのS3の機能を利用してログイン機能があるウェブサイトを作っていきます。



#§３．手順

##１．Cognitoの設定

###（１）ユーザプールを作る

AWS Cognitoを利用するためにはユーザプールかIDプールを作る必要があります。
ユーザプールとIDプールの違いについては[公式のQA](https://aws.amazon.com/jp/premiumsupport/knowledge-center/cognito-user-pools-identity-pools/)をご覧ください。
簡単に説明するとユーザプールは認証（アクセスした人が”誰”なのか判断する）ができて、
IDプールは認可（アクセスしてきた人にどんな操作を許可するかを判断する）ができます。

今回はログインの仕組みを作りたいのでユーザプールを利用します。

まずは[マネジメントコンソール](https://aws.amazon.com/jp/console/)を開きます。
ここで右上のリージョンが東京になっていることを確認しておいてください。

マネジメントコンソールの上部中央の検索欄に「Cognito」と入れてCognitoを開きます。
そうすると以下のようなページが出てきますのでユーザプールの管理を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996038/57e66069-b765-dfa4-73bd-985bbb7c7b13.png)



そこから「ユーザープールを作成するには、ここをクリックします。」をクリックします。
クリックすると以下のような画面が出てきますので好きなプール名を入力して「デフォルトを確認する」を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996038/f074137d-4fcc-ff56-19cc-162d9ede04d4.png)




今回はお試しということでこのまま「プールの作成」を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996038/19703d2a-e2dd-ad45-df74-7191fe5458d5.png)


ちょっと待ってるとプールができます。



###（２）ユーザプールの設定を行う

そのままでは使えないので色々設定をしていきましょう。
プールの作成を押すと下記のような画面になると思います。
まずはアプリクライアントの追加をしましょう。
アプリクライアントは平たく言うとこのユーザプールでユーザを照会するための窓口と思ってください。
左のメニューから「アプリクライアント」を押して「アプリクライアントの追加」を押します。
好きなアプリクライアント名を入れてページ下部のアプリクライアントの作成を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996038/8b71ddfd-f4d0-2926-6323-994fde73b895.png)


###（３）ユーザを追加する

テスト用にユーザを一人作って見ましょう。
Aws Cognitoのユーザプールの画面の左側に「ユーザとグループ」という項目がありますのでそれを押します。
すると以下のような画面が出ますので、「ユーザの作成」を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996038/de2b85f7-8848-e989-8f75-97d28fd5f40a.png)

ユーザの作成を押すと以下のような小窓が出てきます。
「この新規ユーザに招待を送信しますか？」にチェックを外して後は好きな文字列を入れます。
入力したらユーザの作成を押しましょう。
これでユーザが作成できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996038/9ea3793f-45a8-b999-bf3e-cbabd2768f8f.png)


###（４）ユーザを有効にする

作成したユーザの「アカウントのステータス」を見ると「FORCE_CHANGE_PASSWORD」と記載されていると思います。
これは「登録はしたけど（パスワードを変えていないので）まだサインインできませんよ」という状態です。
ですのでパスワードを変えましょう。
パスワードを変えるにはいろいろな方法があるのですが今回はAWS CLIを利用しましょう。
AWS CLIはバッチでAWSのいろいろなサービスを利用できるプログラムです。
以下のサイトからダウンロードして導入してください。

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-windows.html


ダウンロードできたら自分のPCのどこでもいいのでバッチファイルを新規作成して、
以下の内容を書き込みます。

```batch
aws cognito-idp admin-initiate-auth ^
  --user-pool-id <自分のユーザプールのID> ^
  --client-id <ユーザプールに紐づくアプリClientのID> ^
  --auth-flow ADMIN_USER_PASSWORD_AUTH ^
  --auth-parameters USERNAME=<ユーザ名>,PASSWORD=<仮パスワード>^
  --output json
pause
```

書き込んで実行して以下のような画面が出れば成功です。
この画面の「"Session:" 」から始まるながーい文字列（下記の画像だと「AYA....Z6t4Q」）
をコピーして一旦どこかのメモ帳などにはりつけておいください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996038/f8df9c3a-761b-aa29-ddd9-fb388cf539b2.png)


さっきと同じ要領で以下のようなバッチを作って実行します。
実行してめちゃくちゃ長い英数字の羅列が出てきたら成功です。

```batch
:NewPassWord
aws cognito-idp admin-respond-to-auth-challenge ^
  --user-pool-id        <自分のユーザプールのID> ^
  --client-id           <ユーザプールに紐づくアプリClientのID> ^
  --challenge-name      NEW_PASSWORD_REQUIRED ^
  --challenge-responses NEW_PASSWORD=<新しいパスワード>,USERNAME=<ユーザ名> ^
  --output              text^
  --session <さっきコピーした長い文字列>
pause
```

念の為Cognitoの「ユーザとグループ」のページを見て起きましょう。
ステータスが「CONFIRMED」となっていれば成功です。

これでCognitoの設定は完了です。
次は今まで設定したユーザプールやユーザを使ってウェブサイトからログインをしてみましょう。




##２．S3の設定

###（１）ウェブサイトのホスティング

AWS S3でバケットを作ってそれをウェブサイトとしてホスティングします。
手順は以下のページが非常にわかりやすかったです。

[【AWS S3】静的WEBサイトホスティング](https://qiita.com/OPySPGcLYpJE0Tc/items/d5be466d7dcb156649ae)

一応自分もウェブサイトの作り方を記事にしてるのでよろしければ。
[AWSで簡単なウェブサイトを作ろう](
https://qiita.com/ryucian1117/private/c275f153bdfa14288a85#%E3%82%A6%E3%82%A7%E3%83%96%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%AE%E4%BD%9C%E6%88%90amazon-s3)



###（２）SDKの入手

ウェブページからユーザIDとパスワードをCognitoに送り、
ユーザが居るかどうか？居るならどんなユーザかをCognitoから送って貰う必要があります。

そのためにはJavascriptで色々書かないといけなくて大変です。
なので他の人が書いてくれたJavaScriptを利用しましょう。

以下のサイトからまずは自分のパソコンに以下のJSファイルを落としてください。

https://github.com/amazon-archives/amazon-cognito-identity-js/tree/master/dist

・amazon-cognito-identity.min.js
・aws-cognito-sdk.min.js


jsファイルを落としたらフォルダを作って２つのJSを格納します。
さらに作ったフォルダにhtmlファイルを作成して以下のコードをコピーしてください。
（htmlのファイル名は何でもよいです）

```html:cognitoTest.html

<html> 
<head> 

	<meta charset="UTF-8" />

	<!--とりあえずAWSのSDKを読み込んでおくt-->
	<script src="https://sdk.amazonaws.com/js/aws-sdk-2.23.0.min.js"></script>
		
	<!--先程アップロードしたJavaScriptファイルを読み込む Start-->
	<script type="text/javascript" src="aws-cognito-sdk.js"></script>
	<script type="text/javascript" src="amazon-cognito-identity.js"></script>

	<!--読み込んだJavaScriptを利用してAPIを叩く-->
	<script type="text/javascript">
		function setMsg(msg)
		{
			document.getElementById('msg').innerHTML = msg;
		}
		function Login()
		{
			//可読性を上げるために設定情報を上にまとめておく
			let myUserPoolId = "ap-northeast-1_XXXXXXXX";	//作成したユーザプールのID
			let myClientId   = "XXXXXXXXXXXXXXXXXXXXXXX";	//作成したユーザプールのClientID
		
			//どのユーザプールを利用するかを設定する
			AWSCognito.config.region = "ap-northeast-1";
			
			var poolData = {
				UserPoolId: myUserPoolId,
				ClientId: myClientId,
			};
			
			//設定した情報をもとにユーザプールへ接続する
			var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
		
			//認証情報（ユーザIDとパスワード）を設定する
			var authenticationData = {
				Username : document.getElementById("userID").value,
				Password : document.getElementById("password").value
			};
			
			//ユーザIDとパスワードを元にサインイン用の認証詳細オブジェクトを作成する
			var authenticationDetails 
				= new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);

			//ユーザ名とユーザプールでユーザデータを作成
			var userData = {
				Username : document.getElementById("userID").value,
				Pool : userPool
			};

			//ユーザオブジェクトを取得？
			cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
			console.log(cognitoUser);
			
			//ユーザオブジェクトの認証関数を実行
			cognitoUser.authenticateUser(authenticationDetails, {
				onSuccess: function (result) {
					console.log("Id      Token + " + result.getIdToken().getJwtToken());
					console.log("Access  Token + " + result.getAccessToken().getJwtToken());
					console.log("Refresh Token + " + result.refreshToken.token);
					setMsg("ログイン成功");
				},
				onFailure: function(err) {
					setMsg(err);
				},
			});
			
			return false;
		}
	</script>
	
</head>
<body>
	<input type="text" placeholder="ID" id="userID"  value="お試し１"/>
	<input type="password" placeholder="PassWord" id="password" value="Ot@meshi1" />
	<button type="button" onClick="Login()">ログイン</button>
	<p id="msg">ログインしてください</p>
</body>
</html>

```




コピペしたソースの以下の部分の左辺をそれぞれ書き換えます。

``` javascript
            let myUserPoolId = "ap-northeast-1_XXXXXXXX";   //作成したユーザプールのID
            let myClientId   = "XXXXXXXXXXXXXXXXXXXXXXX";   //作成したユーザプールのClientID
```


また必須ではありませんが以下のタグのvalueの左辺を書き換えて置くと入力の手間が省けます。

``` html
	<input type="text" placeholder="ID" id="userID"  value="お試し１"/>
	<input type="password" placeholder="PassWord" id="password" value="Ot@meshi1" />
```

書き換えたら保存してそのHTMLファイルをブラウザで開きます。
自分が登録したユーザIDとパスワードを入力してログインを押したときに、
「ログイン成功」と表示されればログイン成功です。
ログインが成功したら今度は登録していないユーザIDとパスワードを入れてログインを押します。
するとエラーメッセージが表示されますので正しく認証をしていることがわかると思います。

後はこのHTMLファイルとJSファイルをS3にアップすれば完成です。
今回はあくまでもCognitoを触ってみたかっただけなのでアップロードの手順は割愛します。
（というか誰かに見せるわけでないならS3に上げる必要はないです）



以上です
お疲れさまでした。



#今後の課題とか
ウェブ上から以下のようなことができるようしたい
　・ユーザパスワードの変更
　・ユーザの登録（Gmailとか顔本のアカウントを使うやつ）
　・ユーザの削除
　・ユーザの有効化（上でAWS CLIでやったやつ）