Amazon Cognito User Poolsを使って、webサイトにユーザ認証基盤を作る

# 概要
AWS Summit 2016 Chicago にてAmazon Cognitoの新機能として発表された「User Pools」を使ってwebサイトにユーザ認証基盤を作ります。User Poolsはサインインやサインアップ、セッション管理など、よくあるユーザ管理機能をマネージドで提供してくれるサービスです。

[[New] Amazon Cognito 向け User Pools](https://aws.amazon.com/jp/blogs/news/new-user-pools-for-amazon-cognito/)


# User Poolsの作成
[[新機能] Amazon Cognito に待望のユーザー認証基盤「User Pools」が追加されました！](http://dev.classmethod.jp/cloud/aws/cognito-user-pool/)
作成方法についてはClassmethodさんのブログに詳しく乗ってますので参考にしてください。

JavaScriptからUser Poolsの認証機能を使う時の注意点として、以下のAppsの作成で`Generate client secret`のチェックを外してください。JavaScriptからはclient secretが使用できないためです。
<img width="906" alt="スクリーンショット 2016-04-23 16.34.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/6c6944a1-3027-c9c0-5d03-607dc75008e8.png">

# identitypoolの作成
identitypoolを作ります。認証プロバイダーに先ほど作ったUser Poolを指定します。
Unauthenticated identitiesも有効化してください。
<img width="952" alt="スクリーンショット 2016-04-23 16.38.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/a34d1515-a736-210c-66b0-95a9943b2093.png">

Step2に進んでロールを付与します。特にAWSのリソースにアクセスする必要がなければ、下記のデフォルトのままのロールで問題無いです。
<img width="1260" alt="スクリーンショット 2016-04-23 16.44.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/a992a96f-f923-f31c-9037-017f9cd6dee0.png">

# JavaScriptで認証機構をサイトに埋め込む
[amazon-cognito-identity-js](https://github.com/aws/amazon-cognito-identity-js)を使ってwebサイトに認証基盤を埋め込んでいきます。

## サインアップ
以下の様なサインアップ用のフォームを作ります。
<img width="286" alt="スクリーンショット 2016-04-23 16.49.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/268a3e48-b006-a875-0afa-561f95f17a1e.png">

以下がJavaScriptのコードです。Sendボタンを押せばサインアップの処理が走ります。

```js
<script type="text/javascript">
jQuery(document).ready(function($){ 
  AWS.config.region = 'us-east-1'; // Region
  AWS.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: 'us-east-1:a3132b33-a05d-4a9f-9ddd-39d8c9dba547'
  });

        // Cognito User Pool Id
  AWSCognito.config.region = 'us-east-1';
  AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: 'us-east-1:a3132b33-a05d-4a9f-9ddd-39d8c9dba547'
  });

  $("#signup").on( "click", function(){
	    
	    
    var poolData = { 
    			UserPoolId : 'us-east-1_Ab129faBb',
                ClientId : '7lhlkkfbfb4q5kpp90urffao'
    		};

    var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);

    var attributeList = [];
    
    var dataEmail = {
        Name : 'email',
        Value : $('#email').val()
    };

    var attributeEmail = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataEmail);

    attributeList.push(attributeEmail);

    userPool.signUp($('#email').val(), $('#password').val(), attributeList, null, function(err, result){
        if (err) {
            console.log(err);
            return;
        }
        cognitoUser = result.user;
        console.log('user name is ' + cognitoUser.getUsername());
        console.log('call result: ' + result);
    });
  });
});

</script>
```

以下のようにUser Poolにユーザが登録されています。
<img width="938" alt="スクリーンショット 2016-04-23 16.59.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/47abfbfc-5314-b11f-b811-b84c3e4f5bbf.png">

アクティベーション用のコードを書いたメールも届いています。
<img width="304" alt="スクリーンショット 2016-04-23 16.59.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/7fb69d3b-4d91-8a55-95af-0e7a714523dd.png">

## ユーザのアクティベーション
以下の様なアクティベーション用のフォームを作ります。
<img width="292" alt="スクリーンショット 2016-04-23 17.08.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/46278445-a7f1-6b32-6a43-9640fccfb4ec.png">

以下がJavaScriptのコード。Sendボタン押せばアクティベーションを実行します。

```js
<script type="text/javascript">
jQuery(document).ready(function($){ 
  AWS.config.region = 'us-east-1'; // Region
  AWS.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: 'us-east-1:a3132b33-a05d-4a9f-9ddd-39d8c9dba547'
  });

  // Cognito User Pool Id
  AWSCognito.config.region = 'us-east-1';
  AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: 'us-east-1:a3132b33-a05d-4a9f-9ddd-39d8c9dba547'
  });


  $("#send").on( "click", function(){
 	var poolData = { 
    			UserPoolId : 'us-east-1_Ab129faBb',
                ClientId : '7lhlkkfbfb4q5kpp90urffao'
    		};
    var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);

    var userData = {
        Username : $('#email').val(),
        Pool : userPool
       };
    var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
        cognitoUser.confirmRegistration($('#key').val(), true, function(err, result) {
        if (err) {
            alert(err);
            return;
        }
        console.log('call result: ' + result);
    });
  });
});

</script>
```

StatusがComfirmedとなればアクティベーション完了です。
<img width="537" alt="スクリーンショット 2016-04-23 17.11.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/e3199b67-9e3a-5e14-6594-0d79b6a4c2db.png">

## ログイン
ログイン用のフォームを作ります
<img width="235" alt="スクリーンショット 2016-04-23 17.14.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/18643764-30fe-0fb6-8f13-693c8a6d1a1d.png">

コードは以下。
これでaccesstokenがCognitoから返却されるので、それを引き回すことでマイページなどが作れます。

```js
<script type="text/javascript">
jQuery(document).ready(function($){ 
	AWS.config.region = 'us-east-1'; // Region
    AWS.config.credentials = new AWS.CognitoIdentityCredentials({
        IdentityPoolId: 'us-east-1:a3132b33-a05d-4a9f-9ddd-39d8c9dba547'
    });

        // Cognito User Pool Id
    AWSCognito.config.region = 'us-east-1';
    AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
        IdentityPoolId: 'us-east-1:a3132b33-a05d-4a9f-9ddd-39d8c9dba547'
    });

  $("#login").on( "click", function(){
	var authenticationData = {
        Username : $('#email').val(),
        Password : $('#password').val()
    };
    var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
    var poolData = { 
    	UserPoolId : 'us-east-1_Ab129faBb',
        ClientId : '7lhlkkfbfb4q5kpp90urffao'
    };
    var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
    var userData = {
        Username : $('#email').val(),
        Pool : userPool
       };
    var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
    cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: function (result) {
            console.log('access token + ' + result.getAccessToken().getJwtToken());
        },

        onFailure: function(err) {
            alert(err);
        },

    });	
  });
});

</script>
```

# まとめ
ユーザの管理機能がサーバ側のコードを1行も書くこと無く実現できちゃうのはまじでスゴイです。
しかもセキュア。

[ログイン・ログアウト機能をサーバレスアーキテクチャで実装する](http://qiita.com/horike37/items/dc81442d5d1b8ea89325)
[会員登録機能をサーバレスアーキテクチャで実装する](http://qiita.com/horike37/items/6f2575d6a061216fe019)
↑
先週こんな記事を書いたんですが、もう無意味なものになっちゃいました。
それだけAWSのアップデートが早いってことですね！