1
votes

Hello I am new to keycloak and Spring Security. I have a backend service REST API. I am trying to secure it with keycloak. The problem is when I make POST request using Postman, it returns 403 Forbidden response. I checked the logs in Keycloak they seem to authenticate with keycloak fine. I isolated logs for one POST API request. Can some say what is wrong with my configurations?

2019-01-23 16:17:14 DEBUG - adminRequest http://localhost:8080/api/users
2019-01-23 16:17:14 DEBUG - AuthenticatedActionsValve.invoke /api/users
2019-01-23 16:17:14 DEBUG - AuthenticatedActionsValve.invoke http://localhost:8080/api/users
2019-01-23 16:17:14 DEBUG - Policy enforcement is disabled.
2019-01-23 16:17:14 DEBUG - adminRequest http://localhost:8080/api/users
2019-01-23 16:17:14 DEBUG - Request is to process authentication
2019-01-23 16:17:14 DEBUG - Attempting Keycloak authentication
2019-01-23 16:17:14 TRACE - --> authenticate()
2019-01-23 16:17:14 TRACE - try bearer
2019-01-23 16:17:14 DEBUG - Verifying access_token
2019-01-23 16:17:14 TRACE -     access_token: eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJBeThhY0RDeURhM0NKWVhjeUVPQkhEWkpIS2U4TTV3T3JpeU1UTmZLWngwIn0.eyJqdGkiOiI5NzFkNDg4YS1iMGJkLTRiMTUtOTgzNC1lYzIxN2NlYzAxZDMiLCJleHAiOjE1NDgyNDA3MzAsIm5iZiI6MCwiaWF0IjoxNTQ4MjQwNDMwLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgxODAvYXV0aC9yZWFsbXMvTXlEZW1vIiwic3ViIjoiMWZiNTlmMjItYTMzMi00YjdmLWJkMzgtYzE5M2RiYTI0ZDk5IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoibXktcmVhY3QtY2xpZW50IiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiYmRiNzA4N2ItNGViMi00NzMyLWIzNGQtY2RmYTEwZjgxNjA0IiwiYWNyIjoiMSIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJNZW51a2EgSXNoYW4iLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbi11c2VyIiwiZ2l2ZW5fbmFtZSI6Ik1lbnVrYSIsImZhbWlseV9uYW1lIjoiSXNoYW4iLCJlbWFpbCI6Im1lbnVrYUBoc2VuaWQubGsifQ.signature
2019-01-23 16:17:14 DEBUG - successful authorized
2019-01-23 16:17:14 TRACE - checking whether to refresh.
2019-01-23 16:17:14 TRACE - useResourceRoleMappings
2019-01-23 16:17:14 TRACE - Setting roles: 
2019-01-23 16:17:14 DEBUG - Completing bearer authentication. Bearer roles: [] 
2019-01-23 16:17:14 DEBUG - User '1fb59f22-a332-4b7f-bd38-c193dba24d99' invoking 'http://localhost:8080/api/users' on client 'my-react-client'
2019-01-23 16:17:14 DEBUG - Bearer AUTHENTICATED
2019-01-23 16:17:14 DEBUG - Auth outcome: AUTHENTICATED
2019-01-23 16:17:14 DEBUG - Authentication success using bearer token/basic authentication. Updating SecurityContextHolder to contain: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@dacf45b2: Principal: 1fb59f22-a332-4b7f-bd38-c193dba24d99; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@6bb92c4a; Not granted any authorities
2019-01-23 16:17:14 DEBUG - AuthenticatedActionsValve.invoke http://localhost:8080/api/users
2019-01-23 16:17:14 DEBUG - Policy enforcement is disabled.
2019-01-23 16:17:14 DEBUG - adminRequest http://localhost:8080/error
2019-01-23 16:17:14 DEBUG - Request is to process authentication
2019-01-23 16:17:14 DEBUG - Attempting Keycloak authentication
2019-01-23 16:17:14 TRACE - --> authenticate()
2019-01-23 16:17:14 TRACE - try bearer
2019-01-23 16:17:14 DEBUG - Verifying access_token
2019-01-23 16:17:14 TRACE -     access_token: eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJBeThhY0RDeURhM0NKWVhjeUVPQkhEWkpIS2U4TTV3T3JpeU1UTmZLWngwIn0.eyJqdGkiOiI5NzFkNDg4YS1iMGJkLTRiMTUtOTgzNC1lYzIxN2NlYzAxZDMiLCJleHAiOjE1NDgyNDA3MzAsIm5iZiI6MCwiaWF0IjoxNTQ4MjQwNDMwLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgxODAvYXV0aC9yZWFsbXMvTXlEZW1vIiwic3ViIjoiMWZiNTlmMjItYTMzMi00YjdmLWJkMzgtYzE5M2RiYTI0ZDk5IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoibXktcmVhY3QtY2xpZW50IiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiYmRiNzA4N2ItNGViMi00NzMyLWIzNGQtY2RmYTEwZjgxNjA0IiwiYWNyIjoiMSIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJNZW51a2EgSXNoYW4iLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbi11c2VyIiwiZ2l2ZW5fbmFtZSI6Ik1lbnVrYSIsImZhbWlseV9uYW1lIjoiSXNoYW4iLCJlbWFpbCI6Im1lbnVrYUBoc2VuaWQubGsifQ.signature
2019-01-23 16:17:14 DEBUG - successful authorized
2019-01-23 16:17:14 TRACE - checking whether to refresh.
2019-01-23 16:17:14 TRACE - useResourceRoleMappings
2019-01-23 16:17:14 TRACE - Setting roles: 
2019-01-23 16:17:14 DEBUG - Completing bearer authentication. Bearer roles: [] 
2019-01-23 16:17:14 DEBUG - User '1fb59f22-a332-4b7f-bd38-c193dba24d99' invoking 'http://localhost:8080/error' on client 'my-react-client'
2019-01-23 16:17:14 DEBUG - Bearer AUTHENTICATED
2019-01-23 16:17:14 DEBUG - Auth outcome: AUTHENTICATED
2019-01-23 16:17:14 DEBUG - Authentication success using bearer token/basic authentication. Updating SecurityContextHolder to contain: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@93251b1b: Principal: 1fb59f22-a332-4b7f-bd38-c193dba24d99; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@13c4eea7; Not granted any authorities
2019-01-23 16:17:14 DEBUG - AuthenticatedActionsValve.invoke http://localhost:8080/error
2019-01-23 16:17:14 DEBUG - Policy enforcement is disabled.

