I have a spring boot application and a keycloak instance.
The spring boot application runs in 8083 port and has some endpoints-resources and I want all these to be accessed upon authentication but also authorization having a certain role
Let's assume that we have some users and the role named myrole assigned to one or more of them.
I have the below configuration in my spring boot app in order to make all my endpoints to be accessible from every user that has the myrole role assigned.
SecurityConfig.java
package mypackage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Bean
public SecurityFilterChain resourceServerFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authorize -> authorize.anyRequest().hasAuthority("myrole"));
http.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class)
.build();
}
}
application.properties
keycloak.uri=http://localhost:8080/realms/myrealm
spring.security.oauth2.client.registration.keycloak.client-id=myclient
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.scope=openid
spring.security.oauth2.client.provider.keycloak.issuer-uri=${keycloak.uri}
spring.security.oauth2.client.provider.keycloak.use-resource-role-mappings=true
spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username
spring.security.oauth2.resourceserver.jwt.issuer-uri=${keycloak.uri}
I test it with postman and every time I get a 403 Forbidden response. The request has the bearer token in Authorization header.
What do I miss?
RTFM
Also, you shouldn't need OAuth2 client dependencies and configuration properties on a REST API authorized with access tokens.
If you want something simpler that what is exposed in the doc, you can have a look at this starter I wrote:
If you're using method security (decorate your
@Controllerclasses or methods with@PreAuthorize("hasAuthority('myrole')")), then all you need is:If you prefer to use
AuthorizationManagerRequestMatcherRegistryin your conf, then what you need is: