AWS Lambda@edge to set cookies to origin response

Viewed 2198

My objective is to protect an aws s3 bucket link and I'm trying to solve this by using cloudfront as the link via which the s3 buckets are accessible, hence when a user tries to access the cloudfront link, there is a basic auth if there's no cookie in their browser, but if there's a cookie, then auth values in this cookie is checked and user is granted access. PS: This is not a website, my quest is to protect s3 bucket links.

Here is my attempt, using lambda@edge, on viewer request, there's the auth page if user is not logged in, otherwise, they're allowed access, it works but I can't set cookies, because somewhere in aws documentation, cloudfront deletes set-cookies in header files: CloudFront removes the Cookie header from requests that it forwards to your origin and removes the Set-Cookie header from responses that it returns to your viewers

Here is my code:

'use strict';

// returns a response error
const responseError = {
                status: '401',
                statusDescription: 'Unauthorized',
                headers: {
                    'www-authenticate': [{key: 'WWW-Authenticate', value:'Basic'}]
                }
};




exports.handler = (event, context, callback) => {
    // Get request and request headers
    console.log(event.Records[0]);
    const request = event.Records[0].cf.request;
    const response = event.Records[0].cf.response;
    const headers = request.headers;



    // checks to see if headers exists with cookies
    let hasTheHeader = (request, headerKey) => {
        if (request.headers[headerKey]) {
            return true;
        } 
        else return false;
    };

    // Add set-cookie header to origin response
    const setCookie = function(response, cookie) {
        const cookieValue = `${cookie}`;
        console.log(`Setting cookie ${cookieValue}`);
        response.headers['set-cookie'] = [{ key: "Set-Cookie", value: cookieValue }];    
    }


    // Configure authentication
    const authUser = 'someuser';
    const authPass = 'testpassword';
    let authToken;
    let authString;

    // Construct the Auth string
    const buff = new Buffer(authUser + ':' + authPass).toString('base64');
    authString = 'Basic ' + buff;


    const authCookie = 'testAuthToken';

    //execute this on viewer request that is if request type is viewer request:
    if(event.Records[0].cf.config.eventType == 'viewer-request'){

        //check if cookies exists and assign authToken if it does not
        if(hasTheHeader(request, 'cookie')  ){
            for (let i = 0; i < headers.cookie.length; i++)
            {
                if (headers.cookie[i].value.indexOf(authString) >= 0)
                {
                    authToken = authString;
                    console.log(authToken);
                    break;
                }
            }
        }

        if (!authToken)
        {
                if (headers && headers.authorization && headers.authorization[0].value === authString)
                    {

                        // Set-Cookie: testAuthToken= new Buffer(authUser + ':' + authPass).toString('base64')



                        authToken = authString;
                        request.header.cookie = [];

                        //put  cookie value to custom header - format is important
                        request.headers.cookie.push({'key': 'Cookie', 'value': authString});

                    }
                else
                    {
                        callback(null, responseError);
                    }

                // continue forwarding request
                callback(null, request);
        }

        else{
            //strip out "Basic " to extract Basic credential in base 64
            var authInfo = authToken.slice(6);    

            var userCredentials = new Buffer(authInfo, 'base64');
            var userLoginNamePass = userCredentials.toString();

            var baseCredentials = userLoginNamePass.split(":");
            var username = baseCredentials[0];
            var userPass = baseCredentials[1];


            if (username != authUser && userPass != authPass) {

                //user auth failed
                callback(null, responseError);

            } else {

                request.header.cookie = [];

                //put  cookie value to custom header - format is important
                request.headers.cookie.push({'key': 'Cookie', 'value': authString});

            }

            // continue forwarding request
            callback(null, request);

        }

    }
    else if(event.Records[0].cf.config.eventType == 'origin-response')
    {

        if(hasTheHeader(request, 'cookie')){
            for (let i = 0; i < headers.cookie.length; i++)
            {
                if (headers.cookie[i].value.indexOf(authString) >= 0)
                {
                    setCookie(response, authString);
                    break;
                }
            }

        }

        // console.log(res_headers);
        console.log("response: " + JSON.stringify(response));
        callback(null, response);

    }
};

Your suggestions will be most welcome. Thanks in advance.

0 Answers
Related