Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keycloak Spring boot configuration

I'm trying to configure Spring Boot and Keycloak for SSO. I've created a basic AngularJS application that do some requests to the Spring boot backend. using this

The Angular app is working fine and now I'm trying to follow the new Spring Boot Keycloak apdater docuementation here

This is my keycloak.json that is in the WEB-INF folder.

{
  "realm": "my-backend",
  "bearer-only": true,
  "realm-public-key": "MIIB...",
  "auth-server-url": "http://localhost:8180/auth",
  "ssl-required": "external",
  "resource": "my-backend",
  "principal-attribute": "preferred_username",
  "credentials": {
    "secret": "a75f55ca-8174-4072-8c60-b545c9ebf7e1"
}

Here is my security configuration :

@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
{
    /**
     * Registers the KeycloakAuthenticationProvider with the authentication manager.
     */
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(keycloakAuthenticationProvider());
    }

    /**
     * Defines the session authentication strategy.
     */
    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        super.configure(http);
        http
                .authorizeRequests()
                .antMatchers("/api/v1*").hasRole("user")
                .antMatchers("/admin/hello*").hasRole("admin")
                .anyRequest().permitAll();
    }

}

The 2 roles, 'admin' and 'user' are created in Keycloak and the current user has this roles.

@RestController
@RequestMapping("/")
@CrossOrigin("*")
public class PharmaController {

    public class Response{
        private String message;

        public Response(String msg){
            this.message = msg;
        }
        /**
         * @return the message
         */
        public String getMessage() {
            return message;
        }
        /**
         * @param message the message to set
         */
        public void setMessage(String message) {
            this.message = message;
        }

    }

    @RequestMapping(
            path="api/v1/userinfo", 
            method = RequestMethod.GET)
    @ResponseBody
    public void getUserInformation(KeycloakAuthenticationToken token) {
        if(token != null){
            System.out.println("token :" + token);

            try {
                System.out.println(token.getAccount().getPrincipal().getName());
                System.out.println(token.getAccount().getRoles());
            } catch (Exception e) {
                // TODO: handle exception
            } 

        }else{
            System.out.println("User not connected.");
        }
    }

    @RequestMapping(
            path="admin/hello", 
            method = RequestMethod.GET)
    @ResponseBody
    public Response adminHello(KeycloakAuthenticationToken token) {
        return new Response("Hello");
    }

}
  1. Even if the user doesn't have any of this role, he can access api/v1/userinfo with this response

{"data":"","status":200,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"http://localhost:8080/api/v1/userinfo","headers":{"Accept":"application/json, text/plain, */*","Access-Control-Allow-Origin":"*","Authorization":"BEARER eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJSN2JSQUgtcmUwNnVEMHh4Vlotd1dyWVIycVI0S0pyMDFIZWQ2QmJMNnA4In0.eyJqdGkiOiI3ZDU4ZGM0Yi0wYzgwLTQwZDYtYWE5OC0yNDk5YzEzZTg2NmMiLCJleHAiOjE0ODM5MTY3OTgsIm5iZiI6MCwiaWF0IjoxNDgzOTE2NDk4LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgxODAvYXV0aC9yZWFsbXMvbXktcGhhcm1hIiwiYXVkIjoicGhhcm1hLXdlYmFwcCIsInN1YiI6IjIxMjI2YzNlLWYwY2UtNGRjNC1hYzk0LTRlNTVmZjc4YWRlMSIsInR5cCI6IkJlYXJlciIsImF6cCI6InBoYXJtYS13ZWJhcHAiLCJub25jZSI6Ijg4MWI1MjhhLWFkOTktNDcwYy04YzJiLTlhYjI0MzM2N2IwOCIsImF1dGhfdGltZSI6MTQ4MzkxNjQ5OCwic2Vzc2lvbl9zdGF0ZSI6Ijg4ZmExODJjLTljOTctNGI2Ny1hMTMzLTk5YjFkNmU4OTZiYyIsImFjciI6IjEiLCJjbGllbnRfc2Vzc2lvbiI6IjJiM2FjNDg1LWQ5ZjUtNDc2ZC1hYjQ1LTA2ZGZmM2VjMTQxMiIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjkwMDAiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsInZpZXctcHJvZmlsZSJdfX0sIm5hbWUiOiJVc2VyMSBGTiBVc2VyMSBMTiIsInByZWZlcnJlZF91c2VybmFtZSI6InVzZXIxIiwiZ2l2ZW5fbmFtZSI6IlVzZXIxIEZOIiwiZmFtaWx5X25hbWUiOiJVc2VyMSBMTiIsImVtYWlsIjoidXNlcjFAeW91LmNvbSJ9.M1RvECaBV3jvNXRxQzLzS4bfKnK-gQp85mkr9GD8HbOsGRui81pZP3Pb_NJ-ieaQ7pca7tO_06UNeSqbHut7c1APV3_GEGTnwuCkKdbu1QKrVwXSXMWNyt0nu_MOdjhzG3bQat3aG68b744KdCSi5i8OBg2L4I3Zmc6nPX5vklf1U7LUXyvs_bswLPZEy1_VQ_ACu_BSIVA8iv64Nl4ng4QlEc6pyEHbhQ2pKpE7wNIiZe-ndfeQWU5FgnV0Ya16b2Up9ZnFw7fpGHDGjzlIEV_As3K32vON171OuAhTKmIbVnG4kuoijQzeqHmkoB-ldfMKPPlLheSILtHvRn8WkA"}},"statusText":""}
  1. The endpoint admin/hello is not reachable.

