ASi

Cognito を Javascript から使う実験

https://dev.classmethod.jp/cloud/aws/login-form-by-using-aws-sdk-for-javascript/ はとても参考になったが、記事が使っているAWSJavascript向けSDKが古かった。そこで公式の https://github.com/aws/aws-amplify/blob/master/packages/amazon-cognito-identity-js/README.md を参照しつつ v1.32.0 時点の仕様で動くようにして試してみた。


amazon-cognito-identity.min.js は 2018/3/9 現在最新の下記リビジョン。
https://github.com/aws/aws-amplify/blob/62f7f2e365a1b4b99e9ebdf55e30199121afa19b/packages/amazon-cognito-identity-js/dist/amazon-cognito-identity.min.js


なお csshttps://codepen.io/Lewitje/pen/BNNJjo のものを使わせてもらったが、無くても Cognito の確認には支障ない。

js/common.js

下記のID類を Cognito の管理画面か Admin API で作成して揃えておく。

var AWS_REGION = 'ap-northeast-1';
var COGNITO_IDENTITY_POOL_ID = 'ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
var COGNITO_USER_POOL_ID = 'ap-northeast-1_XXXXXXXXX';
var COGNITO_CLIENT_ID = 'xxxxxxxxxxxxxxxxxxxxxxxxxx';
var COGNITO_IDP = 
    'cognito-idp.' + AWS_REGION + '.amazonaws.com/' + COGNITO_USER_POOL_ID;

login.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Login</title>
        <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    <div class="wrapper">
      <div class="container">
        <h1 class="msg">Welcome</h1>
 
        <form class="form">
            <input type="text" placeholder="Username" id="name">
            <input type="password" placeholder="Password" id="password">
            <button type="submit" id="login-button">Login</button>
        </form>
 
      </div>
    </div>

    <script src="js/amazon-cognito-identity.min.js"></script>
    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.5.2.min.js"></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
 
    <script src="js/common.js"></script>
    <script src="js/login.js"></script>
 
  </body>
</html>

js/login.js

newPasswordRequired に管理コンソール上でアカウント作成した場合の強制パスワード変更の実装を簡易にしてある。

// js client では ClientID に client secret が生成されていると動作しない

AWS.config.region = AWS_REGION;
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: COGNITO_IDENTITY_POOL_ID,
});

var CognitoUserPool = AmazonCognitoIdentity.CognitoUserPool;

var poolData = { UserPoolId: COGNITO_USER_POOL_ID,
                 ClientId: COGNITO_CLIENT_ID,
                 Paranoia : 7
};
 
var userPool;
var cognitoUser;

$("#login-button").click(function(event){ 
    event.preventDefault();
	
    var authenticationData = {
        Username : $('#name').val(),
        Password : $('#password').val()
    };
	
    var authenticationDetails = new 
	    AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
    var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
	var userData = {
        Username : $('#name').val(),
        Pool : userPool
       };
	   
    cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
    cognitoUser.authenticateUser(authenticationDetails, {
		onSuccess: function (authresult) {
             var url = "mypage.html";
             $('form').fadeOut(700, function(){
                $(location).attr("href", url);
             });
             $('.wrapper').addClass('form-success'); 
        },
        onFailure: function(err) {
            console.log('onFailure');
            alert('msg='+ err.message);
        },
        mfaRequired: function(codeDeliveryDetails) {
            // MFA is required to complete user authentication.
            // Get the code from user and call
            cognitoUser.sendMFACode(mfaCode, this)
        },
        newPasswordRequired: function(userAttributes, requiredAttributes) {            
            // User was signed up by an admin and must provide new
            // password and required attributes, if any, to complete
            // authentication.

            console.log('newPasswordRequired');
            console.log(userAttributes, requiredAttributes);

            // the api doesn't accept this field back
            delete userAttributes.email_verified;

            // これらの必要性はUserPoolの設定による
            userAttributes.address='a';
            userAttributes.given_name='b'; 
            userAttributes.family_name='c';
            userAttributes.middle_name='d';
            // phone number はこの形式の必要がある
            userAttributes.phone_number='+818012345678';

            console.log(userAttributes);

            // Get these details and call
            cognitoUser.completeNewPasswordChallenge('0101abab', userAttributes, this);
        }
    });
});

mypage.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>mypage</title>
        <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    <div class="wrapper">
      <div class="container">
        <div class="mypage">
          <h1>mypage</h1>
          <div id="username">Username: XXXXX</div>
          <div id="email">EMail: XXXXX</div>
        </div>
      </div>
    </div>

    <script src="js/amazon-cognito-identity.min.js"></script>
    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.5.2.min.js"></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
    
    <script src="js/common.js"></script>
    <script src="js/mypage.js"></script>
 
  </body>
</html>

js/mypage.js

// js client では ClientID に client secret が生成されていると動作しない

AWS.config.region = AWS_REGION;
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: COGNITO_IDENTITY_POOL_ID,
});

var CognitoUserPool = AmazonCognitoIdentity.CognitoUserPool;

var poolData = { UserPoolId: COGNITO_USER_POOL_ID,
                 ClientId: COGNITO_CLIENT_ID,
                 Paranoia : 7
};

var userPool;
var cognitoUser;
	
var authenticationData = {
    Username : $('#name').val(),
    Password : $('#password').val()
};

var authenticationDetails = new 
    AmazonCognitoIdentity.AuthenticationDetails(authenticationData);

var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var userData = {
    Username : $('#name').val(),
    Pool : userPool
};

// これがポイント
cognitoUser = userPool.getCurrentUser();
	
if (cognitoUser != null) {
    cognitoUser.getSession(function(err, sessresult) {
        if (sessresult) {
            console.log('You are now logged in.');
            cognitoUser.getUserAttributes(function(err, attrresult) {
                if (err) {
                    alert(err);
                    return;
                }
                $("#username").html("Username: " + cognitoUser.username);
 
                for (i = 0; i < attrresult.length; i++) {
                    if (attrresult[i].getName()=="email"){
                      $("#email").html("EMail: " + attrresult[i].getValue());
                    }
                }
 
                // Add the User's Id Token to the Cognito credentials login map.
                AWS.config.credentials = new AWS.CognitoIdentityCredentials({
                    IdentityPoolId: COGNITO_IDENTITY_POOL_ID,
                    Logins: {
                        COGNITO_IDP: sessresult.getIdToken().getJwtToken()
                    }
                });
            });
        } else {
           var url = "login.html";
           $(location).attr("href", url);
        }
    });
} else {
  var url = "login.html";
  $(location).attr("href", url);
}