Home > Net >  CloudFront with Lambda@Edge results in CORS problem
CloudFront with Lambda@Edge results in CORS problem

Time:05-25

I've configured S3 with access only through CloudFront and protected with lambda executed on Viewer request. The problem is that I'm not able to access the files from SPA because of a failing preflight call.

When I removed the lambda function everything is starting to work. This is surprising to me because lambda is not modifying the request at all.

Here is my configuration:

S3: s3

CloudFront:

enter image description here

Lambda@Edge (executed at Viewer request)

exports.handler = async (event, context, callback) => {
    let request;
    let token;

    try {
        request = event.Records[0].cf.request;
        const headers = request.headers;
        const authorization = headers['authorization'][0];
        const authorizationValue = authorization.value;
        token = authorizationValue.substring(7);
    } catch (error) {
        console.error("Missing authorization header", error);
        callback(null, missingAuthorizationHeaderResponse);
    }

    if (token) {
        try {
            if (!secret) {
                secret = await getSecret();
            }
            jwt.verify(token, secret);
            console.log("Token valid");
            callback(null, request);
        } catch (error) {
            console.error("Token not valid", error);
            callback(null, invalidTokenResponse);
        }
    } else {
        console.error("Token not found");
        callback(null, missingAuthorizationHeaderResponse);
    }
};

I will be very grateful for help since I've spent a lot of time on this case, thanks!

CodePudding user response:

The problem is that the preflight call are executed without any additional headers and in my case "authorization" header was missing and was generating 403. I found that by looking into logs of the lambda. I've added handling of options call to the lambda. Also I had to change s3 config to have the response with visible CORS headers.

Lambda Code:

 const preflightCall = {
        status: "204",
        headers: {
                'access-control-allow-origin': [{
                    key: 'Access-Control-Allow-Origin',
                    value: "*",
                }],
                 'access-control-request-method': [{
                    key: 'Access-Control-Request-Method',
                    value: "PUT, GET, OPTIONS, DELETE",
                }],
                 'access-control-allow-headers': [{
                    key: 'Access-Control-Allow-Headers',
                    value: "*",
                }]
        },
    };

exports.handler = async (event, context, callback) => {
    let request;
    let token;

    try {
        request = event.Records[0].cf.request;
        if(request.method === 'OPTIONS') {
            console.log('preflight call');
            callback(null, preflightCall);
            return;
        }
        const headers = request.headers;
        const authorization = headers['authorization'][0];
        const authorizationValue = authorization.value;
        token = authorizationValue.substring(7);
    } catch (error) {
        console.error("Missing authorization header", error);
        callback(null, missingAuthorizationHeaderResponse);
    }

    if (token) {
        try {
            if (!secret) {
                secret = await getSecret();
            }
            jwt.verify(token, secret);
            console.log("Token valid");
            callback(null, request);
        } catch (error) {
            console.error("Token not valid", error);
            callback(null, invalidTokenResponse);
        }
    } else {
        console.error("Token not found");
        callback(null, missingAuthorizationHeaderResponse);
    }
};

S3:

[
    {
        "AllowedHeaders": [
            "Authorization"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD",
            "DELETE",
            "POST",
            "PUT"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [
            "Access-Control-Allow-Origin"
        ],
        "MaxAgeSeconds": 3000
    }
]
  • Related