Reduce size of authorization python AWS Lambda@Edge

Question:

I’m trying to implement authorization in my cloudfront distribution. It has worked so far until I ran into size limitation. I’m now running into the cloudfront error message Max allowed: 1048576, which is roughly ~1MB. But after installing the authlib package the total size is around 6MB. My method for validating tokens look roughly like this:

from authlib.jose import JsonWebToken

jwk = get_jwk()
claims_options = {
    "iss": {"essential": True, "value": ISSUER},
    "aud": {"essential": True, "value": AUDIENCE}
}
jwt = JsonWebToken()
claims = jwt.decode(token, jwk, claims_options=claims_options)
claims.validate()

The whole thing works beautifully until the size limitation.

My ideas to get around this are:

  1. Find another package than authlib that is smaller/more efficient.
  2. Write my own code which validates hash signature of JWT (get around the need for authlib package).
  3. Write the Lambda in javascript to leverage the NodeJSfunction, which according to docs are efficient in packaging the lambda. In the hopes of that its enough.

Perhaps there are more alternatives, but these are the ones I could come up with which are desirable in descending order. Requesting assistance on either of these options or perhaps totally different solution.

Asked By: Frankster

||

Answers:

The problem with authlib package is that a significant part of its size is cryptography dependency, which has compiled dependencies on its own. Here are few thought on how it can be approached.

Solution with less dependencies

One option to consider is trying out a more lightweight package like pyjwt. According to the documentation, pyjwt requires cryptography dependency if you want to encode or decode tokens using certain digital signature algorithms like RSA or ECDSA. This means that with a lightweight version of pyjwt (without cryptography dependency) you can use the HS256 algorithm, but not RSA or ECDSA. Without cryptography, pyjwt library should be below size limit.

I’m not an cryptography expert, but as I understand HS256-based JWT could be subject to a brute force or a dictionary attack. Therefore, it is recommended to use RS256 or ES256 algorithms instead, which are possible only with cryptography.

Solution with delegating jwt decoding to a different API

An interesting solution on how to use recommended algorithm is shown in this repository, where
Lambda@Edge simply makes a request to another API that does not have such harsh limit on its size and can use cryptography without compromising security.

Another way to delegate jwt decoding would be to invoke a separate Lambda function. Current size quotas for a standard Lambda’s deployment package is 50 MB for zipped archive and 250 MB for unzipped package, so you can easily use cryptography with authlib or pyjwt there. Please mind that invoking Lambda this way would be synchronous. You probably would also have to add "lambda:InvokeFunction" permission.

import json
from boto3 import client as boto3_client

lambda_client = boto3_client('lambda')

def lambda_handler(event, context):
    # ...
    response = lambda_client.invoke(
        FunctionName="another_lambda_",
        InvocationType='Event', # or 'RequestResponse' for sync request/response
        Payload=json.dumps(your_payload)
    )
    # ...
Answered By: Pawel Kam