概要
AmplifyでOverride機能を利用してAPIGatewayのAuthorizerにCognitoを指定する方法をご紹介します。
課題
2022/3/10現在、Amplify CLIでは、APIGatewayのAuthorizerにIAMしか利用できません。AWSのコンソールからCognitoを指定したとしても更新した際にテンプレートで上書きされてしまい、設定したAuthorizerの情報が消えてしまいます。
そのため、Override機能を利用してAPIのCFnテンプレートを修正する必要があります。
手順
APIGateway・Cognitoのoverride.ts作成
CLIで以下のコマンドを実行し、override.tsを作成します
amplify override auth
amplify override api
override.tsの編集
Authでは、CognitoユーザープールのIDをエクスポートします。
エクスポート名は重複が許されないため、環境名を取得してユニークにしています。しかし、デフォルトではバグで取得できないため迂回しています。詳細は以下の記事をご覧ください。
Amplifyのoverride.tsで環境名を取得する
import { AmplifyAuthCognitoStackTemplate } from '@aws-amplify/cli-extensibility-helper';
export function override(resources: AmplifyAuthCognitoStackTemplate) {
// override.tsでenv名を参照することはできない(バグ)。そのためamplify-metaからenv名を取得している
// https://github.com/aws-amplify/amplify-cli/issues/9063
const amplify_meta_json = require('amplify-meta.json')
const env_name = amplify_meta_json.providers.awscloudformation.StackName.split("-").slice(-2, -1).pop()
const export_user_pool_id = {
description: "cognito user pool id",
value: resources.userPool.ref,
exportName: `exportUserPoolId-${env_name}`
}
resources.addCfnOutput(export_user_pool_id, "AuthCognitoUserPoolId")
}
AuthでエクスポートしたユーザープールIDを利用してAuthorizerを設定します。
import { AmplifyApiRestResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';
export function override(resources: AmplifyApiRestResourceStackTemplate) {
const amplify_meta_json = require('amplify-meta.json')
const env_name = amplify_meta_json.providers.awscloudformation.StackName.split("-").slice(-2, -1).pop()
resources.restApi.body = {
...resources.restApi.body,
"securityDefinitions": {
"sigv4": {
"type": "apiKey",
"name": "Authorization",
"in": "header",
"x-amazon-apigateway-authtype": "awsSigv4"
},
"Cognito": {
"type": "apiKey",
"name": "Authorization",
"in": "header",
"x-amazon-apigateway-authtype": "cognito_user_pools",
"x-amazon-apigateway-authorizer": {
"type": "cognito_user_pools",
"providerARNs": [
{
"Fn::Join": [
"",
[
"arn:aws:cognito-idp:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":userpool/",
{
"Fn::ImportValue": `exportUserPoolId-${env_name}`
}
]
]
}
]
}
}
},
}
//Authorizerはリソースの各メソッドに設定する必要がある
let paths = resources.restApi.body.paths
Object.keys(paths).forEach((key) => {
let path = paths[key]["x-amazon-apigateway-any-method"]
path.parameters = [
...path.parameters,
{
name: "Authorization",
in: "header",
required: false,
type: "string"
}
]
path.security = [
{
"Cognito": []
}
]
});
}
まとめ
上記設定でAuthorizerにCognitoを使用することができます。
AmplifyのOverride用ヘルパーの情報が少なく、記載方法にとまどいましたのでどなたかの参考になれば幸いです。