LoginSignup
5
4

More than 3 years have passed since last update.

APIGatewayにCognitoオーソライザーをSwaggerで設定する(CloudFrontも少し)

Posted at

背景

AWS使ってサーバーレスで自分用の家計簿的なwebサービスを勉強も兼ねて開発中。メイン機能は大分出来てきて、あとは残課題の対応という形。前の記事でCognitoは対応していたが、フロント部分のみ。APIGateway部分にはCognito制御をしていない。せっかくCognito使ってるので、APIGateway側でも制御を入れたい。

まずAWS側設定

手法検討

色々ページを見ていると、CloudFormationでやっているケースあればSwaggerでやってるケースもあり。今回、API部分はSwaggerでやっているのでSwaggerで出来る部分はSwaggerでやりたい。

やってみた。

色々なページを参考にさせてもらうと、lambdaで認証しているケースが多い。世の中はlambdaで認証チェックするのが主流らしい。Cognitoでやろうという所はあまりないらしい。色々試してみたが、swagger書式でないとか言われたり、エラーは出なかったが、APIGatewayのオーソライザーのタブ見ても新規生成されていなかったり。階層やその表現を色々変えてやったが上手く行かず、手動でやってしまおうかとも考えた。が、結果的に以下の設定でAWSへの反映は出来た。

swaggerのオーソライザー定義部分
# トップ階層(componentsセクション配下の方が良いのか?その場合はsecuritySchemes?)
securityDefinitions:
  # このapi_keyは既存部分(Cognito使ったらもう要らないか?)
  api_key:
    type: "apiKey"
    name: "x-api-key"
    in: "header"
  # この名前を各メソッド設定で使用
  myhomeAccountAuthorizer:
    type: "apiKey"
    # 認証に使うトークンを格納するヘッダーのキー
    name: "Authorization"
    # ここを変えたらヘッダー以外でも可能?
    in: "header"
    x-amazon-apigateway-authtype: "cognito_user_pools"
    x-amazon-apigateway-authorizer:
      type: cognito_user_pools
      # 999999999999はアカウントID、ap-northeast-1_hogehogeはCognitoユーザープールID
      providerARNs:
      - "arn:aws:cognito-idp:ap-northeast-1:999999999999:userpool/ap-northeast-1_hogehoge"
      identityValidationExpression: ".*"
swaggerで各メソッドへオーソライザーを指定する部分例
paths:
  /api/download:
    get:
      produces:
      - "application/json"
      parameters:
        # ・・中略・・
      responses:
        # ・・中略・・
      security:
        - api_key: []
        # で使用したオーソライザーの名前を指定
        - myhomeAccountAuthorizer: []

AWSコンソール側でのオーソライザーテスト

成功すると、AWSコンソール側で、APIGateway => API => オーソライザーで、作成したオーソライザーが表示される。そこでオーソライザーのトークンテストが出来る。
今回、クライアント側ではVue.jsを使用している。javaScriptのawsライブラリ使用中。
session.getAccessToken().getJwtToken() で取得した値を入れてみたが、Unauthorized requestになってしまった。
session.getIdToken().getJwtToken()で取得した値を入れてみたら、AWSコンソール上でのテストは成功。
参考

そしてクライアント側設定

もちろんAPIGateway側で認証設定をしたので何もしないとAPI実行で403エラーが返ってくる様になる。ヘッダにAuthorizerキーで、上記IDトークンを指定すればいいはず。開発環境で普通に成功した。

こんなヘッダ
// key, idtokenは変数名
headers: {
  'Content-Type': 'application/json',
  'x-api-key': key,
  'Authorization': idtoken
}

これで今まで通りに使える、と思っていたら、CloudFront経由のアクセス(本番)でうまく行かない。

ブラウザのResponseHeaderに出てたエラー
x-amzn-errortype: UnauthorizedException
x-amzn-requestid: ************
x-cache: Error from cloudfront

あ、CloudFrontからAPIGatewayに、ヘッダのAuthorizer情報渡ってない・・・
↓ですね。
【小ネタ】カスタム認証を使うAPI GatewayをCloudFrontの後ろに置いたらAPIを叩けなくなった
こちらの神ページを参考に、ヘッダキャッシュ制御の種別をwhitelist指定にして、Authorizerヘッダをwhitelistに追加する事により解消。CloudFrontまわりはCloudFormationでの構築しているのだが、該当部分は以下の形になった。
※この時、ついでに後で使うかもしれないヘッダーを幾つか追加してみたらアクセスエラーになった。使ってもないヘッダーは指定しない方がよさそう。

CloudFrontのCloudFormationテンプレート該当部分
        CacheBehaviors:
        - TargetOriginId: ApiGatewayOrigin
          AllowedMethods:
            - GET
            - HEAD
            - OPTIONS
            - PUT
            - PATCH
            - POST
            - DELETE
          ForwardedValues:
            Cookies:
              Forward: all
            # ここを指定する事でwhitelist指定となる。
            Headers:
              - Authorization
            QueryString: True
          ViewerProtocolPolicy: redirect-to-https
          SmoothStreaming: False
          Compress: True
          PathPattern: api/*
          MinTTL: 0
          MaxTTL: 0
          DefaultTTL: 0

参考にさせてもらったページ

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4