Skip to main content

πŸ‘‰ Unlocking JWT Security: A Deep Dive into Token Validation in Spring Boot

Hi πŸ‘‹, I’m Anandharaj.


Today’s Learnings : JWT Token Validation in Spring Security

πŸ”Ή Always Spring Security gives confusion to me.
So I’m sharing my learnings on how a JWT token is validated when a request comes in.



🌍 What happens when a request comes in?

1️⃣ Incoming request with a token
When a request hits your API, Spring Security’s filter chain intercepts it and extracts the token from the Authorization header (usually in the format: Bearer <token>).

2️⃣ Check token type
The filter checks if it’s a Bearer token and then hands it over to a configured JWT decoder.


πŸ”Ž JWT Structure

A JWT has three parts, separated by dots (.):

  • Header πŸ‘‰ contains metadata (e.g., algorithm: HS256, RS256)

  • Payload πŸ‘‰ contains claims (user info, expiry time, issuer, audience, etc.)

  • Signature πŸ‘‰ ensures integrity and authenticity

πŸ‘‰ Header and Payload are Base64URL‑encoded and readable.
πŸ‘‰ Signature is cryptographically generated and cannot be reverse‑engineered.




πŸ›  How Spring validates a JWT

✔️ Step 1: Decoder setup
When your Spring Boot app starts, it uses a configured JwtDecoder.

For example:


.oauth2ResourceServer(oauth2 -> { oauth2.jwt(jwt -> { jwt.decoder(jwtDecoder); }); });
  • The JwtDecoder is initialized with trusted details (like public keys or JWK Set URIs) from your identity provider.

  • These details are usually cached by Spring for performance.


✔️ Step 2: Validation process

When a token arrives:

  • Header & Payload validation:
    The decoder checks claims like exp (expiry), iss (issuer), aud (audience) against the trusted configuration.

  • Signature validation:
    Using the public key (fetched from the trusted issuer during app startup), Spring recalculates the signature from the header and payload and compares it with the signature part of the token.

✅ If everything matches, the token is valid.


❌ If not, access is denied.



πŸ’‘ Key Takeaways

✅ Always configure a JwtDecoder that matches the way your tokens are generated (e.g., RS256 → use a JWK set URI from your identity provider).


✅ Remember the three parts of a JWT – only header and payload are human-readable; the signature is cryptographically protected.


✅ Spring Security handles this flow through its filter chain and caching, so you rarely need to manually decode tokens.



πŸ–₯ Bonus Tip

If you want to inspect a token manually, try https://jwt.io.
Paste your token, and you’ll see the header, payload, and whether the signature is verified (see my screenshot above).


✍️ This was a quick note from my daily learnings.


If you’ve struggled with JWT validation, hope this helps you understand the flow better! πŸš€


Comments

Popular posts from this blog

🐱 Tomcat vs ⚡ Netty – Which One Should You Use?

🐱 Tomcat vs ⚡ Netty – Which One Should You Use? So recently I got curious about this too πŸ€”. Everywhere in Spring Boot tutorials we see Tomcat . Then suddenly while exploring Spring WebFlux , the name Netty pops up. And I was like – “Wait, who’s this Netty guy trying to replace Tomcat?” πŸ˜… Let’s break it down with real-time examples , icons , and fun comparisons . 🐱 Tomcat – The Traditional Web Server Type: Servlet Container (blocking I/O) World: Used with Spring MVC Style: Thread-per-request model πŸ‘©‍πŸ’» Pros: Stable, widely used, battle-tested Cons: Struggles with huge concurrent connections πŸ‘‰ Example in real life: Tomcat is like a restaurant with fixed waiters 🍴. - Each customer = one thread/waiter - If too many customers come in at once → waiters run out → customers wait outside πŸšͺ ⚡ Netty – The Reactive Rockstar Type: Asynchronous Event-Driven Network Framework World: Default for Spring WebFlux Style: Event-lo...

🎭 Spring’s Secret: Why @Transactional & Friends Betray You Silently

πŸ’‘ Lesson Learned — Not a Prod Bug, But a Real Pain No, this wasn’t a production outage. Nobody screamed at me. But I sat for 3 hours wondering: “Why the heck is my @Transactional not rolling back!?” 😡‍πŸ’« “Why is Redis cache not working?” 🀯 Turned out, the issue was one silent villain: 🧱 Self-invocation 🀷 What Is @Transactional ? If you're new: @Transactional = Tells Spring to start a DB transaction when a method is called. It’ll commit if everything’s okay. It’ll rollback if something fails. 🧠 Think of it like wrapping your code in: try { beginTransaction(); // your logic commit(); } catch(Exception e) { rollback(); } πŸ•΅️ Real-Life Analogy — The Gateway Community 🏘️ Let me tell you about my society — it has a strict watchman at the gate. Here’s how it works: πŸ›‚ Watchman = Spring Proxy 🏠 Your apartment = Your service class πŸšͺ Your room = A method inside that class πŸƒ Scenario 1: Outsider Visits Your friend from outside...

🧡 Virtual Threads in Java — The Ultimate Guide with Diagrams, Code & Interview Qs!

πŸš€ “How are Virtual Threads different from Thread Pools?” 😡 “Are they OS threads or JVM threads?” πŸ™ƒ “Should I still use CompletableFuture?” 🀯 “How do I even use them in real-time microservices?” 🧠 What are Virtual Threads? Virtual Threads (introduced in Java 21 as stable πŸŽ‰) are lightweight threads managed by the JVM instead of the OS kernel. πŸ‘‰ They look like normal threads, but don’t hog OS resources like traditional threads. 🧠 What is the OS Kernel? πŸ›️ OS Kernel = The Brain of the Operating System It’s the core part of your OS (Windows, Linux, Mac) that: Manages memory 🧠 Schedules threads πŸ•’ Talks to hardware πŸ’» Handles I/O operations πŸ“¨ When you create a traditional thread in Java, the JVM asks the OS Kernel to create a real OS-level thread. πŸ–Ό️ Imagine This... ┌───────────────────────────┐ │ Your Java Application │ └────────────┬──────────────┘ │ ...