How to use Spring Security RemoteTokenService with Keycloak

HaVonTe :

I setup a Keycloak server. Configured the realm and client and so on. I managed successfully to write a Spring Boot service with "org.keycloak:keycloak-spring-boot-starter" and secured my RestController. Works like a charm.

But when I try to use Spring Security (without the keycloak specific dependencies) I am stuck.

here is my gradle:

dependencies {
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.security.oauth:spring-security-oauth2')

compile('org.springframework.boot:spring-boot-starter-web')
compileOnly('org.projectlombok:lombok')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.springframework.security:spring-security-test')

}

This is my SecurityConfig:

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends 
ResourceServerConfigurerAdapter {

@Override
public void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/person/**").hasRole("DEMO_SPRING_SECURITY")
        .anyRequest().authenticated()
        .and().formLogin().disable();
}

@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {

    resources.resourceId("demo-client");
    RemoteTokenServices tokenServices = new RemoteTokenServices();
    tokenServices.setCheckTokenEndpointUrl(
        "http://localhost:8280/auth/realms/demo-realm/protocol/openid-connect/token/introspect");
    tokenServices.setClientId("demo-client");
    tokenServices.setClientSecret("80e19056-7770-4a4a-a3c4-06d8ac8792ef");
    resources.tokenServices(tokenServices);
}
}

Now I try the access the server:

  1. get an access token (via REST client) the decoded JWT looks like this:
{
"jti": "78c00562-d80a-4f5a-ab08-61ed10cb575c",
"exp": 1509603570,
"nbf": 0,
"iat": 1509603270,
"iss": "http://localhost:8280/auth/realms/demo-realm",
"aud": "demo-client",
"sub": "6ee90ba4-2854-49c1-9776-9aa95b6ae598",
"typ": "Bearer",
"azp": "demo-client",
"auth_time": 0,
"session_state": "68ce12fb-3b3f-429d-9390-0662f0503bbb",
"acr": "1",
"client_session": "ec0113e1-022a-482a-a26b-e5701e5edec1",
"allowed-origins": [],
"realm_access": {
  "roles": [
    "demo_user_role",
    "uma_authorization"
  ]
},
"resource_access": {
  "account": {
    "roles": [
      "manage-account",
      "manage-account-links",
      "view-profile"
    ]
  }
},
"name": "Jim Panse",
"preferred_username": "demo-user",
"given_name": "Jim",
"family_name": "Panse",
"email": "[email protected]"
}

But I get an AccessDeniedException.

2017-11-02 07:18:05.344 DEBUG 17637 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated:

org.springframework.security.oauth2.provider.OAuth2Authentication@1f3ee7e1: Principal: demo-client; Credentials: [PROTECTED]; Authenticated: true; Details: remoteAddress=127.0.0.1, tokenType=BearertokenValue=; Not granted any authorities 2017-11-02 07:18:05.348 DEBUG 17637 --- [nio-8080-exec-1] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@14032696, returned: -1 2017-11-02 07:18:05.353 DEBUG 17637 --- [nio-8080-exec-1] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is not anonymous); delegating to AccessDeniedHandler

org.springframework.security.access.AccessDeniedException: Access is denied

I debuged the RemoteTokenService and found out the Keycloak responds with the exact same accesstoken. Which is fine. But than the DefaultAccessTokenConverter tries to read the user roles from a field authorities which not exists. And the OAuth2WebSecurityExpressionHandler evaluates that the user doenst have any roles. --> access denied

So my question:

What is neccessary to make Spring Security work with Keycloak access tokens?

Boomer :

Via keycloak admin console you can create a token mapper of type User Realm Role with claim name "authorities" for your client "demo-client". Then the access token contains the role names in this attribute and no custom DefaultAccessTokenConverter is needed.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=439856&siteId=1