1

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

Menuka Ishan
  • 5,164
  • 3
  • 50
  • 66

4 Answers4

3

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. :)

Anthon
  • 31
  • 2
  • Something went wrong during my tests with client. I did some renaming and randomly clicked role menus. I had to create client from scratch and it worked with client roles. Use `clients->your-client->scopes->evaluate->generated access token` to verify you have your resource roles inside token. – simno Jul 16 '21 at 16:36
1

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

tony _008
  • 647
  • 6
  • 19
0

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 ?

Sébastien Blanc
  • 2,929
  • 1
  • 12
  • 11
  • Can you explain how to add that role? Because my user has the role "admin". I don't know how to add roles to bear roles – Menuka Ishan Jan 24 '19 at 10:10
  • It should just be added to your access token without any thing to do, is it a realm role ? Could you also tell me which version of keycloak you are using ? – Sébastien Blanc Jan 24 '19 at 11:02
  • I am using `Keycloak 4.7.0.Final ` I know about the user role in client but not the Bear roles. So I updated question the with details which I though would be helpful. Please help :) – Menuka Ishan Jan 24 '19 at 11:26
  • Could you also share your client configuration ? – Sébastien Blanc Jan 24 '19 at 12:27
  • It is probably a `id_token`, not a real `access_token`. Unfortunately, your question doesn't contain information about used `response_type`. – Jan Garaj Jan 24 '19 at 21:10
  • @SébastienBlanc I updated the question with client details. Please help – Menuka Ishan Jan 25 '19 at 07:42
  • @JanGaraj Where I can find `response_type` details? :O – Menuka Ishan Jan 25 '19 at 07:42
  • It should be in your postman query. But from the question it is not clear which flow and request are you using to get token. – Jan Garaj Jan 25 '19 at 07:57
  • @JanGaraj I updated the question with Postman configurations. Can you check it please? – Menuka Ishan Jan 25 '19 at 09:13
  • 1
    You are using Client Credentials Grant type. Try to use Authorization Code Grant Type. – Jan Garaj Jan 26 '19 at 08:06
  • I tried it. It open a web page Postman I might use wrong Auth URL. I took it from https://stackoverflow.com/a/28673597/2940265 My Auth URL look like http://localhost:8180/auth/realms/MyDemo/tokens/login is this a wrong url for Postman? – Menuka Ishan Jan 28 '19 at 05:13
0

If GET request works fine and other methods(POST,PUT,DELETE, PATCH) results to error code 403, 401. Just disable csrf (cross site request forgery) by adding http.csrf().disable(); in your configure method. See source code in the snapshot here

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 22 '22 at 13:54