Serverless FrameworkでCognito UserPoolの認証をしばくときのメモ
- 社内向けのサーバーレスなサービスが想定で、API GatewayでセキュアなAPIを作ることを考える。
- そこでCognito UserPoolを使った場合のメモ
Severless Framework
auth:
handler: auth.default
timeout : 5
memorySize : 256
secureCheck:
handler: handler.secureCheck # 動かすlambda関数名
timeout : 5
memorySize : 128
events:
- http:
method: get
path: secureCheck
cors : true
authorizer: auth #authorizer: xxx:xxx:Lambda-Name も可能
response:
headers:
Content-Type: "'application/json'"
template: $input.path('$')
/secureCheck と云うAPIは,authと云うLambda Functionの認証を経てsecureCheck Functionに至るようになる。
そうでなければ403が返る。
この形式でsecureCheck APIにアクセスするとき、リクエストのAuthorizationヘッダーに
Cognito UserPoolでログイン認証したアクセストークンをつけること。
クライアント側の処理は今回は書かない。
auth.ts
const aws = require("aws-sdk");
var cognitoidentityserviceprovider = new aws.CognitoIdentityServiceProvider({
apiVersion: '2016-04-18',
region: 'ap-northeast-1'
});
const auth = (event, context, callback)=> {
const token = event.authorizationToken != null ? event.authorizationToken : event.headers.Authorization
var params = {
AccessToken: token
};
cognitoidentityserviceprovider.getUser(params, function (err, data) {
if (err) {
console.log(err)
callback(null, generatePolicy('user', 'Deny', event.methodArn , token));
//callback(null, generatePolicy('user', 'Allow', event.methodArn, data));
} else {
console.log(data)
callback(null, generatePolicy('user', 'Allow', event.methodArn , token));
}
return;
});
};
//"methodArn":"arn:aws:execute-api:<regionId>:<accountId>:<apiId>/<stage>/<method>/<resourcePath>"
const generatePolicy = function generatePolicy(principalId, effect, resource , token) {
return {
principalId:principalId,
policyDocument: {
Version: '2012-10-17',
Statement: [{
Action: 'execute-api:Invoke',
Effect: effect,
Resource: "arn:aws:execute-api:ap-northeast-1:*:<API Gateway Id>/*” //CHECK!! => http://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/permissions.html#api-gateway-calling-api-permissions
}]
}
};
};
export default auth;
generatePolicyメソッドで、ユーザーに対して必要なAWSの権限をつけている。
ここでは、該当のAPI GateWayの各エンドポイントのinvoke権がつくように組んだ。
他メモ
Cognito UserPoolのAccessTokenやIdTokenのexpireはぴったり1時間なので、
APIを叩くたびに Cognateアクセストークンのexpireチェック => 必要ならばCognitoのrefresh叩いてToken更新 => セキュアなAPI gateway叩く、というフローを経ることになる。
Dynamoにセッションとか入れとくよりは楽なのだろうけど割とラフに非同期チェーンが入ってめんどくさい。
毎回リクエストヘッダにアクセストークンつけるのも、Ajax以外でのエンドポイントのアクセスが制限されてしまうので、なんとかCookie使う方向で今後模索してみる。