This is the stack trace :

[org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@63858877:org.apache.tomcat.util.net.NioChannel@4d4fa76c:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8080 remote=/0:0:0:0:0:0:0:1:51832]], Status in: [OPEN_READ], State out: [OPEN]
    2017-01-09 07:11:46.739 DEBUG 14692 --- [nio-8080-exec-2] o.a.coyote.http11.Http11InputBuffer      : Received [GET /admin/hello HTTP/1.1
    Host: localhost:8080
    Connection: keep-alive
    Pragma: no-cache
    Cache-Control: no-cache
    Access-Control-Allow-Origin: *
    Accept: application/json, text/plain, */*
    Origin: http://localhost:9000
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36
    Authorization: BEARER eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJSN2JSQUgtcmUwNnVEMHh4Vlotd1dyWVIycVI0S0pyMDFIZWQ2QmJMNnA4In0.eyJqdGkiOiIyMzMzZmI0OC0yMGE2LTQ2YzctODM1YS0wNGRiMDYyNmEyYWEiLCJleHAiOjE0ODM5MTc0MDQsIm5iZiI6MCwiaWF0IjoxNDgzOTE3MTA0LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgxODAvYXV0aC9yZWFsbXMvbXktcGhhcm1hIiwiYXVkIjoicGhhcm1hLXdlYmFwcCIsInN1YiI6IjIxMjI2YzNlLWYwY2UtNGRjNC1hYzk0LTRlNTVmZjc4YWRlMSIsInR5cCI6IkJlYXJlciIsImF6cCI6InBoYXJtYS13ZWJhcHAiLCJub25jZSI6IjQwZDc3MzAyLWViNTYtNGFhMS05OTllLTcyNDRiNmY3MTFkYiIsImF1dGhfdGltZSI6MTQ4MzkxNzEwNCwic2Vzc2lvbl9zdGF0ZSI6IjdmODlkODMyLTNkNTktNDc1Yi04NzI3LTRiZGQ5MDc4ODQ5YSIsImFjciI6IjEiLCJjbGllbnRfc2Vzc2lvbiI6IjJiOGNjMzc3LWY1NjUtNGE3NS1iMWY5LWEyNWFlZTY0ZGM3MCIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjkwMDAiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsInZpZXctcHJvZmlsZSJdfX0sIm5hbWUiOiJVc2VyMSBGTiBVc2VyMSBMTiIsInByZWZlcnJlZF91c2VybmFtZSI6InVzZXIxIiwiZ2l2ZW5fbmFtZSI6IlVzZXIxIEZOIiwiZmFtaWx5X25hbWUiOiJVc2VyMSBMTiIsImVtYWlsIjoidXNlcjFAeW91LmNvbSJ9.S5Jhrea_JzlXEuMPSfJ9Sd8HdNQyknklfdZFDMH_vaFWHiQShVVQAhM3wbwrz8NoJs3M6iFnkA-kuMPhCUR52y65HJ9mEXSxrUN6hPY4U9mEYIKw_kGVXFf_xOirA8lO9cvEmw7c7p2BN0DWmi85RshqhM6CEdGAtIL4z-rl-b3UDJkm9dT3uaMxcYb3l8lq0AkixqnaI8seFLdLgacdhfMblnKuyP6bgWUD2jl2X9ruVGfIHQeBdA19WesMJKHm9XqQaF1mjl0AM0k52bU7GZZ6cOD3yFwl2RMAUMlUPPyX9xq2L5kNEsgYdw4qlgdvjLaX_HipqHh7JHQksJv4Sg
    Referer: http://localhost:9000/
    Accept-Encoding: gzip, deflate, sdch, br
    Accept-Language: en-GB,en;q=0.8,en-US;q=0.6,fr;q=0.4

    ]
    2017-01-09 07:11:46.740 DEBUG 14692 --- [nio-8080-exec-2] o.a.c.authenticator.AuthenticatorBase    : Security checking request GET /admin/hello
    2017-01-09 07:11:46.740 DEBUG 14692 --- [nio-8080-exec-2] org.apache.catalina.realm.RealmBase      :   No applicable constraints defined
    2017-01-09 07:11:46.740 DEBUG 14692 --- [nio-8080-exec-2] o.a.c.authenticator.AuthenticatorBase    :  Not subject to any constraint
    2017-01-09 07:11:46.740 DEBUG 14692 --- [nio-8080-exec-2] org.apache.tomcat.util.http.Parameters   : Set encoding to UTF-8
    2017-01-09 07:11:46.740 DEBUG 14692 --- [nio-8080-exec-2] o.s.b.w.f.OrderedRequestContextFilter    : Bound request context to thread: org.apache.catalina.connector.RequestFacade@2683da6f
    2017-01-09 07:11:46.740 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /admin/hello' doesn't match 'OPTIONS /**
    2017-01-09 07:11:46.741 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
    2017-01-09 07:11:46.741 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
    2017-01-09 07:11:46.742 DEBUG 14692 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
    2017-01-09 07:11:46.742 DEBUG 14692 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
    2017-01-09 07:11:46.743 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
    2017-01-09 07:11:46.743 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 4 of 13 in additional filter chain; firing Filter: 'CsrfFilter'
    2017-01-09 07:11:46.744 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 5 of 13 in additional filter chain; firing Filter: 'KeycloakPreAuthActionsFilter'
    2017-01-09 07:11:46.744 DEBUG 14692 --- [nio-8080-exec-2] o.k.adapters.PreAuthActionsHandler       : adminRequest http://localhost:8080/admin/hello
    2017-01-09 07:11:46.744 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 6 of 13 in additional filter chain; firing Filter: 'LogoutFilter'
    2017-01-09 07:11:46.744 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /admin/hello' doesn't match 'POST /sso/logout
    2017-01-09 07:11:46.744 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 7 of 13 in additional filter chain; firing Filter: 'KeycloakAuthenticationProcessingFilter'
    2017-01-09 07:11:46.744 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/sso/login']
    2017-01-09 07:11:46.744 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/admin/hello'; against '/sso/login'
    2017-01-09 07:11:46.744 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using RequestHeaderRequestMatcher [expectedHeaderName=Authorization, expectedHeaderValue=null]
    2017-01-09 07:11:46.744 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher  : matched
    2017-01-09 07:11:46.744 DEBUG 14692 --- [nio-8080-exec-2] f.KeycloakAuthenticationProcessingFilter : Request is to process authentication
    2017-01-09 07:11:46.744 DEBUG 14692 --- [nio-8080-exec-2] f.KeycloakAuthenticationProcessingFilter : Attempting Keycloak authentication
    2017-01-09 07:11:46.871 DEBUG 14692 --- [nio-8080-exec-2] a.s.a.SpringSecurityRequestAuthenticator : Completing bearer authentication. Bearer roles: [uma_authorization] 
    2017-01-09 07:11:46.871 DEBUG 14692 --- [nio-8080-exec-2] o.k.adapters.RequestAuthenticator        : User 'user1' invoking 'http://localhost:8080/admin/hello' on client 'pharma-backend'
    2017-01-09 07:11:46.871 DEBUG 14692 --- [nio-8080-exec-2] o.k.adapters.RequestAuthenticator        : Bearer AUTHENTICATED
    2017-01-09 07:11:46.871 DEBUG 14692 --- [nio-8080-exec-2] f.KeycloakAuthenticationProcessingFilter : Auth outcome: AUTHENTICATED
    2017-01-09 07:11:46.871 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.authentication.ProviderManager     : Authentication attempt using org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider
    2017-01-09 07:11:46.872 DEBUG 14692 --- [nio-8080-exec-2] o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'delegatingApplicationListener'
    2017-01-09 07:11:46.889 DEBUG 14692 --- [nio-8080-exec-2] o.k.a.s.management.HttpSessionManager    : Session created: D309F84825BE807C7B34F16B111E92CD
    2017-01-09 07:11:46.890 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.core.session.SessionRegistryImpl   : Registering session D309F84825BE807C7B34F16B111E92CD, for principal user1
    2017-01-09 07:11:46.891 DEBUG 14692 --- [nio-8080-exec-2] f.KeycloakAuthenticationProcessingFilter : Authentication success using bearer token/basic authentication. Updating SecurityContextHolder to contain: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@a08a84cd: Principal: user1; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@4ebe3c30; Granted Authorities: KeycloakRole{role='uma_authorization'}
    2017-01-09 07:11:46.891 DEBUG 14692 --- [nio-8080-exec-2] o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'delegatingApplicationListener'
    2017-01-09 07:11:46.891 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 8 of 13 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
    2017-01-09 07:11:46.891 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 9 of 13 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
    2017-01-09 07:11:46.892 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 10 of 13 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
    2017-01-09 07:11:46.892 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter  : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@a08a84cd: Principal: user1; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@4ebe3c30; Granted Authorities: KeycloakRole{role='uma_authorization'}'
    2017-01-09 07:11:46.892 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 11 of 13 in additional filter chain; firing Filter: 'SessionManagementFilter'
    2017-01-09 07:11:46.892 DEBUG 14692 --- [nio-8080-exec-2] s.CompositeSessionAuthenticationStrategy : Delegating to org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy@29a23c3d
    2017-01-09 07:11:46.892 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.core.session.SessionRegistryImpl   : Registering session D309F84825BE807C7B34F16B111E92CD, for principal user1
    2017-01-09 07:11:46.892 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.core.session.SessionRegistryImpl   : Removing session D309F84825BE807C7B34F16B111E92CD from principal's set of registered sessions
    2017-01-09 07:11:46.892 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.core.session.SessionRegistryImpl   : Removing principal user1 from registry
    2017-01-09 07:11:46.892 DEBUG 14692 --- [nio-8080-exec-2] s.CompositeSessionAuthenticationStrategy : Delegating to org.springframework.security.web.csrf.CsrfAuthenticationStrategy@20f0cc02
    2017-01-09 07:11:46.892 DEBUG 14692 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : SecurityContext 'org.springframework.security.core.context.SecurityContextImpl@a08a84cd: Authentication: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@a08a84cd: Principal: user1; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@4ebe3c30; Granted Authorities: KeycloakRole{role='uma_authorization'}' stored to HttpSession: 'org.apache.catalina.session.StandardSessionFacade@1a43aa14
    2017-01-09 07:11:46.892 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 12 of 13 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
    2017-01-09 07:11:46.892 DEBUG 14692 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /admin/hello at position 13 of 13 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
    2017-01-09 07:11:46.893 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /admin/hello' doesn't match 'POST /sso/logout
    2017-01-09 07:11:46.893 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/admin/hello'; against '/api/v1*'
    2017-01-09 07:11:46.893 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/admin/hello'; against '/admin/hello*'
    2017-01-09 07:11:46.893 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /admin/hello; Attributes: [hasRole('ROLE_admin')]
    2017-01-09 07:11:46.893 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@a08a84cd: Principal: user1; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@4ebe3c30; Granted Authorities: KeycloakRole{role='uma_authorization'}
    2017-01-09 07:11:46.895 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.access.vote.AffirmativeBased       : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@58311096, returned: -1
    2017-01-09 07:11:46.896 DEBUG 14692 --- [nio-8080-exec-2] o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'delegatingApplicationListener'
    2017-01-09 07:11:46.899 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.w.a.ExceptionTranslationFilter     : Access is denied (user is not anonymous); delegating to AccessDeniedHandler

    org.springframework.security.access.AccessDeniedException: Access is denied
        at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-4.1.4.RELEASE.jar:4.1.4.RELEASE]
        at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-4.1.4.RELEASE.jar:4.1.4.RELEASE]
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) ~[spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
        at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115) ~[spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.1.4.RELEASE.jar:4.1.4.RELEASE]
  ...
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.6.jar:8.5.6]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]

    2017-01-09 07:11:46.899 DEBUG 14692 --- [nio-8080-exec-2] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@5ca0c4c5
    2017-01-09 07:11:46.899 DEBUG 14692 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : SecurityContext 'org.springframework.security.core.context.SecurityContextImpl@a08a84cd: Authentication: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@a08a84cd: Principal: user1; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@4ebe3c30; Granted Authorities: KeycloakRole{role='uma_authorization'}' stored to HttpSession: 'org.apache.catalina.session.StandardSessionFacade@1a43aa14
    2017-01-09 07:11:46.899 DEBUG 14692 --- [nio-8080-exec-2] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
    2017-01-09 07:11:46.899 DEBUG 14692 --- [nio-8080-exec-2] o.s.b.w.f.OrderedRequestContextFilter    : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@2683da6f
    2017-01-09 07:11:46.900 DEBUG 14692 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost]           : Processing ErrorPage[errorCode=0, location=/error]
    2017-01-09 07:11:46.901 DEBUG 14692 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/error]
    2017-01-09 07:11:46.902 DEBUG 14692 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /error
    2017-01-09 07:11:46.904 DEBUG 14692 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)]
    2017-01-09 07:11:46.904 DEBUG 14692 --- [nio-8080-exec-2] o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'basicErrorController'
    2017-01-09 07:11:46.904 DEBUG 14692 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/error] is: -1
    2017-01-09 07:11:46.927 DEBUG 14692 --- [nio-8080-exec-2] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Written [{timestamp=Mon Jan 09 07:11:46 MYT 2017, status=403, error=Forbidden, message=Access is denied, path=/admin/hello}] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@45db4b8b]
    2017-01-09 07:11:46.927 DEBUG 14692 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
    2017-01-09 07:11:46.927 DEBUG 14692 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Successfully completed request
    2017-01-09 07:11:46.928 DEBUG 14692 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    :  Disabling the response for futher output
    2017-01-09 07:11:46.928 DEBUG 14692 --- [nio-8080-exec-2] o.apache.coyote.http11.Http11Processor   : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@63858877:org.apache.tomcat.util.net.NioChannel@4d4fa76c:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8080 remote=/0:0:0:0:0:0:0:1:51832]], Status in: [OPEN_READ], State out: [OPEN]
like image 997
nono Avatar asked Jan 08 '17 23:01

nono


2 Answers

I went through the same and here are my findings.

org.springframework.security.access.vote.RoleVoter assumes that your roles start from

private String rolePrefix = "ROLE_";

There is no such assumption in Keycloak (unless you name all your roles ROLE_someName), therefore no roles are actually found matching.

Similar explanation can be obtained from Spring Security Javadoc of SecurityExpressionOperations class for hasRole method

This is similar to {@link #hasAuthority(String)} except that this method implies
that the String passed in is a role. For example, if "USER" is passed in the
implementation may convert it to use "ROLE_USER" instead. The way in which the role
is converted may depend on the implementation settings.

To sum it up, I've ended with exactly the same solution as you did, using hasAuthority instead of hasRole now.

like image 88
hakamairi Avatar answered Sep 28 '22 02:09

hakamairi


I solved it myself by replacing hasRole() by hasAuthority(). I still don't know why keycloak role is mapped to spring security authority. Any explaination is welcomed. Thank you.

like image 31
nono Avatar answered Sep 28 '22 01:09

nono