Mastering Spring Security OAuth 2: Your Comprehensive Series Guide





Spring Security OAuth2 Roadmap (The Stuff That Actually Matters) | www.codegigs.app





Spring Security OAuth2 Roadmap (Stop Reading the RFCs)

I distinctly remember the first time I tried to implement OAuth2. I read the RFC spec. I read the Spring docs. I cried a little bit. Then I copy-pasted some code from a 4-year-old tutorial and prayed.

It didn’t work.

At www.codegigs.app, OAuth is the #1 topic developers ask me about. Why? Because the ecosystem is a mess of deprecated projects (RIP Spring Security OAuth) and confusing terminology.

If you’re trying to figure out if you need an Authorization Server, a Resource Server, or just a Client, this guide is for you. No fluff, just the architecture you actually need.

Step 1: The Mental Model (Forget the Buzzwords)

Before you write a single line of code, you need to know what you’re building. Most developers overcomplicate this.

OAuth 2.0 is just about access. It’s giving your app a key (token) to open a door (API) without giving it the master password.

OpenID Connect (OIDC) is about identity. It’s a layer on top of OAuth that says “Okay, you have the key, but who are you?”

Here is the only thing that matters. You will build one of three things:

  1. Client: The app the user clicks “Login” on. (e.g., your React app or Spring MVC app).
  2. Resource Server: The API that holds the data. It checks the token. (e.g., your Spring Boot REST API).
  3. Authorization Server: The thing that issues the token. (e.g., Keycloak, Auth0, or Spring Authorization Server).

If you just want to let users log in with Google, you are building a Client. If you are protecting your API, you are building a Resource Server. Do NOT build an Authorization Server unless you absolutely have to.

Step 2: The “Login with X” Flow (The Easy Win)

This is where everyone starts. You want users to sign in via GitHub or Google. In Spring Boot 3, this is shockingly easy.

We cover this extensively in our Azure AD Authentication Guide, but here is the gist:

// SecurityConfig.java
// Spring Boot 3.2+
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            )
            // This one line enables the entire OAuth2 login flow
            // It handles the redirect, the code exchange, everything.
            .oauth2Login(withDefaults());
            
        return http.build();
    }
}

You pair this with your properties file:

spring:
  security:
    oauth2:
      client:
        registration:
          github:
            client-id: ${GITHUB_CLIENT_ID}
            client-secret: ${GITHUB_CLIENT_SECRET}

That’s it. Spring Boot sees those properties, spins up an OAuth2LoginAuthenticationFilter, and does the heavy lifting. No custom controllers needed.

Step 3: Protecting Your API (The Resource Server)

This is where most microservices live. You aren’t handling logins; you’re just verifying tokens sent in the Authorization: Bearer [token] header.

I used to write custom filters to parse JWTs manually. Don’t do that. Spring Security 6 has a built-in JWT decoder that connects to the provider’s JWK Set URI (the public keys) automatically.

// ApiSecurityConfig.java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/api/public").permitAll()
            .requestMatchers("/api/admin/**").hasAuthority("SCOPE_admin")
            .anyRequest().authenticated()
        )
        // This makes your app a Resource Server
        // It validates the signature and expiration automatically
        .oauth2ResourceServer(oauth2 -> oauth2
            .jwt(withDefaults())
        );
        
    return http.build();
}

The tricky part here is handling roles. By default, Spring maps scopes to authorities (e.g., SCOPE_read). If you need to map complex roles from Keycloak or Azure, you’ll need a custom converter.

We detail exactly how to extract these roles in our lesson on Granted Authority vs Roles.

Step 4: The Boss Fight (Spring Authorization Server)

Okay, so you don’t want to use Auth0 or Keycloak. You want to be the bank. You want to issue the tokens yourself.

Enter Spring Authorization Server (SAS). This project replaces the legacy “Spring Security OAuth” project. It is strictly compliant with the specs, which means it doesn’t support “hacky” non-standard flows like Password Grant.

Here is what a minimal setup looks like. Warning: It’s heavy.

// AuthorizationServerConfig.java
// This is just a snippet - the full setup requires 5+ beans
@Bean 
public RegisteredClientRepository registeredClientRepository() {
    RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
        .clientId("my-client")
        .clientSecret("{noop}secret")
        .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
        .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
        .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
        .redirectUri("http://127.0.0.1:8080/login/oauth2/code/my-client")
        .scope(OidcScopes.OPENID)
        .scope("message.read")
        .build();

    return new InMemoryRegisteredClientRepository(registeredClient);
}

SAS requires you to configure the RegisteredClientRepository, the JWKSource (for signing keys), and specific filter chains for the protocol endpoints. It is not for the faint of heart.

If you are building this, check out our guide on Securing Applications with SSL, because you cannot run an Auth Server over HTTP in production. Browsers will block the secure cookies.

Building an Auth Server is Hard.

I’ve spent months debugging Spring Authorization Server so you don’t have to.

Join 50,000+ developers in the full Spring Security course at www.codegigs.app.

Start the Master Class

Step 5: Advanced Real-World Stuff

Once you have the basics, reality hits. Here are the patterns that trip people up:

Token Relay in Microservices

So you have Service A calling Service B. Great. How does B know who the user is? You need the Token Relay Pattern. Spring Cloud Gateway creates a bridge here, taking the OAuth2 token from the client and forwarding it downstream.

Testing (The Actual Nightmare)

How do you test a controller that expects a JWT without spinning up a full Keycloak instance? Use @WithMockJwt (part of spring-security-test).

@Test
@WithMockJwt(authorities = {"SCOPE_message:read"})
void whenAuthorized_thenSuccess() {
    webTestClient.get().uri("/api/messages")
        .exchange()
        .expectStatus().isOk();
}

We discuss testing strategies more in our Basic Authentication Guide, comparing simple mocks vs full integration tests.

Summary: Your Next Steps

Don’t try to learn all of OAuth2 at once. Pick your lane:

  • Need to login users? Use oauth2-client.
  • Need to secure an API? Use oauth2-resource-server.
  • Need to manage users? Try Keycloak first. Only build a Spring Authorization Server if you have very specific customization needs.

This series covers every single one of these steps in detail. If you’re ready to start building, jump into the next lesson on Securing APIs.


Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top