AWS API Gateway custom Authorizer strange showing error

16,076

Solution 1

This could be fixed in two ways that are described in buggy's answer: https://forum.serverless.com/t/rest-api-with-custom-authorizer-how-are-you-dealing-with-authorization-and-policy-cache/3310

Short version:

  1. Set TTL for customer authorizer to 0
  2. Set custom authorizer policy resource as "*"

I've tried each solution and they both solved the issue with "User is not authorized to access this resource" for me.

Solution 2

This error will occur if you use event.methodArn as a resource for generated policy and share an authorizer between different functions, because of how policy caching works. For provided token it caches a policy across an entire API, it will be the same cache entry for all methods and resources within the same API and stage (if they share the same authorizer).

For example, when making a request to GET /users, ARN will look something like this:

arn:aws:execute-api:us-1:abc:123/prod/GET/users

Next call to any endpoint with the same authentication token will use a cached policy, which was created on the first call to GET /users. The problem with that cached policy is that it's resource only allows a single particular resource arn: ... /prod/GET/users, any other resource will be rejected.

Depending on how much do you want to limit policy permissions, you can either mention every possible resource when creating a policy

{
  "principalId": "user",
  "policyDocument": {
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow",
        "Resource": [
          "arn:aws:execute-api:us-1:abc:123/prod/GET/v1/users",
          "arn:aws:execute-api:us-1:abc:123/prod/POST/v1/users",
          "arn:aws:execute-api:us-1:abc:123/prod/GET/v1/orders"
        ]
      }
    ],
    "Version": "2012-10-17"
  }
}

or use wildcards

"Resource": "arn:aws:execute-api:us-1:abc:123/prod/*/v?/*"

or even

"Resource": "*"

You can use policy variables for some advanced templates.

It is also possible to use a blacklist approach by allowing everything using wildcards and then denying specific resources in another policy statement.

Sources:

Solution 3

In the your custom policy build code use, the node js module aws-auth-policy The Nodejs part you can use ,

AuthPolicy.prototype.allowAllMethods = function () {
  addMethod.call(this, "allow", "*", "*", null);
}

In the code

const AuthPolicy = require('aws-auth-policy');
  const policy = new AuthPolicy(principalId, awsAccountId, apiOptions);
           // policy.allowMethod(method, resource);
            policy.allowAllMethods();
            const authResponse = policy.build();

Solution 4

I fixed this by setting the AuthorizerResultTtlInSeconds to 0.

The reason for this is that I was using a shared authorizer. However the authorizer worked by reading the event context of the request and granting an IAM to then invoke a specific lambda.

Because the authorizer was shared it was caching the response which was an IAM for a specific lambda for the TTL of (in my case) 300 seconds.

Therefore, I could call one API one minute, then not the next.

Changing the value above to 0 fixed the issue.

Share:
16,076
Arman Fatahi
Author by

Arman Fatahi

www.armanfatahi.com

Updated on June 14, 2022

Comments

  • Arman Fatahi
    Arman Fatahi almost 2 years

    Here is the context:

    • I set up a resource in the API gateway. /user/company
    • This resource have 2 methods. Get and POST.
    • I have configured a custom Authorizer for this resource.

    The problem:

    • I can call the GET method by sending right authorization information and I get the results as expected.
    • I try to send a POST request and I get the following error:

    {
      "message": "User is not authorized to access this resource"
    }
    • If I wait for few minutes, then call the POST method, it will work.
    • If after calling the POST method and getting the results I call GET method, it will show the same error as mentioned above.

    In addition, I have disabled cache for the authorizer.

    enter image description here

    What might have caused this issue?

  • astroanu
    astroanu almost 4 years
    setting TTL to 0 did the trick. if anybody's using cf or sam use the ReauthorizeEvery property in the template.
  • roccolocko
    roccolocko over 3 years
    This does the trick, but what if do want the caching?
  • Lolo.
    Lolo. about 3 years
    I think this should be the best answer. Set TTL to 0 (disable cache) will make authorizers been called whenever your endpoints have been called. This probably not what developers want.
  • ken
    ken almost 3 years
    OOOOMMMMGGGG... YOU ARE THE TRUE LIFE SAVER 😂🤣 Thank you very much
  • Jeff S.
    Jeff S. over 2 years
    This is a good answer as it describes what the actual issue is.
  • Adrian B
    Adrian B about 2 years
    Agree with the above : this answer explains what the problem is and how to fix it. Turning off caching without knowing why seems like the wrong approach.