OAuth 2.0 Overview and Spring Boot Implementation Guide
This article introduces OAuth 2.0 concepts, roles, and grant types, then provides a step‑by‑step Spring Boot implementation for an authorization server and a resource server, including configuration classes, Maven dependencies, test endpoints, and screenshots of the authentication and token‑validation process.
This article introduces OAuth 2.0, an open standard for delegating authorization without sharing user credentials, and explains its core concepts such as resource owner, client, authorization server, and resource server.
1. OAuth 2.0 Overview
OAuth 2.0 is widely used for secure authentication and authorization in web applications.
Roles
Resource Owner: The user who owns the protected resources.
Client: The third‑party application requesting access.
Authorization Server: Issues access tokens after authenticating the resource owner.
Resource Server: Hosts the protected resources and validates tokens.
Grant Types
Authorization Code: Standard flow used by most third‑party login integrations.
Implicit (Simplified): Token is obtained directly in the browser, suitable for pure static sites.
Password: Client receives username/password from the user; suitable when client and server are trusted.
Client Credentials: Client authenticates on its own behalf, often used for service‑to‑service calls.
2. Code Setup
2.1 Authorization Server (port 8080)
Import the required Maven dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
</dependencies>Add two configuration classes.
@Configuration
@EnableAuthorizationServer
public class MyAuthorizationConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private ClientDetailsService clientDetailsService;
@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);
}
} @Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@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)
Use the same dependencies and add the following configuration class:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@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 URL http://localhost:8080/oauth/authorize?client_id=test&response_type=code&scope=all&redirect_uri=http://www.baidu.com , log in with admin / 123456 , obtain the authorization code, exchange it for an access token, and call the resource endpoint with and without the token.
The screenshots show successful login, token issuance, and resource access when the token is present, while requests without a token are rejected.
Feel free to discuss the implementation details, ask questions, or share alternative approaches.
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.