Another Intro for Cookies

Cookies are strings of data that are stored directly in the browser. They are a part of HTTP protocol, defined by RFC 6265 specification.

Cookies are often set by server using the response Set-Cookie HTTP-header. Then, the browser automatically attaches them to every request to the same domain using the request Cookie HTTP-header.

Limitations

  1. The name=value pair, after encodeURIComponent, should not exceed 4KB. So we can not store anything huge in cookie.
  2. The total number of cookies per domain is limited to around 20+, the exact limit depends on the browser.

domain

A domain defines where the cookies are accessible, but in practice though, we can not set any domain within limitations.
By default, a cookie is accessible only the domain that set it. So, if the cookie was set by site.com, we can not get it from other.com, nor can subdomain like forum.site.com by default! That's tricky but a safety restriction to allow us store some how sensitive data in cookies, which be sure that should be available only on one site.

If we'd like to allow subdomains such as forum.site.com to get a cookie, we should explicitly set the domain option to the root domain domain=site.com or the old notation domain=.site.com for very old browsers for historical reasons.

document.cookie = `author=john; domain=.site.com`

path

The url path prefix must be absolute(that starts with /). It makes the cookies accessible for pages under the path. By default, it's the current path.
For example, if a cookie is set with path=/admin, it's visible at pages /admin and /admin/something, but not at / or /home.

Usually, we set path to the root as below, which can be accessed from the whole website.

document.cookie = `author=john; path=/`

Expires and max-age

By default, the so-called session cookies disappear when the browser closes. To let cookies survive from a browser close, we can set either the expires or max-age option.

  • expires, the cookie expiration date defines the time, when the browser will automatically delete it. The date must be exactly in the GMT timezone(like Tue, 19 Jan 2038 03:14:07 GMT), which we can use date.toUTCString to get. For instance, we can set the cookie to expire in a day:

    let date = new Date(Date.now() + 86400e3)
    document.cookie = `author=john; expires=${date.toUTCString()}`

    If we set expires to a date in the past, the cookie is deleted.

  • max-age, is an alternative to expires and specifies the cookie's expiration in seconds from the current moment. If set to zero or a negative value, the cookie is deleted:

    document.cookie = `author=john; max-age=0`

HttpOnly flag

The HttpOnly flag is an optional flag that can be included in a Set-Cookie response header to tell the browser to prevent client side script from accessing the cookie.

The biggest benefit here is protection against XSS(Cross-Site Scripting). If a site has an XSS vulnerability then an attacker could exploit this to steal the cookies of a visitor, essentially taking over their session and logging in the victim's account.

When a piece of JavaScript attempts to read a cookie with the HttpOnly flag set, a empty string will be returned instead of the cookie itself.

Unless you have a specific requirement to access the cookie with client-side script, you should enable this flag.

Secure flag

It instructs the browser that the cookie must only ever be sent over a secure connection. You can see it on the end of this header: Set-Cookie: CookieName=CookieValue; path=/; Secure

Because a session cookie is incredibly sensitive, it should not be sent over an insecure connection as it would be trivial for an attacker to intercept it and abuse it. If you serve your site over HTTPS then you should set this flag on your cookies.

SameSite

The new property SameSite is used to avoid CSRF and user tracking.

There are three options for SameSite

  • Strict, prohibit request along with any cookie belongs to the target website, when the target URL and source are not the same.

    • example: Set-Cookie: CookieName=CookieValue; SameSite=Strict;
    • Downside: To strict to cause when you redirect to GitHub from other site, you will have to login again, even though you have login before. That means all SSO will be unavailable.
  • Lax, as the default option of Chrome. It follows the rules like below

    • link , send cookie
    • pre-render , send cookie
    • GET form
      , send cookie
    • POST form , cookie sending is forbidden
    • iframe