Amazon Cognitoシリーズ3作目です。1作目、2作目はこちら。
前回までの記事で、サインイン機能が実装できました。今回は、その先(認証が通ったあと)にちょっと踏み込みたいと思います。
サインイン後、サインインしたユーザーの情報を取得することがあります。例えば、
- 画面上に「ようこそ!〇〇さん」を表示する
- サインインしたユーザーにひもづくデータをDBから取得する
などです。
2つのケースの違いをものすごくざっくり言うと、1はクライアント側でユーザー情報が必要で、2はサーバー側でユーザー情報が必要という点です。今回は1のケースにおいて、Amazon Cognitoで認証したユーザーの情報を、JavaScriptで取得したいと思います。
JavaScriptでユーザー情報を取得する
Webアプリでは、サーバー側の処理を呼び出してユーザー情報を取得し、取得結果を画面に表示する、という方法が一般的かと思います。しかし、Amazon Cognito(のJavaScriptライブラリ)では、ユーザーの認証後、そのユーザーの情報をローカルストレージに保持しているため、JavaScriptライブラリ経由で現在のユーザー情報を取得することができます。
メニュー画面の実装
まずは、サインイン後に遷移する画面を実装してみましょう。(とりあえず「メニュー画面」ということにしておきます)必要なJavaScriptライブラリは前回と同じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Menu</title> <script src="js/aws-cognito/jsbn.js"></script> <script src="js/aws-cognito/jsbn2.js"></script> <script src="js/aws-cognito/sjcl.js"></script> <script src="js/aws-cognito/aws-sdk.min.js"></script> <script src="js/aws-cognito/aws-cognito-sdk.min.js"></script> <script src="js/aws-cognito/amazon-cognito-identity.min.js"></script> <script src="js/jquery-3.3.1.min.js"></script> <script src="js/menu.js"></script> </head> <body> <div id="menu"> <h1></h1> </div> </body> </html> |
現状、bodyの中身は特になしです。空のh1タグだけ書いておきます。
ユーザー情報取得処理の実装
次に、JavaScriptでユーザー情報を取得する処理を実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
// ユーザープールの設定 const poolData = { UserPoolId : [ユーザープールID], ClientId : [アプリクライアントID] }; const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData); const cognitoUser = userPool.getCurrentUser(); // 現在のユーザー var currentUserData = {}; // ユーザーの属性情報 /** * 画面読み込み時の処理 */ $(document).ready(function() { // Amazon Cognito 認証情報プロバイダーの初期化 AWSCognito.config.region = 'ap-northeast-1'; // リージョン AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: [IDプールのID] }); // 現在のユーザーの属性情報を取得・表示 getUserAttribute(); }); /** * 現在のユーザーの属性情報を取得・表示する */ var getUserAttribute = function(){ // 現在のユーザー情報が取得できているか? if (cognitoUser != null) { cognitoUser.getSession(function(err, session) { if (err) { console.log(err); $(location).attr("href", "signin.html"); } else { // ユーザの属性を取得 cognitoUser.getUserAttributes(function(err, result) { if (err) { $(location).attr("href", "signin.html"); } // 取得した属性情報を連想配列に格納 for (i = 0; i < result.length; i++) { currentUserData[result[i].getName()] = result[i].getValue(); } $("div#menu h1").text("ようこそ!" + currentUserData["family_name"] + "さん"); }); } }); } else { $(location).attr("href", "signin.html"); } }; |
ユーザープールやプロバイダーの初期化はサインアップやサインイン機能を実装したときと同じです。
現在のユーザー情報をCognitoUserPool#getCurrentUserで取得しておきます(7行目、変数cognitoUser)。
getUserAttribute関数内で、現在のユーザーの属性情報を取得し、画面に表示しています(38~49行目)。
ユーザーの属性情報の取得はcognitoUser#getUserAttributesで取得することができ、取得結果は変数resultに格納されています。取得に失敗した場合は変数errとしてエラー情報オブジェクトが返却されます。
今回は、現在のユーザー情報や属性情報の取得に失敗した場合、サインイン画面(signin.html)に遷移するように実装しています。
属性情報は一気に全部取得できるので、forループを回しながら連想配列に属性情報を格納します(44~47行目)。今回の場合、email、given_name、family_nameが取得できます。
属性情報はユーザープールの設定によるので、ほしい情報はユーザープール作成時に設定するようにしましょう。ちなみにですが、ユーザープールの仕様上、後から属性を追加することはできませんので要注意です!(ユーザープールの作成は下記の記事をご参考にしてください。)
画面への「ようこそ!〇〇さん」の表示は、48行目で行っています。メニュー画面作成時に空のh1タグを記述したと思いますが、取得した属性情報のfamily_nameを組み込んだ文字列をjQueryのtextメソッドを使ってh1タグに設定しています。
動作確認
それでは動作確認してみましょう。
今回サインインするユーザーは、以下の通りです。
ではサインインしてみます!
Eメールアドレスとパスワードを入力し、「Sign In」ボタンをクリックします。
すると…
表示されました~!
すごくシンプルですが(h1タグしか書いてないので当たり前)、JavaScriptで実装したとおり、family_nameが表示されました。ちなみに、Chromeの開発者ツールでローカルストレージを確認することができます。Applicationタブを開き、左サイドメニューからLocal Storage(のサブメニュー)を選択すると、Key-Value形式で保存されたローカルストレージの内容が表示されます。
字が小さくて見えにくいかもしれませんが、Keyの部分をよく見てみると、保存されている項目の中にはidToken、accessToken、refreshTokenが含まれています。この3つのトークンは、前回の記事でご紹介したとおり、認証に成功すると発行されるものです。このうち、IDトークンには認証されたユーザーに関する情報が含まれており、今回はこのIDトークンを使ってユーザーの属性情報を取得したということになります。
トークンはJWT(Json Web Token)というエンコードされた文字列なので、Valueを見たところで属性情報までは全くわからないのですが、JavaScriptライブラリを使えば、うまいことデコードしたりあれこれしたりしてくれるので、簡単に属性情報を取得することができるということですね。
おわりに
今回はJavaScriptでユーザー情報を取得する処理を実装してみました。結構簡単にできちゃいました。次回は、冒頭にも少し書きましたが、2の「サーバー側でユーザー情報が必要」なケースをやってみたいと思います。使うのはAmazon API Gateway + AWS Lambdaです。「サーバー側」と書きましたが、このAmazon Cognitoシリーズではサーバーレスが大きなキーワードですので、サーバーレスでやりますよ~!お楽しみに。
執筆者プロフィール
- 社内の開発プロジェクトの技術支援や、新技術の検証に従事しています。主にアプリケーション開発系支援担当で、Java&サーバサイドが得意です。最近は、サーバーレスonAWSを推進しています。