OAuth 2.0 Tutorial with Spring Boot Implementation and Testing
This article introduces OAuth 2.0 concepts, explains its roles and grant types, and provides a complete Spring Boot implementation—including configuration classes, dependency setup, and test endpoints—followed by step‑by‑step testing results with screenshots.
Hello everyone, I am a senior architect.
1. OAuth 2.0 Overview
OAuth 2.0 (Open Authorization 2.0) is an open standard that allows third‑party applications to access protected resources on behalf of a resource owner without sharing the owner's credentials. It is widely used for secure delegation and authentication on the Internet.
The core concepts and workflow of OAuth 2.0 are:
Roles:
Resource Owner: The user who owns the protected resources.
Client: The third‑party application that wants to access the resource owner's protected resources.
Authorization Server: The server that authenticates the resource owner and issues access tokens.
Resource Server: The server that hosts the protected resources; it may be the same as the authorization server or a different one.
Grant Types:
OAuth 2.0 supports four main grant types:
Authorization Code Grant: Commonly used by third‑party login integrations.
Implicit Grant: Does not require a client server; the token is obtained directly in the browser, suitable for pure static pages.
Password Grant: The user provides username and password directly to the client; suitable only when the client is highly trusted.
Client Credentials Grant: The client obtains a token on its own behalf, useful for service‑to‑service communication.
2. Code Setup
2.1 Authorization Server (port 8080)
Import the following Maven dependencies:
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-security
2.2.5.RELEASE
org.springframework.cloud
spring-cloud-starter-oauth2
2.2.5.RELEASEOnly two configuration classes are needed:
MyAuthorizationConfig class
@Configuration
@EnableAuthorizationServer
public class MyAuthorizationConfig extends AuthorizationServerConfigurerAdapter {
/**
* Client storage strategy – using in‑memory for demo.
*/
@Autowired
private ClientDetailsService clientDetailsService;
/**
* Authentication manager needed for password grant.
*/
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()")
.allowFormAuthenticationForClients();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("test")
.secret(new BCryptPasswordEncoder().encode("123456"))
.resourceIds("order")
.authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token")
.scopes("all")
.autoApprove(false)
.redirectUris("http://www.baidu.com");
}
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
@Bean
public AuthorizationServerTokenServices tokenServices() {
DefaultTokenServices services = new DefaultTokenServices();
services.setClientDetailsService(clientDetailsService);
services.setSupportRefreshToken(true);
services.setTokenStore(tokenStore());
services.setAccessTokenValiditySeconds(60 * 60 * 2);
services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 3);
return services;
}
@Bean
public AuthorizationCodeServices authorizationCodeServices() {
return new InMemoryAuthorizationCodeServices();
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authorizationCodeServices(authorizationCodeServices())
.authenticationManager(authenticationManager)
.tokenServices(tokenServices())
.allowedTokenEndpointRequestMethods(HttpMethod.POST);
}
}SecurityConfig class
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/** Password encoder */
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login")
.permitAll()
.and()
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password(new BCryptPasswordEncoder().encode("123456"))
.roles("admin");
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}2.2 Resource Server (port 8081)
Import the same dependencies as the authorization server and add a configuration class ResourceServerConfig :
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
/** Token validation service (remote call to auth server) */
@Bean
public RemoteTokenServices tokenServices() {
RemoteTokenServices services = new RemoteTokenServices();
services.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
services.setClientId("test");
services.setClientSecret("123456");
return services;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId("order")
.tokenServices(tokenServices());
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/**").access("#oauth2.hasScope('all')")
.anyRequest().authenticated();
}
}Test controller:
@RestController
public class TestController {
@GetMapping("/test")
public String hello() {
return "hello world";
}
}3. Test Results
Access the authorization endpoint:
http://localhost:8080/oauth/authorize?client_id=test&response_type=code&scope=all&redirect_uri=http://www.baidu.comLog in with username admin and password 123456 to obtain an authorization code, then exchange it for an access token (screenshots shown).
When calling the resource server without a token, the request is rejected (screenshot). With a valid token, the protected endpoint returns the expected response (screenshot).
Feel free to discuss, ask questions, or contact the author for further communication.
Additional promotional content about ChatGPT services, community groups, and interview material is included in the original article.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.