サーバレスAPI認証作成手順
こんにちは。すーさんです。
今回はAWSで簡易的な認証システムの作り方を説明します。
(※入金の確認や認証キーの送付は考慮していないちょー簡易的なものなので、完全自動化する場合は別途組み込む必要があります。)
ちなみに、入金システムは利用料金的にもセキュリティ的にもPAY.JPがオススメです。(クレジットカード決済、ApplePayに対応しています。)
Step1 DynamoDBでテーブルの定義をする
テーブル作成時にはプライマリーキーとソートキーしか設定できない。
カラムを追加するには、テーブル作成後にテストデータのの入力と共にカラムの設定をしなければならない。
テーブル名:user_authentication
カラム:userID(プライマリーキー)、password
Step2 Lambdaでユーザー新規追加関数と認証機能関数の2つの関数を作る
①クライアントからUserIDが送られてきた時にランダムで認証キーを作成してDynamoDBに保存し、認証キーをクライアントに返す関数。(簡略化のため割愛)
②クライアントからユーザーIDとパスワードを渡されたときにDynamoDBの該当データを引っ張り、合っているか確かめる関数。(ソースは下記)
expor ts.handler = function(event, context, callback){ console.log(event);var params = { "TableName": "user_authentication", "Key":{ "email": event.userID } }; console.log('テスト'); dynamo.getItem(params, function(err, res) { if (err){ callback(null,response); } else { var response = {"result":""}; if(event.password === res.Item.password){ response.result = "認証に成功しました。"; }else{ console.log('失敗') response.result = "認証に失敗しました。"; } callback(null,response); } }); };
Step3 API Gateway によって外部からLambdaを呼び出せるようにする(API化する)
APIを作成したら、アクション→メソッドの追加でGETを関数①に紐づけて、POSTを関数②に紐づける。
GETのメソッドリクエストからURLクエリを指定(userIDとpassword)する。
統合リクエストでクライアントから渡されるURLクエリをマッピングする。
content-typeはapplication/jsonにして、マッピングの本文は下記
{ "userID":"$input.params('userID')", "password":"$input.params('password')" }
これによって、URLクエリがLambdaの第一引数eventに渡される。
Step4 APIをデプロイしてSDKを作成する
まずはリソース毎に「アクション→CORSの有効化」によって外部からアクセスできるように設定します。
そして「アクション→APIのデプロイ」で専用のSDKを作成したら、クライアントで使います。
GETやPOST関数はapigClient.jsに書いているので、その関数を利用することでAPI Gatewayをクライアントから呼び出せます。
下記はSDKを作ってクライアントに適用した場合のGetの例。
・URLクエリはparamsにjson形式で渡す。
・userPluginGetというGETメソッドだが、userPluginというのはAPI Gatewayによってよって名前が変わる。apigClient.jsでGETメソッドの名前をチェックして使うようにする。
・API GatewayからのレスポンスはLambdaのcallbackで返された形式に従う。
(JavaScriptコード)
$('#authenticate').click(function(e) { var user_ID = $('#user_id').val(); var password = $('#password').val(); var apigClient = apigClientFactory.newClient(); var params={"userID":user_ID,"password":password}; var body={}; var additionalParams = {}; apigClient.userPluginGet(params,body,additionalParams) .then(function(response) { $('#result').val(response.data.result); }).catch(function(result) { //This is where you would put an error callback console.log('error:'+result.data); }); });
(HTMLコード)
<table border="0"> <tbody> <tr> <th>ユーザID:</th> <td><input id="user_id2" size="24" type="text" value="testuser" /></td> </tr> <tr> <th>認証キー:</th> <td><input id="password" size="24" type="password" value="********" /></td> </tr> <tr> <td colspan="2"><button id="authenticate" type="button">認証する</button></td> </tr> </tbody> </table> <table> <tbody> <tr> <th>認証結果:</th> <td><input id="result" size="25" type="text" /></td> </tr> </tbody> </table>
エラーが出た時などに修正する時の注意点
・API Gatewayの修正をした場合は、APIをデプロイし直し→SDKを再度作成→クライアントに適用を行うこと。
・task timeoutというエラーはLambdaのタイムアウト時間が短すぎるため、Lambda設定画面のconfiguration→Advanced Settingからタイムアウト時間を延ばす。
・”Process exited before completing request.”はデータベースのへの検索時にクエリ指定を間違えた時に出るエラーなので、クライアントのparams、API Gateway のクエリ文字列設定とマッピング設定、Lambda関数のクエリをチェックする。
今回は以上となります。
lambda、dynamoの組み合わせで、サーバーレスxxxxが簡単に構築できます。
みなさんもぜひチャレンジしてみて下さい!