These are some notes that I have needed to write down about using cookies in web applications. Admittedly, I don’t know a lot about cookies and should probably not be considered a source of authority on this topic.

Why cookies?

Making authenticated anchor tags

Can’t specify headers with <a> tags.

Could supply token as query parameter, but that’s a security concern due to potential of token being cached with URL.

No need to manage JWTs within your application

Things that are annoying about JWTs when building frontend applications:

  • You need to choose where to store the JWTs
  • You need to supply the JWT to any code making API requests

How cookies?

Cookies are typically set by backend code after a user successfully logs in. They are typically signed to verify their authenticity. Often, they simply point to an identifier that tracks a user’s “session” within some stateful service (ie database).

How to do cross-origin cookies

  1. Backend must set the access-control-allow-credentials header to instruct browsers that it’s okay to pass credentials when making requests (docs).
  2. Backend must specify the access-control-allow-origin header to instruct browsers which origins are allowed to access the API. Note that you can’t use * when passing credentials between origins (docs).
  3. Backend will need to specify that our cookies have samesite=none if attempting to send cookie to other sites. Note that Same-Site is not the same as Same-Origin, a cookie set with samesite=strict will still be passed between hosts at different subdomains or ports of a domain (docs). Also note that Secure must also be set when samesite=none (docs).
  4. Backend must skip auth checks on preflight requests, as browsers don’t send cookies on OPTIONS requests (docs)
  5. Frontend needs to provide credentials with requests.
    await fetch(url, { credentials: true });