What Are Cookies?
A cookie is a small piece of data stored on the client’s browser, sent by the server. It is used for various purposes like:
- Session management
- Authentication
- Tracking user behavior
Cookies are sent back and forth between the client and server with every request to a domain that set them.
What Is an HttpOnly Cookie?
An HttpOnly cookie is a special type of cookie that cannot be accessed or modified via JavaScript in the browser.
Declared using the HttpOnly attribute:
Set-Cookie: token=abc123; HttpOnly
Key Point:
- Accessible only to the server
- Not accessible to JavaScript
- Helps prevent Cross-Site Scripting (XSS) attacks
Why Use HttpOnly Cookies?
| Problem | How HttpOnly Helps |
|---|---|
| XSS Attack | Prevents JavaScript from stealing cookies |
| Token Theft | Hides tokens from browser JS (e.g., no localStorage) |
| Session Hijacking | Mitigates one of the most common session-related vulnerabilities |
Comparison with Other Storage Options
| Storage | Accessible via JS | Secure by Default | Recommended for Tokens? |
|---|---|---|---|
localStorage | Yes | No | No |
sessionStorage | Yes | No | No |
| HttpOnly Cookie | No | Yes (with Secure flag) | Yes |
Example: Setting an HttpOnly Cookie in Spring Boot
Here’s how you can set an HttpOnly cookie after a successful login in Spring Boot:
Step 1: Return JWT Token as HttpOnly Cookie
@PostMapping("/login")
public ResponseEntity<String> login(@RequestBody LoginRequest request, HttpServletResponse response) {
String jwtToken = jwtService.generateToken(request.getUsername());
Cookie cookie = new Cookie("access_token", jwtToken);
cookie.setHttpOnly(true);
cookie.setSecure(true); // Use HTTPS in production
cookie.setPath("/");
cookie.setMaxAge(60 * 15); // 15 minutes
response.addCookie(cookie);
return ResponseEntity.ok("Login successful");
}
Explanation:
HttpOnly: Makes cookie inaccessible to JS.Secure: Ensures cookie is sent over HTTPS only.Path=/: Available across the whole domain.MaxAge: Sets expiry of the cookie.
How Browser Sends HttpOnly Cookies
Once the server sets a cookie using Set-Cookie header, the browser automatically sends it with every request to that domain:
GET /api/user Host: your-domain.com Cookie: access_token=abc123
- Even if JavaScript cannot see it, the browser sends it.
- This allows seamless authentication for backend APIs.
What Happens If You Try to Read It in JavaScript?
console.log(document.cookie);
- Does not include
HttpOnlycookies - Your app cannot log or modify
access_tokenstored inHttpOnlycookies
React + HttpOnly Cookies Integration
1. React Sends Credentials in Fetch Request
To include cookies in API requests:
fetch("http://localhost:8080/api/data", {
method: "GET",
credentials: "include" // 👈 must be set to include cookies
})
2. Spring Boot Sends JWT as HttpOnly Cookie
Cookie cookie = new Cookie("access_token", jwtToken);
cookie.setHttpOnly(true);
response.addCookie(cookie);
3. Spring Boot Validates the Cookie
@GetMapping("/api/data")
public ResponseEntity<String> getData(@CookieValue("access_token") String token) {
if (jwtService.validateToken(token)) {
return ResponseEntity.ok("Protected data");
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
Best Practices for HttpOnly Cookies
| Practice | Why |
|---|---|
Set HttpOnly | Prevents access from JS (XSS protection) |
Set Secure | Ensures cookie sent only over HTTPS |
| Use short expiration | Limits risk in case of theft |
Set SameSite=Strict or Lax | Mitigates CSRF |
| Rotate tokens | Invalidate and refresh regularly |
Common Misconceptions
| Myth | Reality |
|---|---|
| HttpOnly cookies are 100% safe | They protect from XSS but not from CSRF |
| JavaScript can still read HttpOnly cookies | Not possible |
| They make CSRF impossible | Still need CSRF protection (or use SameSite flags) |
Real-World Use Case
A React frontend uses Keycloak for login:
- Keycloak returns
access_tokenin a secure HttpOnly cookie - React fetches data via APIs without manually handling tokens
- Backend (Spring Boot) extracts and validates JWT from the cookie
- Browser never exposes token to JavaScript → protected from token theft via XSS
Summary
| Feature | HttpOnly Cookie |
|---|---|
| Accessed by JavaScript? | No |
| Sent by browser with request? | Yes |
| XSS-Proof? | Yes |
| CSRF-Proof? | No (use SameSite or CSRF tokens) |
| Best use case | Store access/refresh tokens securely |
| Compatible with React? | Yes (use credentials: "include") |
