简体   繁体   中英

API Gateway Authorizer - IAM policy not caching

I am trying to cache the IAM policy returned by the authorizer lambda when it validates the JWT token for the first time. I have enabled and set the authorizerResultTtlInSeconds to 3500 seconds in API Gateway Authorizer. However, I still see a request going to the Authorizer lambda function within the caching time frame.

My node.js script is as below:

const jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');

const keyClient = jwksClient({
    jwksUri: process.env.JWKS_URI
})

const allow = {
    "principalId": "user",
    "policyDocument": {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": "execute-api:Invoke",
                "Effect": "Allow",
                "Resource": process.env.RESOURCE // RESOURCE = *
            }
        ]
    }
}

const unauthorized = {
    "error": "Unauthorized",
}

//excluded verificationJWTOptions object and getSigningKey function for simplicity
function validateJWTToken(token, callback) {
    jwt.verify(token, getSigningKey, verificationJWTOptions, (error) => {
        if (error) {
            callback(unauthorized)
        } else {
            callback(null, allow)
        }
    })
}

exports.handler = (event, context, callback) => {
    const token = extractTokenFromHeader(event);
    validateJWTToken(token, callback);
}

Not sure what I am missing out. Any help would be much appreciated!

I figured out that I wasn't testing the API Gateway Authorizer caching logic correctly. I have been testing various scenarios and found two cases here:

  • When token is valid: When an endpoint is invoked, the request goes to the Lambda Authorizer which validates/invalidates the token. An IAM policy is returned by the function to the API Gateway Authorizer and gets cached (in this case - for 58 minutes, 20 seconds ).

    The header name specified in Token Source becomes the cache key and the authorization policy generated by the authorizer becomes the cache value. The API gateway will check the header specified in Token Source . If value of the header matches the key, API Gateway will not invoke the Lambda Authorizer and will instead check whether the policy is valid according to the configured TTL .

    If a new token gets generated within the caching time frame, then a call is made again to the Lambda Authorizer and this token gets cached. Thus, if an endpoint is invoked using these two tokens, then no call is made to the Lambda Authorizer as IAM policies for these tokens are cached already for the given cache time frame and the response is got back.

  • When token is invalid: For instance, if the token is valid for 30 minutes from 11:00:00AM to 11:30:00AM , and the cache TTL is set to 58 minutes . The client makes 2 API requests using that token, one at 11:29:59AM and the other at 11:31:3APM - then both requests will be accepted although the second one used an expired token. This basically means that the JWT token gets extended by the cache TTL .

I hit the same issue using AWS CDK. I believe this is a bug in CDK, CloudFormation or API Gateway itself.

The workaround was to manually re-deploy the API Gateway stage. Otherwise the caching option had no effect.

The deploy action can be found from the "Actions" menu in "Resources" section:

重新部署操作

I believe this is a bug because AWS CDK should do this automatically by default because deploy: true is the default in RestApi construct:

https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApi.html#deploy

Indicates if a Deployment should be automatically created for this API, and recreated when the API model (resources, methods) changes.

In CDK code I was able the force redeployment by renaming the RequestAuthorizer id:

api.root
    .addResource("things")
    .addMethod("POST", new LambdaIntegration(nextHandler, {}), {
        apiKeyRequired: true,
        authorizer: new RequestAuthorizer(
            this,
            "Authorizer3", // 👈 Update this if you change resultsCacheTtl
            {
                // WARNING: resultsCacheTtl change requires manual
                // deployment from the AWS console. Or update the
                // RequestAuthorizer id
                resultsCacheTtl: Duration.minutes(5),
                handler: authorizer,
                identitySources: [IdentitySource.queryString("jwt")],
            },
        ),
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM