Implementing OAuth2.0 Authentication and Resource Server with Spring Boot
This article explains the fundamentals of OAuth2.0, outlines its roles and grant types, and provides a step‑by‑step Spring Boot implementation—including authorization server, security configuration, resource server, and a test controller—followed by detailed testing procedures and results.
OAuth 2.0 (Open Authorization) is an open standard that enables third‑party applications to obtain limited access to a user's protected resources without sharing credentials, and it is widely used for secure delegation in authentication and authorization scenarios.
The core roles in OAuth2.0 are the Resource Owner (the user), the Client (the third‑party app), the Authorization Server (issues tokens after authenticating the user), and the Resource Server (hosts the protected resources).
Four main grant types are supported: Authorization Code (commonly used for third‑party logins), Implicit (simplified flow for browser‑only apps), Password (direct user‑password exchange, suitable when the client is highly trusted), and Client Credentials (client‑only access). An additional refresh token grant allows token renewal.
**Code setup**
1. Add Maven dependencies for Spring Boot Web, Spring Cloud Security, and Spring Cloud OAuth2:
<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>2. **Authorization Server configuration** (`MyAuthorizationConfig`): enables the authorization server, defines client details (in‑memory client "test" with secret "123456"), token store, token services, and supported grant types.
@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);
}
}3. **Security configuration** (`SecurityConfig`): sets up password encoding, form‑login, and an in‑memory user "admin" with password "123456".
@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();
}
}4. **Resource Server configuration** (`ResourceServerConfig`): validates tokens via the authorization server’s `/oauth/check_token` endpoint and protects all endpoints with the scope "all".
@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();
}
}5. **Test controller** provides a simple endpoint returning "hello world":
@RestController
public class TestController {
@GetMapping("/test")
public String hello() { return "hello world"; }
}**Testing steps and results**
Open 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 username admin and password 123456 to obtain an authorization code.
Exchange the code for an access token (screenshots in the original article illustrate the token response).
Access the protected resource at http://localhost:8081/test with the token; the article shows both the failure without a token and the successful response when the token is supplied.
Images in the original post demonstrate the UI of each step (authorization page, token response, and resource access).
Author: 山河亦问安 – source: CSDN blog .
Top Architecture Tech Stack
Sharing Java and Python tech insights, with occasional practical development tool tips.
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.