All posts
Spring BootSecurityOAuth2

Securing Spring Boot APIs with OAuth2 and JWT: A Practical Guide

· Samir Gautam

Most "secure" Spring Boot APIs I get called in to fix aren't actually broken — they're just built on a security model nobody fully understood. Here's the pattern I use by default, and why each piece is there.

Why OAuth2 + JWT, not sessions

Session-based auth is fine for a single monolith. The moment you have more than one service — a mobile app, a partner API, a background worker — shared session state becomes a coordination problem. A signed JWT carries its own proof of identity, so any service can verify a request without calling back to a central session store.

The shape of it

  • Authorization Server issues short-lived access tokens (I default to 15 minutes) and longer-lived refresh tokens.
  • Resource Server (your Spring Boot API) validates the JWT signature and scopes on every request — no database lookup needed for auth itself.
  • Spring Security's OAuth2ResourceServerConfigurer does most of the heavy lifting once you point it at your issuer's JWK set.
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
      .authorizeHttpRequests(auth -> auth
        .requestMatchers("/api/public/**").permitAll()
        .requestMatchers("/api/admin/**").hasAuthority("SCOPE_admin")
        .anyRequest().authenticated())
      .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
    return http.build();
}

Three mistakes I see repeatedly

  1. Long-lived access tokens. If a token leaks, its lifetime is your exposure window. Keep access tokens short and lean on refresh tokens for longevity.
  2. Trusting the JWT payload without checking aud and iss. A valid signature only proves who issued the token — not that it was issued for your API.
  3. No token revocation story. Short expiry buys you most of what you need, but for anything handling payments I also keep a denylist of revoked token IDs in Redis, checked on the hot path.

Where this earns its keep

I built this exact pattern for a fintech client's payment gateway — OAuth2 + JWT securing every transaction endpoint, with idempotent request handling on top so a retried request never double-charges a customer. Getting the auth layer right up front meant the security audit six months later was a formality, not a scramble.

If you're stitching together auth for a Spring Boot service and want a second pair of eyes on the design before you ship it, that's exactly the kind of review I do.

DIRECT CHATWhatsApp