DEV Community

Cover image for HTTP Cookies Demystified: A Web Developer's Guide
Ahmed Hinedy
Ahmed Hinedy

Posted on

HTTP Cookies Demystified: A Web Developer's Guide

Understanding HTTP Cookies in Web Development

In this article, we'll explore the ins and outs of HTTP cookies, their significance in web development, and how they compare to alternatives like localStorage. Whether you're new to web development or looking to refine your skills, understanding cookies is key to building robust, efficient, and secure web applications.

HTTP cookies are small pieces of data stored on a user's device by the web browser that can be used for managing user sessions, tracking user behavior, and enhancing the overall user experience.

Cookies are regular headers. On a Request, they are stored in the Cookie header. On a Response they are in the Set-Cookie header

Cookies vs localStorage

When it comes to client-side storage, developers often choose between cookies and localStorage. Let's compare these options:

Localstorage is designed to be accessible by javascript, which makes it convenient for storing client-side data. However, this accessibility comes with a significant drawback: it doesn't provide any protection against Cross-Site Scripting (XSS) attacks. There are multiple ways an attacker could exploit an XSS vulnerability to access data stored in localStorage.

On the other hand, cookies have security flags that make them more secure for storing sensitive data:

  • HttpOnly flag prevents client-side JavaScript from accessing the cookie, mitigating XSS risks.
  • Secure flag ensures that the browser only transfers the cookie over SSL, protecting against man-in-the-middle attacks.
  • SameSite flag helps prevent Cross-Site Request Forgery (CSRF) attacks by ensuring that the cookie is only sent to the origin site.

So cookies are a more secure choice for storing authentication data. However, localStorage can be more appropriate for storing non-sensitive client-side data like user preferences or cached content.localStorage offers larger storage capacity (usually 5-10MB compared to 4KB for cookies) and easier JavaScript access, making it suitable for improving application performance and user experience in scenarios where the enhanced security of cookies isn't necessary.

How does Cookies Work

cookies between client and server

  1. Setting the Cookie: When a user visits a website, the backend server can send a cookie to the browser. This is done via the Set-Cookie header in the HTTP response.
  2. Storing the Cookie: The browser automatically stores these cookies. As a developer, you don't need to write any client-side code to save the cookie.
  3. Accessing Cookies: On the client side, you can access some of the cookies (not **HttpsOnly) using document.cookie. For example:

    console.log(document.cookie);
    // Output: "username=John Doe; session_id=1234567890"
    
  4. Sending Cookies: The browser automatically sends all relevant cookies (based on domain and path) with every request to the server. This includes regular page loads, AJAX calls, and resource requests like images or scripts from the same domain.

However, there's an important exception to note: cookies are not automatically sent with cross-origin POST requests. To include cookies with cross-origin requests, you need to enable the withCredentials option in your client-side API request headers, as shown

axios.post('https://api.example.com/data', {
  key: 'value'
}, {
  withCredentials: true 
})
.then(response => console.log(response))
.catch(error => console.error('Error:', error));
Enter fullscreen mode Exit fullscreen mode

Keep in mind that this requires the server to respond with the appropriate CORS headers, including Access-Control-Allow-Credentials: true. If the server does not allow credentials, the browser will still prevent the inclusion of cookies, even if you set withCredentials: true on the client side.

Cookie Attributes

Cookies can have various attributes that control their behavior:

  • Expires: Determines how long the cookie should last.
  • Domain: Specifies which domains the cookie is valid for.
  • Path: Limits the cookie to a specific path on the server.
  • Secure: Ensures the cookie is only sent over HTTPS.
  • HttpOnly: Prevents JavaScript from accessing the cookie.
  • SameSite: Controls how the cookie is sent with cross-site requests.

IETF Standards provide the definitive guide to cookies.
Learn more.

Setting Cookies

The method of setting a cookie depends on the context:

HTTP Headers

This is the common server-side approach. Servers send a Set-Cookie header in the response, containing cookie details such as name, value, and various attributes like expiry time and domain. This is typically done in server-side languages like PHP, Python, or JavaScript(Express).

app.get('/set-cookie', (req, res) => {
  res.setHeader('Set-Cookie', [
    'user=John; HttpOnly; Secure; SameSite=Strict',
    'session=1234567890; HttpOnly; Secure; SameSite=Strict; Max-Age=3600'
  ]);
  res.send('Cookies are set');
});
Enter fullscreen mode Exit fullscreen mode

JavaScript

JavaScript, through the document.cookie property, allows you to set cookies directly on the client-side.

 document.cookie = "username=John Doe; expires=Thu, 18 Dec 2023 12:00:00 UTC; path=/";
Enter fullscreen mode Exit fullscreen mode

However, this approach has limitations as it cannot set certain attributes like HttpOnly which are crucial for security.

You can refer to MDN's Extensive documentation on cookies for more details and examples.

Top comments (3)

Collapse
 
anitabrown profile image
Anita Osagie

Nice article, very informative

Collapse
 
omar_elghazaly_192905ae6f profile image
Omar Elghazaly

A great insightful article!

Collapse
 
mahmod_jwily_e400fa89b147 profile image
mahmod jwily

You're very helpful; thank you so much for this excellent explanation.