awslabs / aws-support-tools

Tools and sample code provided by AWS Premium Support.
https://aws.amazon.com/premiumsupport/
Apache License 2.0
1.45k stars 800 forks source link

Cache Cognito user pool public key #139

Open deepsadhi opened 3 years ago

deepsadhi commented 3 years ago

In the implementation of jwt verification - https://github.com/awslabs/aws-support-tools/blob/master/Cognito/decode-verify-jwt/decode-verify-jwt.py. On line number 21 - 27 and 32 - 42, the code checks for Congito public key. If the key will remain the same after the creation of Cognito pool till it's destroyed, can I store the public key in environment variables? By avoiding public key fetch on each request, it helps to avoid an extra API request.

Code snippet

region = 'ap-southeast-2'
userpool_id = 'ap-southeast-2_xxxxxxxxx'
app_client_id = '<ENTER APP CLIENT ID HERE>'
keys_url = 'https://cognito-idp.{}.amazonaws.com/{}/.well-known/jwks.json'.format(region, userpool_id)
# instead of re-downloading the public keys every time
# we download them only on cold start
# https://aws.amazon.com/blogs/compute/container-reuse-in-lambda/
with urllib.request.urlopen(keys_url) as f:
  response = f.read()
keys = json.loads(response.decode('utf-8'))['keys']

def lambda_handler(event, context):
    token = event['token']
    # get the kid from the headers prior to verification
    headers = jwt.get_unverified_headers(token)
    kid = headers['kid']
    # search for the kid in the downloaded public keys
    key_index = -1
    for i in range(len(keys)):
        if kid == keys[i]['kid']:
            key_index = i
            break
    if key_index == -1:
        print('Public key not found in jwks.json')
        return False
fondberg commented 3 years ago

I would like to know the answer as well

solariswu commented 3 years ago

Currently, the userpool public keys are not changed after the pool is created.

However, the public key may be rotated in the future without any notification. In that case, the applications using permanent public key values will meet errors at that point.

That is to say, although it has not been happened in the past, you would be on your own risk if taking the public keys as const values.

AAZANOVICH commented 1 year ago

Currently, the userpool public keys are not changed after the pool is created.

However, the public key may be rotated in the future without any notification. In that case, the applications using permanent public key values will meet errors at that point.

That is to say, although it has not been happened in the past, you would be on your own risk if taking the public keys as const values.

Key rotation should be configurable by user, instead of "aws will change it whenever they want without any notice". Unnecessary GET on each request (pretty much) if you use Lambda authorizer (Which BTW I have to use because cognito can't store jwt in a cookie in secure way..)

lucasvall commented 1 year ago

To improve the security of your system, you could consider implementing the following measures:

  1. Store the secret in AWS Secret Manager and periodically rotate it using a Lambda function that retrieves the new public key every 24(?) hours. However, be aware that if AWS rotates the keys, your system might experience failures until the rotating Lambda function updates the cache with the new key. Consider your Service Level Agreement (SLA).

  2. To minimize the number of GET requests to retrieve the public key, you could check the validity of the token against the cached key first. If the token fails to validate, only then retrieve the new keys. If the validation is successful, refresh the cache with the new key. However, note that tokens issued with the old key will still be valid against the cache until they expire, which could lead to potential security risks.

It's also important to keep in mind that if AWS rotates the keys due to a security breach, all old tokens will become invalid, even if they haven't yet expired. This could potentially cause issues for your system and users. In short: cached or not your are going to have problems if AWS changes the key pair!