Here is my Spring SecurityConfig java file.

@KeycloakConfiguration
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {


    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }


    @Bean
    public KeycloakConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }
//    FilterRegistrationBean to avoid Bean duplicate registrations
    @Bean
    public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(
            KeycloakAuthenticationProcessingFilter filter) {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
        registrationBean.setEnabled(false);
        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(
            KeycloakPreAuthActionsFilter filter) {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
        registrationBean.setEnabled(false);
        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean keycloakAuthenticatedActionsFilterBean(
            KeycloakAuthenticatedActionsFilter filter) {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
        registrationBean.setEnabled(false);
        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean keycloakSecurityContextRequestFilterBean(
            KeycloakSecurityContextRequestFilter filter) {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
        registrationBean.setEnabled(false);
        return registrationBean;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);

        http.authorizeRequests()
                .antMatchers("/api/**").hasRole("admin")
                .anyRequest().authenticated();

        http.csrf().disable();

    }
}

This is my user's roles look like.

Keycloak user

This is how my OAuth2 token request in Postman looks like

Postman OAuth2 token request

Client Settings

enter image description here

enter image description here

Credentials set to Client Id and Secret Roles have admin role. enter image description here

enter image description here

Postman Configurations

Postman Keycloak configurations

3

3 Answers

2
votes

In case someone else still have this problem, you need to create the role under the "client" (clients->{your client}->roles->add role) and not the "realm".

Then assign the client role to the user.

example: user role assignment

this is my token content:

{...
,
  "realm_access": {
    "roles": [
      "offline_access",
      "uma_authorization",
      "user" // not visible in spring security
    ]
  },
  "resource_access": {
    "backstage-api": {
      "roles": [
        "user" // visible in spring security
      ]
    },
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },
...
}

Spring boot logg:

"Completing bearer authentication. Bearer roles: [user] "

I hope someone finds this useful. :)

1
votes

I'd suggest you to test your endpoint using a GET request (instead of POST, PUT, PATCH or any other unsafe verb). If this works, then your 403 is not related to keycloak or your access-token, but is related to the csrf (cross site request forgery) check that spring security activates as a default behaviour for all non safe verbs.

Some weeks ago I had a similar problem, check it here: by securing and endpoint with a role, works for GET methods bot not POST, I receive 403 Forbiden . If this is indeed the problem, a solution is also presented there.

Note: If your GET endpoint gets the same 403, then the problem is related to the role not being present in your token. In this page: https://jwt.io/ , you have an access-token decoding tool that can help you visualize the contents of your token with all its claims, so it'll be easy for you to check if the desired role is not present.

Hope it helps!

EDIT: Actually you are disabling csrf in your config:

http.csrf().disable();

So it seems unrelated to a csrf check. Use the tool above to see the contents of your token and verify it contains the role that protects that endpint. Even if your role is present, check if you have it under "realm_access" or "resource_access". If you have it under "resource_access", you'll need to add to your application properties the following line:

keycloak.use-resource-role-mappings=true

if you have the role under "realm_access", then you either delete the line above, or set it to false:

keycloak.use-resource-role-mappings=false

0
votes

Looks like your bearer token does not contain any role and your service need the role "admin", this is why you get a 403. Does your user that has obtained the token have roles assigned ?