Spring security adapter roles

Hi guys, I have a quick question about Roles
When I use the hasRole() method or hasAuthority() method of spring security, it only checks with the client roles assigned to the user and it doesn’t care about the Realm roles . I don’t know if this is supposed to be the normal behaviour or there’s something wrong with my code.
I couldn’t find an answer to this nowhere
I’m really thankful for your help guys

1 Like

use-resource-role-mappings will look on the resource level for roles when set true and on the realm level when set to false.
I think if you need them both you will need a custom role mapper in your security config.
I could be wrong though and maybe there is an easier solution to your problem.

1 Like

Thanks a lot man.
Anyone has any idea how I could use both type of roles?

Maybe you don’t have to, check out role mapping in Keycloak, didn’t work with it yet but looks a solution for you without touching your own code.

1 Like

I’m using pure Spring Security, without Keycloak adapters.
For parsing the token I have the following code (oidcClient is the client name, and is configured on the application):

//Specific converter for JWTs emitted from keycloak with our configuration.
//This is vendor-specific structures on top of base ODIC specification
class KeycloakJwtAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken> {
	private static final String ROLES = "roles";
	private static final String RESOURCE_ACCESS = "resource_access";
	private Converter<Jwt, Collection<GrantedAuthority>> jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();

	protected Collection<GrantedAuthority> extractAuthorities(Jwt theJwt) {
		if (theJwt != null) {
			JSONObject keycloakClientAuthorities = ((JSONObject) theJwt.getClaimAsMap(RESOURCE_ACCESS).get(oidcClient));
			if (keycloakClientAuthorities != null) {
				JSONArray clientRoles = (JSONArray) keycloakClientAuthorities.get(ROLES);

				if (clientRoles != null) {
					Collection<GrantedAuthority> clientAuthorities = clientRoles.stream()
							.map(aRole -> (String) aRole)
							.map(SimpleGrantedAuthority::new)
							.collect(Collectors.toList());

					clientAuthorities.addAll(jwtGrantedAuthoritiesConverter.convert(theJwt));

					return clientAuthorities;
				}
			}

		}
		return jwtGrantedAuthoritiesConverter.convert(theJwt);
	}
}
1 Like

I found a workaround for this (thanks to zonaut’s hint )
The solution I found is to set the use-resource-role-mappings property to false and then map the client client roles under the realm roles…
As functionnal as this workaround may seem, I’m wondering , from a security point of view, if this may cause future security issues especially for microservices architectures where there are some confidential clients allowed to do the authentication process and other bearer-only services that are just validating the propagated token?

Can’t you do it the other way around, map realm roles to the resource (client)?

1 Like

Yeah, that might be a little bit more secure I guess

Can you please share more details how did you do this? I’m interested mainly in part where you’ve mapped realm roles to client.
Another question would be, didn’t you tried to also map scopes somehow?

Thanks in advance

Sorry for the late response,
To answer your question about mapping realm roles to client role:

  1. Open your keycloak admin dashboard
  2. Go to Clients and click on the client you want to map your realm role to it
  3. Go to Mappers tab and create a new mapper
  4. Under Mapper Type choose User Realm Role
    And under Token Claim Name type resource_access.${client_id}.roles

How You are using this ? could you please send the whole code in the configuration