7
3

More than 3 years have passed since last update.

【AWS】API Gateway Lambdaオーソライザー「User is not authorized to access this resource」エラーの原因と対応

Posted at

1.png

上記のようなAPIGatewayで構築したAPIにLambdaオーソライザーを適用した際に、正しい認証情報、正しいAWSリソースへのアクセス権限を設定しているにも関わらず「User is not authorized to access this resource」エラーが発生することがあります。
本記事ではその原因と対応を記載します。

原因

Lambdaオーソライザーから返却される認可情報のキャッシングが原因です。

以下のようなアクセスポリシーを返却するコードを記述した際に発生します。

node.js
  ...
  statementOne.Action = 'execute-api:Invoke'; 
  statementOne.Effect = 'Allow';
  // ↓ 以下のアクセス承認するリソースを指定するコードが原因
  statementOne.Resource = event.methodArn;
  ...

ポイントはevent.methodArnです。
ここでは呼び出しされたAPIのみのArnが含まれています。
例: arn:aws:execute-api:ap-northeast-1:xxxxxxxxxxx:xxxxxxxxx/stg/GET/users/43/info

このArnへのアクセス権限を許可したポリシーを返却すると、初回のアクセスはうまくいきます。

2 (2).png

しかし同じLambdaオーソライザーが適用されている他のAPIを呼び出した際に、上記のArnが含まれたポリシーがキャッシュとして返却されてしまい、初回アクセスとは別の認可されていないリソースにアクセスすると「User is not authorized to access this resource」エラーが発生します。

3 (3).png

対応

2パターンの対応方法があります。

パターン1Lambdaオーソライザーの認可のキャッシュのTTL値を0に設定

API Gatewayのオーソライザーから対象のオーソライザーを選択して、
スクリーンショット 2020-08-06 17.43.01.png
TTLを0に変更すると、毎回認証を実行するためevent.methodArnをアクセス承認リソースとして返却しても、問題なく認可が通ります。
ただ毎回認証処理が走るため、パフォーマンス的には優れません
その点が気になる場合は、後述のパターン2を利用することを推奨します。

※ AWS CloudFormation, AWS SAMを利用する場合の注意点
CloudFormation、SAMを利用してLambdaオーソライザーを設定した場合、デフォルトでは認可のキャッシュのTTL値は300秒です。
認可キャッシュのTTL値を変更せずにデプロイしたオーソライザーの設定値をマネジメントコンソールから確認すると...

スクリーンショット 2020-08-06 17.56.52.png

こんな感じでundefinedとなっており、キャッシュが無効になっているように見えます。
しかし実際には300秒のキャッシュ設定が有効になっています。
(これに1時間くらいハメられました...)

TTLを0に設定する際には、ReauthorizeEveryを0に設定しましょう。

template.yaml
  TestApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prd
      Auth:
        AddDefaultAuthorizerToCorsPreflight: false
        DefaultAuthorizer: MyLambdaCustomAuthorizer
        Authorizers:
          MyLambdaCustomAuthorizer:
            FunctionPayloadType: REQUEST
            FunctionArn:
              Fn::GetAtt:
              - RestApiAuthFunction
              - Arn
            Identity:
              QueryStrings:
              - authToken
              ReauthorizeEvery: 0

パターン2 Lambdaオーソライザー側で返却するリソースポリシーを変更

Lambdaオーソライザー側でevent.methodArnを指定するのではなく、ワイルドカードを指定して対応する方法です。

node.js
  ...
  statementOne.Action = 'execute-api:Invoke'; 
  statementOne.Effect = 'Allow';
  // ↓ ワイルドカード指定に変更
  statementOne.Resource = 'arn:aws:execute-api:*';
  ...

上記例では、全Lambdaの実行権限を返却しています。
こうすることでポリシーのキャッシュが行われていても、ワイルドカードで許可されたリソースは問題なくコールすることが可能です。
どこまでをワイルドカード指定にするかは、自身のセキュリティポリシーと相談してみてください。

キャッシュと併用することができるため、パターン1よりもパフォーマンス的に優れていますが、ワイルドカード指定になる分、セキュリティとトレードオフです。

まとめ

  • 1つのオーソライザーを複数のリソースで共有した際に、オーソライザーの認可キャッシュが有効になっていると「User is not authorized to access this resource」が発生する。
  • オーソライザーの認可情報のキャッシュが原因であるため、TTLを0にするか認可リソースを拡大することで対応可能

記載情報に誤りがあったらご指摘いただけると助かります。

参考リンク

7
3
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
7
3