HTTP Cookies
An HTTP Cookie is a small, client-side dataset that contains information sent by the server. Also known as a web cookie, browser cookie, or internet cookie, it can be used to identify a client and acts as a way to maintain information about the client’s state in an otherwise stateless system.
Usage
When the client stores data associated with a cookie, it is typically in a small file. The data is sent back to the server to identify the client, and can normally be relied upon to indicate that subsequent HTTP requests are coming from the same browser.
A cookie is generally used for three things:
Tracking cookies are used to build and maintain a browsing history for a client on a particular browser.
Authentication cookies can be used to keep state-related information about a user that is currently logged in to the server. This type of cookie stores information about the user's account that can be used to continue a session. Without it, the user will have to re-authenticate each time a HTTP request is made.
Preferences can be stored for the benefit of improving the user’s experience. For example, having a light or dark mode for a web page is user-specified customization that can persist between HTTP sessions.
Creation and storage
When a server receives an HTTP request, it can optionally return the Set-Cookie response header field to instruct the browser to store the data. Multiple Set-Cookie headers can be used to store more than one piece of data using only one response.
Cookies can also include certain prefixes and attributes that further specify how they can be used and how long they last. For example, a cookie can include details on which domains can receive it, as well as an expiry date that specifies a time after which it is expected to no longer be sent.
Persistence
The data in a cookie is generally persistent and the lifetime can be specified by the server. A session cookie is deleted when the HTTP session is completed, and this is governed by the client’s browser. The server can also ask the client to create a permanent cookie, which includes the Expires
attribute as part of the response to inform the client as to when the cookie data is expected to no longer be sent.
Note
Expiry dates are relative to the client, as opposed to the server.
The Max-Age
attribute is another way for the server to time-limit a cookie. The value is the number of seconds until the cookie expires. If both Expires and Max-Age
attributes are set then the Expires
is ignored and the Max-Age
dictates the expiry date. If neither one is set then the cookie is not persistent and will expire as soon as the current HTTP session ends.
Note
Browsers may choose to cap the maximum value for the max-age
attribute to 400 days. This is close to 13 months, allowing for sites visited roughly once a year by users to keep working, e.g. reporting the yearly utilities usage through the utility-company's website.
While permanent cookies can be available for quite some time, internet browsers offer functionality for clearing cookies from the system. Also, browsers generally have options like Google Chrome’s Incognito Mode, which does not store information related to a user’s HTTP session, including maintaining cookies after the HTTP session is completed.
First-party vs third-party cookies
Cookies and their accompanying data are associated with a domain. If the domain matches the server hosting the resource from which it was set, then it is a first-party cookie. If on the other hand, the domain is different, it is a third-party cookie. Examples of the latter are advertising banners visible on a web page. They are displayed in one domain but hosted in another. Third-party cookies are typically used for web usage tracking and advertising. Servers can optionally use the SameSite
attribute to inform clients whether cookies can be sent to third-party sites.
CORS support and the SameSite attribute
Cookies are supported by the cross-origin resource sharing (CORS) protocol through the SameSite
attribute. This is intended to offer protection against cross-site request forgery (CSRF) attacks and there are three options:
Lax: This is the default value and specifies that the cookie will be restricted to a limited number of requests. The cookie will be sent if it is a safe HTTP request, such as a top-level HTTP GET or HEAD. A top-level request is an address that is entered into the navigation bar on a browser, or when a user clicks on a link that visibly changes the domain name in the bar.
Strict: This stipulates that the cookie will only be sent to the originating site. It will not be sent with any cross-domain requests, regardless of the HTTP method.
None: Specifying this will mean that cookies will be sent, regardless of the HTTP method, to the cross-origin site.
Although the Strict setting is the most preventative against CSRF attacks by malicious websites, some popular functionality no longer works as a result. In these cases, setting SameSite
to Lax
is often a reasonable alternative.
Domain restriction
As cookies originate from a specific site or domain, it is reasonable that only that domain receives the data back from the client. By default, the value is assumed to be the same host that created the cookie, excluding subdomains. Optionally, the scope can be expanded to include other areas of the server.
For example, if the server that sent the cookie is www.example.re, then omitting the Domain
header field will mean it will not be sent to a subdomain such as staging.example.re. By specifying the domain, it can be given wider access.
Domain=example.re
By setting the field value to example.re, it makes it available to subdomains such as staging.example.re.
Note
If the scope for the cookie is outside of the domain, such that it does not include the origin server, then the cookie will be rejected. For example, if the server at staging.example.re specifies the domain as example.re then it is valid. However, if the server at staging.example.re specifies the domain as news.example.re then it will be rejected.
Path restriction
Similar to the way that the Domain
attribute can be used to widen the scope that a cookie has, the Path
attribute can be used to further restrict it. The cookies will only be sent when the specified path is included in the URL.
Path=/news/
If this attribute were included then access is available for the top-level news path, as well as for any directory below it. If it does not exist in the path then the cookie will not be sent. Consult the following table for examples of paths that do and do not match this value.
Path | Match |
---|---|
/news or /news/ | Yes – Exact match |
/news/current | Yes – Valid subdirectory |
/news/current/world | Yes – Valid subdirectory |
/ | No – The root directory is not accessible |
/oldnews | No – Different subdirectory |
Security and restricting access
With cookies having the ability to maintain Authentication information, it is sometimes necessary to safeguard against them being accessed by third parties. There are two attributes, Secure
and HttpOnly
, that can be used to control access. Each is interpreted by the client and directs it to treat the cookie in particular ways.
A cookie with these attributes can be specified in this way:
Set-Cookie: jobid=111; Expires=Sun, 1 Jan 2023 12:00:00 GMT; Secure; HttpOnly
By including the Secure
attribute, it means that cookies will only be sent when HTTP requests are directed to an HTTPS address. Servers or resources that do not support encrypted HTTP requests cannot use this attribute, and by specifying it, browsers will not transmit this cookie over an unsecured HTTP Connection.
The HttpOnly
attribute is used then it cannot be accessed using a client-side script. This prevents attacks that can occur even when CORS is permitted and a malicious website attempts to access the cookie using a script run from a link that the user has clicked on. Given that this option is supported at the browser level, cookies are still accessible by tools that bypass the browser and read the client’s storage facility directly.
Prefixes
In addition to the aforementioned attributes, two prefixes are used to further specify particular details. These are __Host-
and __Secure-
and are accepted by browsers only if they meet certain requirements. The purpose is to keep track of a cookie’s origin since it is often not apparent.
A cookie that is prefixed with __Host-
will only be accepted if it includes the Secure
attribute, does not include a Domain
attribute, has a Path
attribute set to the root directory (i.e. Path=/
), and was sent from a secure origin. With these restrictions in place and verified, the cookie is domain-locked. It must only be sent to the specific domain, not subdomains, and the scope is the entire directory tree.
Set-Cookie: __Host-jobid=111; Secure; Path=/
The __Secure-
prefix is ostensibly weaker than the __Host-
prefix because it is accepted under less strict conditions. It only requires that the cookie includes the Secure
attribute and was sent from a secure origin server.
Set-Cookie: __Secure-jobid=111; Secure; Domain=example.re
Drawbacks
One disadvantage to using cookies is that they are sent with every HTTP request, meaning that duplicate data is regularly and repeatedly sent. This consumes additional bandwidth and depending on the nature of the cookie, unnecessarily so. This is compounded by sites that use several different cookies during a HTTP session.
Regulations
A variety of regulations from different jurisdictions help to govern the use of cookies. Examples of these include the General Data Protection Regulation (GDPR) for the European Union and the California Consumer Privacy Act (CCPA). These and other regulations generally ensure that people are informed as to what information about them is being collected, it gives them the option to opt-out of or delete the associated cookies, and allows clients to use the majority of the services of a website even if cookies are rejected.
Example
In this example, the server includes several cookies for the client to store. In subsequent HTTP requests, the client sends all of the cookies back to the server using the Cookie request header field. The two exceptions are screenmode, which will not be sent after January 1st, 2023, and job, which will only be sent for the next hour.
Response
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length:
Set-Cookie: items=16
Set-Cookie: headercolor=blue
Set-Cookie: footercolor=green
Set-Cookie: screenmode=dark, Expires=Sun, 1 Jan 2023 12:00:00 GMT
Set-Cookie: job=111; Max-Age: 3600; Secure; HttpOnly
Request (shortly after)
GET / HTTP/1.1
Host: www.example.re
Cookie: items=16; headercolor=blue; screenmode=dark; job=111
Request (more than an hour later but before January 1st, 2023)
GET / HTTP/1.1
Host: www.example.re
Cookie: items=16; headercolor=blue; screenmode=dark
Takeaway
HTTP Cookies are a mechanism that servers have for storing data on a client, typically used to identify them during subsequent HTTP requests. This allows for the concept of maintaining a state in an otherwise stateless environment. Different attributes are used to keep cookies secure, including options to prevent them from being sent to different domains and having them expire. Popular uses for cookies are in web-tracking applications and as such, a variety of regulations exist to restrict their use.