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
HttpOnly
cookies - Your app cannot log or modify
access_token
stored inHttpOnly
cookies
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_token
in 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" ) |