I have implemented authorization server and resource server using spring boot. authorization server works fine and I am able to get tokens. But my resource server remains unprotected. My objective is that resource server ahould only be accessed by someone having valid access token.
My entire code is:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
TokenStore tokenStore;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.tokenStore(tokenStore)
.authenticationManager(authenticationManager);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("client")
.scopes("read", "write")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.authorizedGrantTypes("password", "refresh_token")
.secret("secret")
.accessTokenValiditySeconds(180)
.refreshTokenValiditySeconds(600);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
super.configure(security); //To change body of generated methods, choose Tools | Templates.
}
}
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources
.tokenServices(tokenServices())
.resourceId("MY_RESOURCE");
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.anonymous().disable()
.requestMatchers().antMatchers("/**")
.and()
.authorizeRequests()
.antMatchers("/").access("hasRole('USER')")
.antMatchers("/secure/").access("hasRole('ADMIN')")
.and()
.exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore);
return defaultTokenServices;
}
@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("bill").password("abc123").roles("ADMIN").and()
.withUser("bob").password("abc123").roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/oauth/token").permitAll();
}
}
@Configuration
@EnableGlobalMethodSecurity
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
@SpringBootApplication
@RestController
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
@GetMapping(value = "/")
public ResponseEntity<?> hello(){
return ResponseEntity.ok("Hello World");
}
@GetMapping(value = "/secure/")
public ResponseEntity<?> secure(){
return ResponseEntity.ok("Secure Resorce");
}
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>boot-oauth2</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>boot-oauth2</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
What am I missing? Thanks for help.
UPDATE:
I figured out that my resource server is unprotected because of presence of OAuth2SecurityConfig
class. If I remove this class and add following class (where I have moved the inMemmory users), then resource server is protected as required
@Configuration
public class WebSecurityGlobalConfig extends GlobalAuthenticationConfigurerAdapter {
@Autowired
UserService userService;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("bill").password("abc123").roles("ADMIN").and()
.withUser("bob").password("abc123").roles("USER");
}
}
So, I am sensing improper HttpSecurity configuration in OAuth2SecurityConfig class is conflicting with resource server config. So, How can I configure HttpSecurity of OAuth2SecurityConfig so, that it does allow access token protection for resource server paths and normal web security for non-resource server paths
What Is a Resource Server? In the context of OAuth 2.0, a resource server is an application that protects resources via OAuth tokens. These tokens are issued by an authorization server, typically to a client application. The job of the resource server is to validate the token before serving a resource to the client.
Updated on 17 June, 2022 in Spring Security. Resource Server in OAuth2 is used to protect access to resources, APIs. It will validate the access token passed by the Client Application, with the Authorization Server to decide if the Client Application has access to the resources and APIs it wants.
End of Life NoticeThe Spring Security OAuth project has reached end of life and is no longer actively maintained by VMware, Inc. This project has been replaced by the OAuth2 support provided by Spring Security and Spring Authorization Server.
finally after a lot of googling, I found the solution.
It was due to order of filters. order of OAuth2 resource filter has been changed in spring-boot-1.5.1. as change log says
The default order of the OAuth2 resource filter has changed from 3 to SecurityProperties.ACCESS_OVERRIDE_ORDER - 1. This places it after the actuator endpoints but before the basic authentication filter chain. The default can be restored by setting security.oauth2.resource.filter-order = 3
So, I changed the order of my OAuth2 resource server filter to 3 by setting it in application.properties security.oauth2.resource.filter-order = 3
and my problem was solved.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With