Spring Security + Keycloak Authorization: How to associate an endpoint with a Resource?

Viewed 1646

I have created a Spring Boot app with spring-boot-starter-security and keycloak-spring-security-adapter and authenticating users with Keycloak works as intended.

I now want to use Keycloak's Authorization Services for fine-grained access control to my API.

In Keycloak, I've enabled Authorization for my client. I've created a Role and I've assigned the Role to my test User. I've created a Resource and a Resource-based Permission and I've added a Role-based Policy. Using the Evaluate feature, I've confirmed, that my user has permission to access my resource.

enter image description here

Let's say I have the following controller with one endpoint.

@RestController
class GreetingController {

    @GetMapping("/hello")
    fun getPatientInfo(principal: Principal): String {
        return "Hello, ${principal.name}!"
    }
}

Now my question is: How do I associate an endpoint in my Spring Boot application with the given Resource so that the permission is evaluated when a request is made?

1 Answers

„…How do I associate an endpoint in my Spring Boot application with the given Resource so that the permission is evaluated when a request is made?…“

By way of example, let's say…

  • Your Keycloak server is running on port 8585
  • Your application server is running on port 8080
  • Your realm is named „myrealm“
  • Your resource is named „my-client-resource“
  • You role is named „super-user“

Then in your Spring Boot application's application.properties file you'd set…

#port on which the application would run
server.port = 8080
keycloak.realm = myrealm
keycloak.auth-server-url = http://localhost:8585/auth
keycloak.ssl-required = none
#keycloak resource is the client ID
keycloak.resource = my-client-resource
keycloak.use-resource-role-mappings = true
keycloak.public-client = true
…
# Configures what ${principal.name} will return
keycloak.principal-attribute=preferred_username

And you hook into Spring Boot's Keycloak configuration with…

…
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity( prePostEnabled = true )
@ComponentScan( basePackageClasses = KeycloakSecurityComponents.class )
public class SecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {

    @Override
    public void configure( HttpSecurity http ) throws Exception {
        super.configure( http );
    
        http.authorizeRequests( )
            .antMatchers( "/hello", "…" )
            .hasRole( "super-user" )
            .anyRequest( )
            .permitAll( );
    }
…
}

In the absence of more specific details of your application and configuration, the above is a sketch. But that is the general approach.

For a more concrete grasp of the above general approach, download and play with this MRE that I implemented for another answer recently.

Related