If you’re building secure APIs, SPAs, or mobile apps, understanding the underlying standards — like OAuth 2.0, OpenID Connect, and SAML — is critical.
Note: This article belongs to Part 2.1: Security Standards in our Application Security series.
In this post, we’ll explore OAuth 2.0, the most widely adopted authorization framework in the modern web. We’ll break down:
- What OAuth 2.0 is and why it exists
- The key flows developers need to know
- Token types and how they work
- How OAuth enables delegated access securely
- Spring Security examples to bring it all together
What Is OAuth 2.0?
OAuth 2.0 is an authorization framework – a security standard you can say. It allows a third-party application to obtain limited access to user resources on another service — without handling the user’s credentials directly.
Think:
“I want to let a calendar app access my Google Calendar — without giving it my Google password.”
It’s based on token issuance and scoped access, and it separates resource owners (users), clients (apps), authorization servers, and resource servers.
Why Not Just Use Login + Roles?
Because modern systems are:
- Distributed (microservices, APIs)
- Multi-client (SPAs, mobile apps, CLI)
- Often integrating third-party access
- Needing secure delegation without trust violation
OAuth solves all this by issuing time-limited, scoped access tokens on behalf of users or systems.
The Core OAuth Roles
Role | Description |
---|---|
Resource Owner | The end user or entity who owns the data |
Client | The application requesting access to the resource |
Authorization Server | The system issuing tokens (e.g., Google, Okta, Auth0) |
Resource Server | The API or service being accessed (e.g., your backend) |
Key OAuth 2.0 Flows
Different flows exist depending on client type, trust level, and user interaction:
1. Authorization Code Flow (With PKCE)
Use Case: Web apps, SPAs, mobile apps
- Redirect-based
- Uses temporary authorization code, exchanged for token
- PKCE secures public clients
Browser → Login Page → Redirect with Code → Backend exchanges code for token
✅ Recommended for most interactive apps
2. Client Credentials Flow
Use Case: Machine-to-machine communication
- No user involved
- Auth server issues token to the client based on client ID + secret
✅ Best for backend services calling other services
3. Refresh Token Flow
Use Case: Token renewal
- Long-lived refresh token used to obtain new access tokens
- Used in combination with Authorization Code flow
4. Device Code Flow
Use Case: CLI apps, smart TVs
- User logs in on a separate device
- Client polls token endpoint
Token Types Explained
🔑 Access Token
- Used to access protected resources
- Usually a JWT or opaque string
- Carries scopes, user ID, roles
🔄 Refresh Token
- Used to obtain a new access token without re-authenticating the user
- Must be stored securely — usually never exposed to browsers
🪪 ID Token (from OpenID Connect)
- Contains user identity (e.g., name, email, sub)
- Meant for client-side identity info, not for API access
✅ Spring Security: OAuth2 Client (Login)
To support OAuth login (Authorization Code Flow with PKCE):
@Configuration
@EnableWebSecurity
public class OAuth2LoginConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login() // Enables OAuth2 login with external IdP
.and()
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
);
return http.build();
}
}
Spring will handle redirects, token exchange, and user session creation via SecurityContext.
✅ Spring Security: OAuth2 Resource Server (API)
To secure a REST API that receives access tokens:
@Configuration
public class ResourceServerConfig {
@Bean
public SecurityFilterChain apiSecurity(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/admin/**").hasAuthority("SCOPE_admin")
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt() // Validates incoming JWTs
);
return http.build();
}
}
Spring will decode JWTs automatically, validate their signature, expiry, issuer, and audience.
🔐 Real-World Delegated Access
Let’s say you’re building a service that posts on behalf of a user to Twitter.
Without OAuth:
- You’d need to ask for the user’s password. Bad idea.
With OAuth:
- The user authenticates with Twitter, and you get an access token scoped to
write:posts
- You never see their password — and Twitter can revoke your token at any time
That’s delegated access done right.
Common Pitfalls
- ❌ Using
id_token
as an access token (they serve different purposes!) - ❌ Forgetting to validate scopes before granting access
- ❌ Storing refresh tokens insecurely (never store in browser localStorage)
- ❌ Not rotating signing keys for JWTs (use JWKs + key rotation policies)
Best Practices for Developers
- Use Authorization Code flow with PKCE for SPAs and mobile apps
- Always validate access tokens on the resource server
- Use short-lived access tokens + refresh tokens
- Validate token claims (issuer, audience, scope, expiry)
- Never rely on frontend-only logic for authorization
Conclusion
OAuth 2.0 is the industry standard for secure, scalable, and flexible authorization. Whether you’re securing APIs, building user login flows, or enabling third-party access to data, OAuth provides the tools to do it safely — without compromising user trust.
Spring Security offers excellent support for both OAuth clients and resource servers, making it easy to integrate secure token-based workflows into your applications.
Check out https://spring.io/projects/spring-security and https://en.wikipedia.org/wiki/Spring_Security Wikipedia links for more information on the current topic.
What’s Next
Up Next in our Application Security Series is:
Part 2.2 👉 OpenID Connect in Spring Security: Login, ID Tokens & Best Practices
We’ll dive into OpenID Connect: Turning OAuth into a Login System
- How OIDC builds on OAuth2
- How to use
id_token
safely - Adding OIDC login to your Spring Boot app
Have a Question?
OAuth can be confusing at first — especially with all the flows and tokens involved. If you’re working through a real implementation or unsure how to apply it to your project, drop a comment or send a message. Happy to help!