OAuth2 & SSO with Spring Security
AdvancedSpring Security OAuth2 Client enables "Login with Google/GitHub" and SSO; the resource-server mode protects APIs accepting Bearer tokens from an authorisation server.
Overview
Spring Security provides two distinct OAuth2 integrations: OAuth2 Client (for "Login with Google/GitHub/Okta" and SSO flows) and OAuth2 Resource Server (for protecting APIs that accept Bearer tokens). The Client integration handles the Authorization Code flow — redirecting users to the provider, exchanging the code for tokens, and populating the SecurityContext with an authenticated principal. The Resource Server integration validates incoming JWT Bearer tokens using a public key or JWKS endpoint from the authorisation server. Spring Boot auto-configures both through spring-security-oauth2-client and spring-security-oauth2-resource-server starters.
OAuth2 Login (Authorization Code flow) for SSO
Add the spring-boot-starter-oauth2-client dependency and configure the client registration in application.yml. Spring Security auto-configures the login endpoint, callback URL, and UserInfo endpoint integration. For Google and GitHub, Spring ships pre-configured CommonOAuth2Provider entries — you only need the client-id and client-secret.
# application.yml — Google OAuth2 login
spring:
security:
oauth2:
client:
registration:
google:
client-id: ${GOOGLE_CLIENT_ID}
client-secret: ${GOOGLE_CLIENT_SECRET}
scope: openid,email,profile
github:
client-id: ${GITHUB_CLIENT_ID}
client-secret: ${GITHUB_CLIENT_SECRET}
scope: user:email
# Security config — allow OAuth2 login
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/login", "/error").permitAll()
.anyRequest().authenticated())
.oauth2Login(oauth2 -> oauth2
.defaultSuccessUrl("/dashboard", true)
.failureUrl("/login?error"))
.build();
}
}OAuth2 Resource Server — protecting APIs with JWT
The Resource Server validates incoming Bearer tokens using the authorisation server's JWKS (JSON Web Key Set) endpoint. Spring Security fetches public keys automatically and verifies token signature, issuer, and expiry. Use @PreAuthorize with hasAuthority() to check JWT scopes/claims for fine-grained access control.
# application.yml — JWT resource server
spring:
security:
oauth2:
resourceserver:
jwt:
jwks-uri: https://auth.example.com/.well-known/jwks.json
issuer-uri: https://auth.example.com
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class ResourceServerConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/health").permitAll()
.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtConverter())))
.sessionManagement(s -> s.sessionCreationPolicy(STATELESS))
.csrf(AbstractHttpConfigurer::disable)
.build();
}
@Bean
public JwtAuthenticationConverter jwtConverter() {
JwtGrantedAuthoritiesConverter converter = new JwtGrantedAuthoritiesConverter();
converter.setAuthoritiesClaimName("roles"); // custom claim name
converter.setAuthorityPrefix("ROLE_");
JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter();
jwtConverter.setJwtGrantedAuthoritiesConverter(converter);
return jwtConverter;
}
}
// Method security using JWT scopes
@RestController
public class OrderController {
@GetMapping("/orders")
@PreAuthorize("hasAuthority('ROLE_USER')")
public List<Order> getOrders() { ... }
@DeleteMapping("/orders/{id}")
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
public void deleteOrder(@PathVariable Long id) { ... }
}OAuth2 Client Credentials flow for service-to-service
Machine-to-machine calls use the Client Credentials grant — no user login involved. Spring Security's OAuth2AuthorizedClientManager + OAuth2AuthorizedClientInterceptor automatically fetches and caches tokens, refreshing them before expiry. Configure a registration with authorization-grant-type=client_credentials.
# application.yml — client credentials for service-to-service
spring:
security:
oauth2:
client:
registration:
inventory-service:
client-id: ${SERVICE_CLIENT_ID}
client-secret: ${SERVICE_CLIENT_SECRET}
authorization-grant-type: client_credentials
scope: inventory.read,inventory.write
provider:
inventory-service:
token-uri: https://auth.example.com/oauth2/token
// Auto-refresh-aware RestClient/WebClient
@Bean
public WebClient inventoryWebClient(OAuth2AuthorizedClientManager manager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(manager);
oauth2.setDefaultClientRegistrationId("inventory-service");
return WebClient.builder()
.baseUrl("http://inventory-service")
.apply(oauth2.oauth2Configuration())
.build();
}
// Token is fetched automatically; refreshed when expired
public InventoryResponse getStock(String productId) {
return webClient.get()
.uri("/stock/{id}", productId)
.retrieve()
.bodyToMono(InventoryResponse.class)
.block();
}Key Points to Remember
- 1OAuth2 Client handles "Login with Google/GitHub" SSO via Authorization Code flow; Resource Server validates incoming JWTs
- 2spring-security-oauth2-client auto-configures CommonOAuth2Provider for Google, GitHub, Facebook, Okta
- 3Resource Server uses JWKS endpoint to fetch public keys and verify JWT signatures without storing them locally
- 4JwtAuthenticationConverter maps custom claims (roles, scopes) to Spring Security GrantedAuthority objects
- 5Client Credentials grant is for machine-to-machine; OAuth2AuthorizedClientManager caches and auto-refreshes tokens
- 6Stateless JWT resource servers must disable CSRF and session creation (SessionCreationPolicy.STATELESS)
Interview Questions
Sign in to ask AriaWhat is the difference between OAuth2 Client and OAuth2 Resource Server in Spring Security?
How does a Spring Boot Resource Server validate a JWT token without calling the auth server on every request?
What is the Client Credentials grant and when would you use it over Authorization Code?
How would you extract custom claims from a JWT and use them as Spring Security roles?
How would you implement JWT revocation when tokens are stateless and resource servers do not call the auth server?
Ask Aria about OAuth2 & SSO with Spring Security
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.