本記事について
API GatewayのオーソライザーをCORSできるようにするための設定を、Serverless Framework上で行う方法について記載します。
詳しくは下記に記載されているものを、概要を加えて転記いたします。
- https://serverless.com/blog/cors-api-gateway-survival-guide/#cors-with-custom-authorizers
- https://github.com/serverless/serverless/issues/3896#issuecomment-326721971
解説
CORSについて
CORSなAPIにするには、APIのレスポンスヘッダーで「Access-Control-Allow-Headers」「Access-Control-Allow-Origin」を返す必要があります。
API Gatewayで[リソース]-[CORSの有効化]を行うと、API GatewayがCORSに必要なもろもろの設定を行ってくれます。
そのAPI GatewayのCORS設定を、Serverlessで行うには、公式サイトに記載のとおり、serverless.yml
で「cors: true」と記載することで行えます。
オーソライザーのCORSについて
APIでオーソライザーを使った場合のCORSの設定は、上記に加えもうひと手間必要になります。
認証に成功した場合は、本来のAPIが呼び出されるのでCORSのレスポンスの設定がされていて問題ありませんが、認証に失敗した場合は、APIは呼び出されず、オーソライザーからレスポンスが返されるため、別途オーソライザーからのエラー返答用にCORSの設定が必要になります。
この設定を行わないと、認証が失敗して応答があっても、クライアントでCORSエラーが発生して、認証エラーを検知することができなくなってしまいます。
手順(API Gatewayを使った場合)
「401 Unauthorized レスポンス」と「500 Authorizer Failure レスポンス」で下記のレスポンスヘッダーを返すようにします
- 「Access-Control-Allow-Headers」:「'*'」
- 「Access-Control-Allow-Origin」:「'*'」
設定は[ゲートウェイのレスポンス]で行います。
401・500の違い
公式ヘルプに記載のとおり、callback("Unauthorized")
でエラーを返した場合は「401 Unauthorized」、「"Unauthorized"」以外でエラーを返した場合は「500 Internal Server Error レスポンス」になります。(本記事では両方を設定しています)
手順(Serverlessを使った場合)
設定は上記API Gatewayを使った場合と同じですが、API Gatewayを直接変更できないため、serverless.ymlの「resources」で、API Gateway設定を行います。
resources:
Resources:
GatewayResponse401:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
ResponseParameters:
gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
ResponseType: UNAUTHORIZED
RestApiId:
Ref: 'ApiGatewayRestApi'
StatusCode: '401'
GatewayResponse500:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
ResponseParameters:
gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
ResponseType: AUTHORIZER_FAILURE
RestApiId:
Ref: 'ApiGatewayRestApi'
StatusCode: '500'
以上で、認証失敗した場合でもレスポンスヘッダーが返されるようになり、オーソライザーを使ったAPIでもCORSが行えるようになります。
その他
ServerlessはCloudFormationでAWSのリソースを作成しており、ゲートウェイレスポンスの設定はCloudFormationのGatewayResponseの記述とほぼ同じです。