How to set Cookies and their attributes

How to set Cookies and their attributes

In this article, we are going to talk about cookies! What are they, how they came to be and their attributes.

To understand cookies we need to know a little history about the protocol behind it, HTTP. HTTP is a stateless protocol, which means it doesn’t differentiate between the users. It’s a simple request and response protocol.

First Website.jpg

See this website above, notice the distinct lack of CSS and JavaScript? I can almost hear the front end dev and designers’ screams. Yeah that’s all HTTP was meant to do but as the internet grew, one of the features needed was for websites to behave differently based on who was using it. A simple example being the website greeting you with your name when you open it and this is where cookies come in.

Cookies

So we needed a way for the servers to know who is visiting the website. i.e. make HTTP stateful without modifying the HTTP protocol due to backwards compatibility. So the problem was "how to make HTTP stateful without making it stateful?"

The solution? The server gives the client some data that uniquely identifies the client and the client must send that data with every single request to the server and that’s what we now know as cookies.

A cookie is a small piece of data that a server sends to the user's web browser. The browser stores it and send it back with later requests to the same server

Permanent and Session Cookies

When no time is set for the cookie it is removed when the session closes and its called a session cookie. When a time is set it's called a permanent cookie. There are two ways to set the time for a cookie.

  • Expires=<date>: The maximum lifetime of the cookie as an HTTP-date timestamp. This date is relative to the client and not the server.
    Example Set-Cookie: id=Lakshya; Expires=Wed, 21 Jul 2021 07:28:00 GMT

  • Max-Age=<number>: Number of seconds until the cookie expires. A zero or negative number will expire the cookie immediately.
    Example Set-Cookie: id=Lakshya; Max-Age=1564000

This is how your favourite websites implement the 'Remember Me' feature. A cookie is saved in your browser that is sent automatically to the website when you visit.

Domain

Domain=<domain-value>
Host to which the cookie will be sent to and domain cannot be set to a domain other than the domain setting it, wouldn't be nice for a website to be able to mess with your cookies for other websites.
Example Set-Cookie: id=Lakshya; Domain=hasnode.com

If the domain is not defined it defaults to the current URL but doesn't include subdomains but if it is set the subdomains are included. So a cookie without a domain attribute will be sent to hashnode.com but not to dev.hashnode.com but a cookie with domain=hasnode.com is sent to both hashnode.com and dev.hashnode.com

Path

Path=<path-value>
The path to which the cookie will be sent. Most of the time this will be set to / but is useful when you have multiple different apps on the same domain such as hashnode.com/app1 and hashnode.com/app2

The forward slash / character is interpreted as a directory separator, and subdirectories will be matched as well: for Path=/app, /app, /app/home/, and /app/home/HTTP will all match.
Example: Set-Cookie: id=Lakshya; Domain=hasnode.com; Path=/app

Secure

You can access a website in two ways with HTTP and HTTPS. HTTP is a cleartext protocol that means all your data is sent in plaintext to the sever, so anyone in between can read what you are sending and receiving and that's why HTTPS was made. HTTPS encrypts the data between the user and the server.

You can check if you are using HTTPS by looking for a little lock 🔒 in the URL bar or https: in the URL. The secure flag makes sure the cookie is sent only when the connection is encrypted.
Example: Set-Cookie: id=Lakshya; Domain=hasnode.com; Secure

HttpOnly

The name can be a bit misleading. Reading the name we think it makes the cookie be only sent over HTTP and not HTTPS which seems useless, why would you want to send cookies only over plaintext protocol? This is actually not the case.

There is a very common exploit called XSS (Cross-site scripting) using which someone could get access to your cookies. So the HttpOnly flag stops the JavaScript in your browser from accessing the cookie and therefore making it HTTPOnly.
Example: Set-Cookie: id=Lakshya; Domain=hasnode.com; HttpOnly

SameSite

SameSite=<samesite-value>
SameSite controls whether to send cookies when making a request from one site to another. SameSite takes one of three values None, Lax and Strict with Lax becoming the new default.

SameSite is used to stop cross-site request forgery (CSRF) attacks which in simple terms means ticking a user to act on some other site. For example, someone sending you a link to your bank and when you click it, it sends money to them because the cookies are automatically sent with the requests.

Example: Set-Cookie: id=Lakshya; Domain=hasnode.com; SameSite=Strict

References and Further Reading

MDN Web Docs: developer.mozilla.org/en-US/docs/Web/HTTP/H..
XSS and its prevention: portswigger.net/web-security/cross-site-scr..
CSRF: portswigger.net/web-security/csrf

👋 Hey if you liked this article be sure to like it and if you want to read more follow me on Twitter or on Hashnode to get notified when I post new articles.