skip to content

Compare CookieHttpSessionIdResolver and HeaderHttpSessionIdResolver. When would you switch from cookies to a header?

level: middleimportance: must knowfreq 55%

answer

  1. HttpSessionIdResolver = how the ID travels
  2. Cookie default: name SESSION, DefaultCookieSerializer
  3. Header: xAuthToken() → X-Auth-Token
  4. Header = client must echo it manually
  5. Non-browser / cross-origin → header

basics

~20 s

An HttpSessionIdResolver decides how the session ID travels between client and server. The cookie resolver (default) uses a Set-Cookie/Cookie. The header resolver reads/writes it in an HTTP header (e.g. X-Auth-Token), which suits non-browser clients like mobile apps or SPAs across domains.

solid answer

~50 s

`HttpSessionIdResolver` is the Spring Session strategy that extracts the session ID from a request and writes it back on the response. `CookieHttpSessionIdResolver` is the default: it uses a cookie (via a `CookieSerializer`, default name `SESSION`) — great for browsers, automatic on every request, and lets you control `HttpOnly`, `Secure`, `SameSite`, and path. `HeaderHttpSessionIdResolver` instead reads the ID from and writes it to an HTTP header, commonly `X-Auth-Token` (there are factory methods `xAuthToken()` and `authenticationInfo()` for the `Authorization` header). You switch to the header resolver for non-browser or cross-origin clients — native mobile apps, or JS clients where cookies are awkward (CORS credentials, third-party-cookie restrictions). The client must then read the header from the login response and echo it on every subsequent request; there's no automatic sending like cookies. You configure it by exposing an `HttpSessionIdResolver` bean.

code

java · 21 lines
java
@Configuration
@EnableRedisHttpSession
public class SessionConfig {

    // Non-browser clients: carry the session id in X-Auth-Token
    @Bean
    public HttpSessionIdResolver httpSessionIdResolver() {
        return HeaderHttpSessionIdResolver.xAuthToken();
    }

    // Alternatively, harden the default cookie resolver:
    // @Bean
    // CookieSerializer cookieSerializer() {
    //     DefaultCookieSerializer s = new DefaultCookieSerializer();
    //     s.setCookieName("SESSION");
    //     s.setUseHttpOnlyCookie(true);
    //     s.setUseSecureCookie(true);
    //     s.setSameSite("Lax");
    //     return s;
    // }
}

go deeper

for a junior

Know that the resolver decides whether the session ID rides in a cookie or a header, and cookie is the default.

for a middle

Name the two implementations, the default cookie name SESSION, xAuthToken(), and when to pick header (mobile/cross-origin).

for a senior

Discuss security trade-offs: HttpOnly/SameSite loss with header, CSRF implications, DefaultCookieSerializer hardening, CORS exposure.

for a principal

Frame the client-contract change, migration strategy across clients, and token-storage/XSS responsibility shift.

## What an HttpSessionIdResolver is Spring Session needs to know two things per request: **how to find the session ID coming in**, and **how to communicate a (new or changed) session ID going out**. That strategy is the `org.springframework.session.web.http.HttpSessionIdResolver` interface, with three methods: - `resolveSessionIds(HttpServletRequest)` → the candidate session IDs on the request - `setSessionId(request, response, id)` → tell the client the current/new ID - `expireSession(request, response)` → instruct the client to drop the ID The `SessionRepositoryFilter` calls the resolver on every request. ## CookieHttpSessionIdResolver (the default) - Transports the ID in an HTTP **cookie**. Serialization/parsing is delegated to a **`CookieSerializer`** — the default is **`DefaultCookieSerializer`**, and the default cookie name is **`SESSION`** (Base64-encoded value), not `JSESSIONID`. - Via `DefaultCookieSerializer` you control the security-relevant attributes: - **`setUseHttpOnlyCookie(true)`** — JS can't read it (XSS mitigation). - **`setUseSecureCookie(true)`** — only sent over HTTPS. - **`setSameSite("Lax"/"Strict"/"None")`** — CSRF / cross-site behavior. `None` requires `Secure`. - **`setCookiePath(...)`, `setDomainName(...)`, `setCookieName(...)`.** - It also supports **cookie-based session-ID rotation** hints and can carry multiple sessions (used by Spring Session's multi-account support). - **Why default:** browsers send cookies automatically on every same-site request, so the app 'just works' with zero client code. ## HeaderHttpSessionIdResolver - Transports the ID in an **HTTP header** instead of a cookie. - Factory methods: - `HeaderHttpSessionIdResolver.xAuthToken()` → header **`X-Auth-Token`**. - `HeaderHttpSessionIdResolver.authenticationInfo()` → header **`Authorization`**. - Or `new HeaderHttpSessionIdResolver("Your-Header")`. - **No automatic transmission:** the client must capture the header from the response (e.g. on login the server sets `X-Auth-Token: <id>`) and **explicitly send it back** on every request. This is a client responsibility. ## When to choose which | Scenario | Resolver | |---|---| | Server-rendered web app / browser | Cookie (default) | | Native mobile app (no cookie jar you want to rely on) | Header | | SPA/API where cookies are painful (CORS credentials, third-party-cookie blocking, multiple origins) | Header | | You need `HttpOnly`/`SameSite`/`Secure` browser protections | Cookie | **Trade-offs of the header approach:** you lose the browser's automatic `HttpOnly`/`SameSite` protections, so the client must store the token safely (and you're now responsible for XSS exposure of that token). CSRF risk changes: header-based IDs aren't sent automatically by the browser, which actually *reduces* CSRF exposure (an attacker's forged request won't carry your custom header), but you take on secure client-side storage. ## How to configure Expose an `HttpSessionIdResolver` bean; Spring Session picks it up. You can only have one active resolver. ## Gotchas - Switching resolver changes the **client contract** — existing browser cookie flows won't send the header, so you can't silently swap in production without updating clients. - With the header resolver, **CORS** must expose the response header (`Access-Control-Expose-Headers`) so JS can read `X-Auth-Token`. - The default cookie name is `SESSION`, a frequent surprise for people expecting `JSESSIONID`.

  • With HeaderHttpSessionIdResolver, how does the client get and use the session ID?
    The server writes it on the response header (e.g. X-Auth-Token) — typically on the first request/login. The client reads and stores it, then sends it back in that header on every subsequent request. Nothing is automatic like cookies.
  • What's the default cookie name Spring Session uses, and how do you harden it?
    SESSION (not JSESSIONID). Harden via a DefaultCookieSerializer bean: setUseHttpOnlyCookie(true), setUseSecureCookie(true), and setSameSite("Lax"/"Strict").

saying these in an interview costs you the question

  • Saying the default cookie is JSESSIONID (Spring Session uses SESSION)
  • Assuming the header resolver auto-sends the ID like a cookie
  • Claiming you can run both resolvers simultaneously
  • Forgetting CORS Access-Control-Expose-Headers is needed for JS to read the header

context