I want to use the new Spring Security Authorization Server to implement OAuth2 for my webservice.
At https://www.baeldung.com/spring-security-oauth-auth-server an example is given, separation
- Authorization Server
- Resource Server
- Client
The code can be found at https://github.com/Baeldung/spring-security-oauth/tree/master/oauth-authorization-server
Those three Maven projects function in the given version, when the client in the web browser access http://localhost:8080/articles the output is correctly
["Article 1","Article 2","Article 3"]
I need to restrict the access to paths based on the roles defined on the users, or maybe with authorities would also work.
In this example, in the Resource Server it is implemented
@EnableWebSecurity
public class ResourceServerConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.mvcMatcher("/articles/**")
.authorizeRequests()
.mvcMatchers("/articles/**").access("hasAuthority('SCOPE_articles.read')")
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
}
I changed it to
http
.authorizeRequests()
.antMatchers("/articles").hasRole("ADMIN")
and also defined in the Authorization Server project an user admin / admin123
with .roles("ADMIN")
However, that doesn't function as expected, when the client accesses http://localhost:8080/articles I get in the client project console the output
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.reactive.function.client.WebClientResponseException$Forbidden: 403 Forbidden from GET http://localhost:8090/articles] with root cause
org.springframework.web.reactive.function.client.WebClientResponseException$Forbidden: 403 Forbidden from GET http://localhost:8090/articles
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:183) ~[spring-webflux-5.3.4.jar:5.3.4]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ 403 from GET http://localhost:8090/articles [DefaultWebClient]
I found an example project https://blog.jdriven.com/2019/10/spring-security-5-2-oauth-2-exploration-part1/, but unfortunately it uses Keycloak as authorization server, but implements the same idea of restricting the access to paths with user roles.
It defines a KeycloakRealmRoleConverter
, but how to define one for the given three Baeldung projects?
The example with Keycloak uses jwt.getClaims().get("realm_access")
, which obviously accesses a key realm_access
, but this is related to Keycloak.
To print out the JWT token I changed in the resource server REST controller
@GetMapping("/articles")
public String[] getArticles(final @AuthenticationPrincipal Jwt
System.out.println("\n\njwt.getTokenValue():\n" + jwt.getTokenValue());
...
}
At jwt.io
it shows
HEADER:ALGORITHM & TOKEN TYPE
{
"kid": "fce0c3e4-a9a6-4e6d-8fbd-c2b774b338f0",
"typ": "JWT",
"alg": "RS256"
}
PAYLOAD:DATA
{
"sub": "admin",
"aud": "articles-client",
"nbf": 1628351323,
"scope": [
"articles.read"
],
"iss": "http://127.0.0.1:9000",
"exp": 1628351623,
"iat": 1628351323,
"jti": "c4bc5f35-e93f-483f-8952-a694a04f8f32"
}
No roles defined there. I would have expected next to the username admin
also the role ADMIN
defined for that user.
Not sure how to restrict the access on a path in the resource server with user role, if it is not in the JWT.