How to send a cookie as a response?

Hi,

I’d like to set a cookie in the response so it can be stored in the browser. How can this be achieved?

There’s a blog that outlines how it can be done but it requires configuring API Gateway.

As I’m using lambda-proxy I was hoping it could be achieved without having to configure API Gateway. I have cors: true enabled in serverless.yml and setting the headers in the response. I tried a mix of what was outlined in the blog but it doesn’t appear to be returning the cookie. My code is below (using serverless-webpack for ES6):

export const hello = (event, context, cb) => {
  const promise = Promise.resolve({
    statusCode: 200,
    headers: {
      "Access-Control-Allow-Origin" : "*", // Required for CORS support to work
      "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS 
    },
    body: JSON.stringify({
      message: 'GET / called',
      input: event,
      loggedIn: false,
      redirectUri: 'www.nba.com',
      Cookie: 'testcookie1=12345; domain=localhost:8000; expires=Thu, 19 Apr 2018 20:41:27 GMT;"'
    }),
    Cookie: 'testcookie2=12345; domain=localhost:8000; expires=Thu, 19 Apr 2018 20:41:27 GMT;"'
  });

  promise.then(r => cb(null, r))
    .catch(e => cb(e));
};

1 Like

Looks like the above code needs the 'Set-Cookie': 'mycookie=test' header

Hi David,

Tried setting it in the headers section to no avail.

headers: {
      "Access-Control-Allow-Origin" : "*", // Required for CORS support to work
      "Access-Control-Allow-Credentials" : true, // Required for cookies, authorization headers with HTTPS 
      "Set-Cookie": 'mycookiee=test; domain=localhost; expires=Thu, 19 Apr 2018 20:41:27 GMT;"',
      "Cookie": 'anotherCookie=test; domain=localhost; expires=Thu, 19 Apr 2018 20:41:27 GMT;"'
    },

Hmmm not sure.

Can you send me the code to test over here?

david at serverless dot com

I’ve made my private repo public: https://github.com/andrewoh531/accounts-service

Tried a bunch of stuff. Seeing the same as you.

I get the set-cookie header back in the response but don’t see the cookie http://volatile-swim.surge.sh/

It looks like it can be done with custom response headers: https://serverless.com/framework/docs/providers/aws/events/apigateway#custom-response-headers

Going to ask the @pmuens and @eahefnawy for some insight here =)

Thanks!

When you say that it can be done with custom response headers, do you mean configuring the serverless.yml file? Looks like only fixed cookie values can be returned with custom response headers.

I’ve set cookies using the Set-Cookie header with lamba-proxy integration but I was returning text/html instead of application/json.

@andrewoh531I assume you’re not deploying with domain=localhost as that would muck with things.

You’re probably experiencing a problem caused by the API and the website having different origins. Search Stack Overflow for 5 minutes and you’ll find a bunch of people having similar issues. See http://stackoverflow.com/questions/14462423/cross-domain-post-request-is-not-sending-cookie-ajax-jquery for example

If you’re building an API then I would recommend against using cookies.

Also look at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials which talks about setting the "Access-Control-Allow-Credentials": true header so that credentials (i.e. cookies) are exposed to the page.

Hi Buggy,

Thanks for your suggestions. Tried them out but didn’t help. I’m trying to build a serverless authentication service and would like to return a jwt token in the response cookie which is what I’m trying to achieve here.

Is your serverless available on Github or somewhere public? Would like to compare configurations to see if there’s something I may have overlooked.

Thanks

Apologies. I got the solution working when I deployed to AWS. I was testing locally and expecting it to work when running offline using serverless-webpack's.

I’m guessing that it’s API Gateway that’s actually doing some “stuff” to set the cookie in the response.

Thanks David + Buggy for the responses.

1 Like

It’s not public at the moment but it probably will be in a few weeks.

When the user makes an API call to authenticate themselves the payload includes a JWT token that is kept in session storage. All future API calls need to include that token in the headers so I can tell who is making the API call.

Hi Buggy,

Somewhat of a side track but I was using cookies (with httpOnly and secure options set) over sessionStorage/localStorage for security reasons. There’s a post here if you’re interested: https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

Cheers

2 Likes

Did anyone solve this yet?

Most of what’s posted here still seems valid. You can set cookies (in general) using the Set-Cookie header. If you’re having a problem it’s almost certainly not serverless specific. The only thing I would add is making sure you set withCredentials = true when making an AJAX request.

@buggy thanks for the response.

I’m trying to do service-to-service (no AJAX). I.e., a have two services: “web” and “auth” (which are both aws-serverless-express services). “web/home” redirects to “auth/login” which (successfully) does the OAuth dance with an external provider and creates a JWT token. It then redirects back to “web/profile”.

In the “web/profile” service handler I want to access the JWT – either through a cookie or a header. For example:

web/home => auth/login => google/auth => auth/callback => web/profile

In the auth handler I have:

res.set({
  'Access-Control-Allow-Origin' : '*', // Required for CORS support to work
  'Access-Control-Allow-Credentials' : true, // Required for cookies, authorization headers with HTTPS 
  'Set-Cookie': 'xxx=123'
});

res.redirect(callbackUrl);    // In this case "web/profile"

But the event (in the “web” service that is redirect to) doesn’t have the header.

If you want help you’ll need to provide a lot more detail about exactly what you’re attempting to do. The more specific you are the easier it is to answer. Currently there are too many gaps and assumptions that need to be made.

I would also suggest starting your own thread rather than hijacking this one. From what you’ve written so far I suspect your problem is an understanding of how to pass auth tokens between services rather than how to send a cookie in a response.

I also have an oauth partner where that partner calls my serverless /oauth endpint where the dance is done. On success I want to create a JWT token and then redirect to my react app.

(The JWT would then be passed from the frontend in every api gateway call and verified by a custom autorizer)

But Im wondering about the best way to pass the JWT to the frontend?

  • with a cookie (I guess that means my authorizer would check the cookie each time)

  • or just pass it back in response, store it somewhere locally in the app like local storage etc and then somehow pass it as an Authorization header each time in each api gateway request (via https of course)

@richburdon curious did you figure it out ?

Did anyone figure out how to return cookies in serverless-offline? I’m not seeing the cookies in Chrome.