Auth0 Home Blog Docs

AWS Authorizer - Possible Caching Issue?

jwt
authorization
aws
unauthorized

#1

We are seeing some odd behavior with AWS API Gateway and Auth0 Authorizers. We are getting random 403 errors back from our APIs(Lambdas).

We can hit an API and get a 200 back. Then, seconds later, we are getting a 403 out of the blue.

{“Message”:“User is not authorized to access this resource”}

Doing some digging around, it sounds similar to this issue:
https://forums.aws.amazon.com/thread.jspa?threadID=225934&tstart=0

However, I don’t think that post is using Auth0, but I am not 100% sure.

Has anybody experienced something similar?


#2

Your issue sounds familiar. Let me explain the issue I had a while ago maybe it helps you.

I used the custom authorizer and in API Gateway and disabled the Cache. In spite of that it cached the authorize request!

I was sending GET and POST to the same resource. First time that I send a GET the request, it worked fine. Any GET request would work fine but I couldn’t send a POST request for that resource. If I would wait for few minutes and send a POST, it would work again but this time GET had problem.

I solved this issue by changing the returned policy. Each time I send back the policy I allow both GET and POST for that resource. If this change doesn’t make any vulnerability on your system you can try it.


#3

Thanks, @armanfatahi! When you say “send back the policy I allow both GET and POST for that resource”, is that done on the API Gateway or somewhere else?


#4

It’s done in the custom authorizer.

The custom authorizer checked the access_token and creates a policy. Then return the policy to API Gateway.

If you are using the custom authorizer Auth0 introduced, you should see this in the lib.js:

    jwt.verify(token, signingKey, { audience: process.env.AUDIENCE, issuer: process.env.TOKEN_ISSUER },
        function (err, decoded) {
            if (err) {
                cb(err);

            }
            else {

                cb(null, {
                    principalId: decoded.sub,
                    policyDocument: getPolicyDocument('Allow', params.methodArn),
                    context: {
                        scope: decoded.scope
                    }
                });
            }
        });

I changed this code to:

    ...
    jwt.verify(token, signingKey, { audience: process.env.AUDIENCE, issuer: process.env.TOKEN_ISSUER },
        function (err, decoded) {
            if (err) {
                cb(err);

            }
            else {

                cb(null, {
                    principalId: decoded.sub,
                    policyDocument: getPolicyDocument('Allow',  "*";),
                    context: {
                        scope: decoded.scope
                    }
                });
            }
        });

Which means if the user is authorized, allow using the whole API resources, this includes GET and POST for each resource.