AWS Cognitoの認証機能をAPI Gatewayの呼び出しに利用する | AWSサーバレス構築
参考にするチュートリアル
・英語版チュートリアル(新しめ)
・日本語チュートリアル(古いけど有益)
・Javascriptコードの在り処
また、事前に当ブログ記事「簡易チュートリアル」を参照のこと。
JavaScript
AWS SDK
amazon-cognito-identity.min.js と aws-cognito-sdk.min.js を、公式チュートリアルのコードから拝借する。(ventorフォルダ)
config.js
Cognitoで作成したユーザープールの「プールID」「アプリクライアントID」「リージョン」を入力する。
window._config = { cognito: { userPoolId: 'プールID', userPoolClientId: 'アプリクライアントID', region: 'リージョン' }, api: { invokeUrl: 'APIGatewayでデプロイしたステージのURL' } };
cognito-auth.js
ログインIDとパスを入力するinput、ログインボタンをhtmlページ上に用意すること。(login.html参照)
// 認証トークン管理変数。全jsファイル間で共有 var tokenManager = window.tokenManager || {}; // 起動時処理 (function cognitoAuthoMain($) { // ユーザープールの取得 var poolData = { UserPoolId: _config.cognito.userPoolId, ClientId: _config.cognito.userPoolClientId }; var userPool; if (!(_config.cognito.userPoolId && _config.cognito.userPoolClientId && _config.cognito.region)) { return; } userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData); if (typeof AWSCognito !== 'undefined') { AWSCognito.config.region = _config.cognito.region; } // === // tokenManager に 関数を設定しておく // サインアウト処理 tokenManager.signOut = function signOut() { userPool.getCurrentUser().signOut(); }; // 認証処理。「check-login-state.js」ファイルにて利用される。 tokenManager.authToken = new Promise(function fetchCurrentAuthToken(resolve, reject) { var cognitoUser = userPool.getCurrentUser(); if (cognitoUser) { cognitoUser.getSession(function sessionCallback(err, session) { if (err) { reject(err); } else if (!session.isValid()) { resolve(null); } else { resolve(session.getIdToken().getJwtToken()); } }); } else { resolve(null); } }); // === // AWS Cognito 認証処理 // ログイン処理 function loginFunc(email, password, onSuccess, onFailure) { var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails({ Username: email, Password: password }); var cognitoUser = createCognitoUser(email); cognitoUser.authenticateUser(authenticationDetails, { onSuccess: onSuccess, onFailure: onFailure }); } function createCognitoUser(email) { return new AmazonCognitoIdentity.CognitoUser({ Username: email, Pool: userPool }); } // === // ページ内処理・イベント // ページ読み込み時の処理 $(function onDocReady() { // ログインボタンにイベント追加 let aTag_login = document.getElementById("a_login"); if( aTag_login ) { aTag_login.href = "javascript:void(0);"; aTag_login.onclick = function() { handleLogin(); }; } // ログアウトボタンにイベント追加 let aTag_logout = document.getElementById("a_logout"); if( aTag_logout ) { aTag_logout.href = "javascript:void(0);"; aTag_logout.onclick = function() { handleLogout(); }; } }); // ログインボタン押下時 function handleLogin() { // フォームに入力された値を取得 var email = $('#login_input_email').val(); var password = $('#login_input_password').val(); // 入力チェック if( (email.length == 0) || (password.length == 0) ) { alert('入力されていない項目があります。ご確認ください。'); return; } // === // ログイン処理実行 // 入力された値でログイン判定、成功したならページ遷移 loginFunc( email, password, function loginSuccess() { console.log('Successfully Logged In'); // ログイン成功でトップページへ遷移 window.location.href = topPageUrl; }, function loginError(err) { console.log('Failed Logged In'); alert('ログインに失敗しました。IDとパスワードをご確認ください。'); } ); } // ログアウトボタン押下時 function handleLogout() { // ログアウト処理 tokenManager.signOut(); // アラート表示 alert('ログアウトしました。'); // ログアウトでログインページへ遷移 window.location.href = loginPageUrl; } }(jQuery));
check-login-state.js
// 認証トークン管理変数。全jsファイル間で共有 var tokenManager = window.tokenManager || {}; // 以降のjsにてAPI認証に使われるトークン。 var authToken; // 起動時処理 (function checkLoginStateMain($) { // 認証失敗時に戻すページのURL。今回はログイン画面に戻す想定。 let loginPageUrl = 'login.html'; // === tokenManager.authToken.then(function setAuthToken(token) { if (token) { authToken = token; } else { alert("ページにアクセスするにはログインを行ってください。ログイン画面に移動します。"); window.location.href = loginPageUrl; } }).catch(function handleTokenError(error) { alert(error); window.location.href = loginPageUrl; }); }(jQuery));
call-api.js
「check-login-state.js」にて取得したトークン「authToken」を、API呼び出し時に渡している。
// 認証トークン管理変数。全jsファイル間で共有 var tokenManager = window.tokenManager || {}; // 引数に、Lambdaに渡すJSONデータと、完了時の関数を渡す // completeFuncは、引数にJSONデータを受け取るので、引数を1つ渡せるような関数とする function requestApi( jsonData, completeFunc ) { $.ajax({ method: 'POST', url: _config.api.invokeUrl + '/admin', headers: { Authorization: authToken }, data: jsonData, contentType: 'application/json', success: completeFunc, error: function ajaxError(jqXHR, textStatus, errorThrown) { console.error('Error requesting: ', textStatus, ', Details: ', errorThrown); console.error('Response: ', jqXHR.responseText); alert("データベースサーバーとの通信に失敗しました。"); } }); }
main.js
call-api.js で準備したAPIコール関数を実行する。APIから応答を受けた後の処理も記述している。
(function MainFunction($) { // Lambda側に渡したいデータをJSON形式で準備 var requestJsonData = { "Key1": "Value1", "Key2": "Value2" }; // Lambda実行完了時の処理 function completeRequest( result ) { // 引数resultは受け取った時点でJSONデータとして認識できる // キーを指定してデータを得られる。複数データも配列として指定して取得すれば良い。 // console.log('Response received from API: ', result); // const responseData = JSON.parse( result ); console.log( result["ReceivedVal1"] ); console.log( result["ReceivedVal2"] ); } // ページ読み込み時の処理 $(function onDocReady() { // Lambda実行 requestApi( JSON.stringify(requestJsonData), completeRequest ); }); }(jQuery));
Html
login.html
<!doctype html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ログインページ サンプル</title> </head> <body> <h1>ログインページ サンプル</h1> <table> <tr><th>ID:</th><td><input id="login_input_email" class="input_text" type="text" required /></td></tr> <tr><th>パスワード:</th><td><input id="login_input_password" class="input_text" type="password" required /></td></tr> </table> <p id="btn_login"><a id="a_login">ログイン</a></p> <!-- javascript --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <!-- Cognito認証 --> <script src="html/js/vendor/aws-cognito-sdk.min.js"></script> <script src="html/js/vendor/amazon-cognito-identity.min.js"></script> <script src="html/js/config.js"></script> <script src="html/js/cognito-auth.js"></script> </body> </html>
index.html
<!doctype html> <html lang="ja"> <head> <meta charset="utf-8"> <title>AWSチュートリアル簡易版テストページ</title> </head> <body> <div>Hello World</div> <!-- jquery --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <!-- 認証処理 --> <script src="js/vendor/aws-cognito-sdk.min.js"></script> <script src="js/vendor/amazon-cognito-identity.min.js"></script> <script src="js/config.js"></script> <script src="js/cognito-auth.js"></script> <script src="js/check-login-state.js"></script> <!-- API呼び出し処理 --> <script src="js/config.js"></script> <script src="js/call-api.js"></script> <script src="js/main.js"></script> </body> </html>