title: Protect individual resources from Spring Boot via Keycloak
body: <p>I've got a very simple Spring Boot application with resources at <code>/repositories</code> and <code>/persons</code>.</p>
  <p>Here is my <code>build.gradle</code> file.</p>
  <pre><code>plugins {
      id 'org.springframework.boot' version '2.4.0'
      id 'io.spring.dependency-management' version '1.0.10.RELEASE'
      id 'java'
  }
  
  // use java 11 until keycloak is fixed
  sourceCompatibility = '11'
  
  repositories {
      mavenCentral()
  }
  
  dependencyManagement {
      imports {
          mavenBom &quot;org.keycloak.bom:keycloak-adapter-bom:12.0.1&quot;
      }
  }
  
  dependencies {
      implementation 'org.springframework.boot:spring-boot-starter-web'
      implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
  
      implementation 'org.springframework.boot:spring-boot-starter-security'
      implementation 'org.keycloak:keycloak-spring-boot-starter'
  
      implementation 'org.flywaydb:flyway-core'
      runtime 'org.postgresql:postgresql'
  
      testImplementation 'org.springframework.boot:spring-boot-starter-test'
  }
  
  ...
  ...
  </code></pre>
  <p>Here is my <code>SecurityConfig.java</code> file.</p>
  <pre class="lang-java prettyprint-override"><code>@KeycloakConfiguration
  public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
  
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
      var keycloakAuthenticationProvider = keycloakAuthenticationProvider();
      keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
      auth.authenticationProvider(keycloakAuthenticationProvider);
    }
  
    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
      return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }
  
    @Override
    protected void configure(HttpSecurity http) throws Exception {
      super.configure(http);
      http.authorizeRequests()
          .antMatchers(&quot;/persons*&quot;)
          .hasRole(&quot;user&quot;)
          .anyRequest()
          .permitAll();
    }
  
    @Bean
    public KeycloakConfigResolver keycloakConfigResolver() {
      return new KeycloakSpringBootConfigResolver();
    }
  }
  </code></pre>
  <p>Here is my <code>application.yaml</code> file.</p>
  <pre class="lang-yaml prettyprint-override"><code>spring:
    datasource:
      url: jdbc:postgresql://localhost:5432/postgres
      username: john
      password: john
  
  keycloak:
    auth-server-url: http://localhost:8081/auth/
    realm: myrealm
    resource: myclient
    credentials:
      secret: 45d43bd6-5ab9-476c-83c8-67bd203a78ee
  </code></pre>
  <p>It's all on my local machine and Keycloak and Postgres are started via docker compose.</p>
  <pre class="lang-yaml prettyprint-override"><code>
  version: &quot;3.1&quot;
  
  volumes:
    postgres_data:
        driver: local
  
  services:
    db:
      image: &quot;postgres:13.1&quot;
      ports:
        - &quot;5432:5432&quot;
      environment:
        POSTGRES_DB: postgres
        POSTGRES_USER: john
        POSTGRES_PASSWORD: john
    postgres:
      image: &quot;postgres:13.1&quot;
      volumes:
        - postgres_data:/var/lib/postgresql/data
      environment:
        POSTGRES_DB: keycloak
        POSTGRES_USER: keycloak
        POSTGRES_PASSWORD: password
    keycloak:
      image: quay.io/keycloak/keycloak:12.0.1
      environment:
        DB_VENDOR: POSTGRES
        DB_ADDR: postgres
        DB_DATABASE: keycloak
        DB_USER: keycloak
        DB_SCHEMA: public
        DB_PASSWORD: password
        KEYCLOAK_USER: admin
        KEYCLOAK_PASSWORD: Pa55w0rd
      ports:
        - 8081:8080
      depends_on:
        - postgres
  </code></pre>
  <p>I've got the users <code>zemirco</code> and <code>one</code> in Keycloak and they both have the <code>user</code> role. It all works very nicely and the route <code>/persons</code> is protected whereas <code>/repositories</code> is open for all.</p>
  <p>Here is my problem! I'd like to secure individual resources, e.g. <code>/person/1</code>. I cannot make it work :( I've been trying for days now but no luck. Here are my keycloak settings.</p>
  <p>Here is my policy.</p>
  <p><a href="https://i.stack.imgur.com/Xgas3.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Xgas3.png" alt="policy" /></a></p>
  <p>Here is the resource.</p>
  <p><a href="https://i.stack.imgur.com/sfZYh.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/sfZYh.png" alt="resource" /></a></p>
  <p>Here is the permission.</p>
  <p><a href="https://i.stack.imgur.com/8GHHL.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/8GHHL.png" alt="permission" /></a></p>
  <p>It all works during the evaluating at Keycloak. However it does not work directly at my Spring Boot application. I can still access <code>/person/1</code> as <code>zemirco</code> although user <code>one</code> should only have access.</p>
  <p>I'm a bit lost at the moment. Do you have any ideas?</p>
  <p>Thank you very much!</p>
  <hr />
  <p>Edit Jan 10 2021</p>
  <p>Thank you all for your answers but I still think it's doable without a lot of extra effort on my side (the application side). I'm especially looking at policy enforcers <a href="https://www.keycloak.org/docs/latest/authorization_services/#_enforcer_overview" rel="nofollow noreferrer">https://www.keycloak.org/docs/latest/authorization_services/#_enforcer_overview</a>.</p>
  <blockquote>
  <p>A PEP is responsible for enforcing access decisions from the Keycloak server where these decisions are taken by evaluating the policies associated with a protected resource. It acts as a filter or interceptor in your application in order to check whether or not a particular request to a protected resource can be fulfilled based on the permissions granted by these decisions.</p>
  </blockquote>
  <p>This sound exactly like what I'm trying to do. Unfortunately I cannot make it work. I just think my configuration is false or maybe incomplete. I will add a bounty to the question.</p>