LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 1222 min read

OAuth2 & JWT Dependencies

Cover spring-boot-starter-oauth2-client for social login, spring-boot-starter-oauth2-resource-server for validating JWTs, and jjwt for issuing your own tokens.

Introduction

OAuth2 and JWT solve two related but different problems: OAuth2 client support handles "Login with Google" style flows where a third party proves who your user is, OAuth2 resource server support handles verifying tokens that arrive on incoming API requests, and JWT libraries let your own application issue tokens when you are the one doing the authenticating. This lesson covers all three.

What You Will Learn
  • How spring-boot-starter-oauth2-client enables social login with providers like Google and GitHub.
  • How spring-boot-starter-oauth2-resource-server validates JWT bearer tokens on incoming requests.
  • How to issue your own JWTs with io.jsonwebtoken (jjwt).
  • When each of these three dependencies is the right tool.

OAuth2 Client: Login with Google/GitHub

spring-boot-starter-oauth2-client is for the "Sign in with Google" button. Your application redirects the user to Google, Google authenticates them and asks for consent, and Google redirects back with proof of identity — your app never sees the user's Google password.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
spring.security.oauth2.client.registration.google.client-id=YOUR_CLIENT_ID
spring.security.oauth2.client.registration.google.client-secret=YOUR_CLIENT_SECRET
spring.security.oauth2.client.registration.google.scope=openid,profile,email
@Configuration
@EnableWebSecurity
public class OAuth2LoginConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/login/**").permitAll()
.anyRequest().authenticated()
)
.oauth2Login(Customizer.withDefaults());
return http.build();
}
}
Behavior

Click Run to see what this code prints.

OAuth2 Resource Server: Validating JWTs

spring-boot-starter-oauth2-resource-server is for the other side of the conversation: your API receives a request with an Authorization: Bearer <token> header, and this starter validates that token — checking its signature and expiry — before letting the request through.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://accounts.google.com
@Configuration
@EnableWebSecurity
public class ResourceServerConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
return http.build();
}
}
Behavior

Click Run to see what this code prints.

jjwt: Issuing Your Own Tokens

If you are not delegating to Google or another identity provider and instead want your own login endpoint to hand back a JWT, io.jsonwebtoken (jjwt) is the standard library for creating and parsing tokens. It ships as three artifacts: the API, the implementation, and a Jackson module for JSON serialization.

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.6</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.6</version>
<scope>runtime</scope>
</dependency>
@Service
public class JwtService {
private final SecretKey key = Jwts.SIG.HS256.key().build();
public String generateToken(String username) {
return Jwts.builder()
.subject(username)
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + 3_600_000))
.signWith(key)
.compact();
}
public String extractUsername(String token) {
return Jwts.parser()
.verifyWith(key)
.build()
.parseSignedClaims(token)
.getPayload()
.getSubject();
}
}
Example Token

Click Run to see what this code prints.

Key Storage

The example above generates a new signing key every time the application starts — every previously issued token becomes invalid on restart. In a real application, load the signing key from a fixed secret in configuration (or a secrets manager), never generate it inline.

Which One Do You Need?

DependencyRoleTypical Use Case
spring-boot-starter-oauth2-clientConsumes another provider's login"Login with Google/GitHub" buttons
spring-boot-starter-oauth2-resource-serverValidates incoming tokensProtecting an API with Bearer tokens
io.jsonwebtoken (jjwt)Issues your own tokensA custom login endpoint that returns a JWT

It is common to combine the resource-server starter with jjwt: your own /login endpoint issues a JWT using jjwt, and every other endpoint is protected by the resource-server starter, which validates that same token on the way back in.

Common Mistakes

Avoid These Mistakes
  • Confusing OAuth2 client (logging your app in via Google) with OAuth2 resource server (validating tokens on your own API) — they are opposite ends of very different flows.
  • Storing JWTs in localStorage where they are exposed to XSS, instead of an HttpOnly cookie.
  • Setting no expiration on issued tokens, so a stolen token remains valid forever.
  • Hardcoding a signing key as a literal string instead of loading it from configuration.

Frequently Asked Questions

Yes, jjwt is a plain Java library with no dependency on Spring Security — it works in any Java application that needs to create or read JWTs.

Only if your app both logs users in via an external provider and also exposes an API that other services call with tokens. Many apps only need one.

No — by default a JWT is signed, not encrypted. Anyone can decode and read its payload; the signature only proves it has not been tampered with. Never put secrets in the claims.

Summary

OAuth2 client handles logging your users in through someone else, OAuth2 resource server handles verifying tokens on the way into your API, and jjwt lets you issue tokens yourself when you are the identity provider. Next, we look at validating request data before it ever reaches your business logic.

Next Lesson →

Validation Dependencies