Securing APIs with Spring Security & JWT
A JWT moves the session into the token itself — which buys you scale and hands you a new set of ways to get it wrong.

Traditional web login keeps a session on the server. You log in, the server remembers you, and your browser carries a session cookie that points back to that memory. It works fine for one server talking to a browser. It fits an API badly. APIs get called by many kinds of client and scaled across many server instances, and a server-side session means every one of those instances has to share or look up that state. JWT authentication exists, more or less, to let the server forget.
What a JWT actually is
A JSON Web Token is a self-contained, signed statement of who you are. When you log in, the server hands you a token that encodes your identity and a few claims, signed with a secret only the server knows. On every request after that you send the token back — in the Authorization header, prefixed with "Bearer" — and the server verifies the signature before trusting it. The load-bearing word is self-contained: the server doesn't look you up in a session store, it reads you out of the token and confirms the signature hasn't been tampered with. No server-side state. That's the whole trick, and the whole payoff — any instance can validate any token, so you scale horizontally without sharing sessions.
Where it plugs into Spring Security
In Spring Security terms you're adding a filter to the chain, typically a JwtAuthenticationFilter extending OncePerRequestFilter. Its one job: pull the token from the Authorization header, validate it, and if it checks out, set the authenticated identity into the SecurityContext — exactly where the earlier posts said the rest of the app reads it from. You also tell Spring Security the session policy is stateless: don't create sessions, there's nothing to keep. Slot that filter in ahead of the usual username-and-password filter, and everything downstream — your URL rules, your @PreAuthorize checks — keeps working unchanged, because they only care that someone is authenticated, not how it happened.
The part where people cut themselves
Here's where I get cautious, because JWT is easy to implement and easy to implement badly. A few rules are non-negotiable. First: a JWT is signed, not encrypted. Anyone who intercepts it can read every claim inside, so it travels over HTTPS, always, and you never put secrets in the payload. Second: verify more than the signature. A valid signature only tells you the token wasn't altered; you still check it hasn't expired, and ideally that the issuer and audience are what you expect. Third: keep tokens short-lived. The awkward truth of stateless auth is that you can't easily revoke a token you never stored — a stolen one stays valid until it expires. Short lifetimes plus a separate refresh token is the standard answer: the access token dies in minutes, and you mint a new one using the longer-lived refresh token.
Notice, too, that the CSRF picture flips. Session cookies need CSRF protection; a token you attach explicitly in a header does not, which is why JWT setups switch off the CSRF machinery a cookie-based app depends on. That's not a shortcut — it's a genuinely different threat model.
The trade, stated plainly
JWT is a real fit for APIs, and it is not free. You trade the server's ability to revoke a session instantly for the ability to scale without holding one. That trade is usually right for a public API and usually wrong for a bank's admin console, where being able to kill a session this second matters more than horizontal scale. Knowing which situation you're in — and respecting the HTTPS, expiry, and refresh rules that keep the stateless model honest — is most of the job.






