Coder Social home page Coder Social logo

Client roles mock about spring-addons HOT 6 CLOSED

ch4mpy avatar ch4mpy commented on June 3, 2024
Client roles mock

from spring-addons.

Comments (6)

ch4mpy avatar ch4mpy commented on June 3, 2024

Short answer: @WithMockKeycloakAuth({"ADMINISTRATOR", "DRIVER"}) just above your @Test as demonstrated in samples and on stackoverflow answers.

Long answer: authorities (in Spring-security world a role is an authority prefixed with ROLE_) are populated from a JWT by an authorities converter. Keycloak get authorities from different claims to retrieve realm roles and client roles. You need to explore Keycloak sources (starting from KeycloakWebSecurityConfigurerAdapter) if you are interested in figuring out how this is exactly done.

In your sample, you are setting roles in a claim named resource_access.ace-ella-ecosystem.roles (yes, a claim name is a JSON string and yes, JSON string can contain dots) when keycloak expects a roles string-array claim inside a ace-ella-ecosystem claim-set itself inside a resource_access claim-set. As this is pretty cumbersome to declare with @ClaimSet and @StringArrayClaim (not @StringClaim as you did), I recently created a @JsonObjectClaim that works close to what you wrote. But the simple sollution to set authorities is clearly to use authorities property on @WithMockKeycloakAuth.

from spring-addons.

cvetan avatar cvetan commented on June 3, 2024

@ch4mpy I still get 403 even with your example.

The test:

@Test
    @WithMockKeycloakAuth({"ADMINISTRATOR", "DRIVER"})
    void exampleTest() throws Exception {
        var uri = URI.create("/v1/support");

        mockMvc.perform(
                        MockMvcRequestBuilders.post(uri)
                )
                .andExpect(MockMvcResultMatchers.status().isOk());

    }

However since we are using client roles, we have this in configuration:

keycloak:
  auth-server-url: ${KEYCLOAK_AUTH_SERVER_URL}
  realm: ${KEYCLOAK_REALM}
  resource: ${KEYCLOAK_RESOURCE}
  public-client: true
  ssl-required: external
  bearer-only: true
  use-resource-role-mappings: true

from spring-addons.

ch4mpy avatar ch4mpy commented on June 3, 2024

Had missed

simpleAuthorityMapper.setPrefix("ROLE_");

Have you tried @WithMockKeycloakAuth({"ROLE_ADMINISTRATOR", "ROLE_DRIVER"}) ?

from spring-addons.

cvetan avatar cvetan commented on June 3, 2024

Thanks, that works. I haven't though about it, because token has roles without prefix. I can't believe solution was this simple. 😄

Anyways everything works, thank you very much, you helped a lot. 🍺

from spring-addons.

cvetan avatar cvetan commented on June 3, 2024

Hi, @ch4mpy me again :D

I have slightly more complicated use case now, I need to check role inside some service class and I do that like this:

var allowedRoles = getAllowedRoles().stream()
                .map(UserRole::toString)
                .collect(Collectors.toSet());
        var userRoles = accessToken
                .getResourceAccess(keycloakResource)
                .getRoles();

However when this code runs inside test, I get following exception:

             Body = {"error_code":null,"error_description":null,"exception_class":"java.lang.NullPointerException","exception_message":"Cannot invoke \"org.keycloak.representations.AccessToken$Access.getRoles()\" because the return value of \"org.keycloak.representations.AccessToken.getResourceAccess(String)\" is null"}

I tried following your advice from first message to this question (about nesting claims resource_access -> resource_id -> roles), however I can't seem to understand that approach nor how to nest them. You mentioned something about json object claim, so maybe that is the right way, but if you could tell me something more or just point me in right direction I would apreciate it.

Thanks

from spring-addons.

ch4mpy avatar ch4mpy commented on June 3, 2024

If you want a RessourceAccess to be be populated in your tests, you just need to populate it with something like:

@WithMockKeycloakAuth(accessToken = @KeycloakAccessToken(resourceAccess = @KeycloakResourceAccess(resourceId = "demo", access = @KeycloakAccess(roles = {"machin", "truc"}))))

Setting authorities with @WithMockKeycloakAuth can't populate claims. Keycloak-spring adapter retrieves authorities from several places: at least "client roles" (by default resource_access.{clientId}.roles) and "realm roles" (by default realm_access.roles).

I write "by default", because this is configurable with mappers and can actually be set to about anything.

I have a strong recomandation for you: use direct claim access for stuff that are neither authorities nor standard OpenID claims (subject, preferredUserName, etc.).
The mapping from claims to authorities should be made in spring security conf.
Access to authorities in your application code should be done exclusively with KeycloakAuthenticationToken::getAuthorities.

=> Read Keycloak doc to figure out how to map your Keycloak "roles" claims to Spring "authorities" and then use:

  • keycloakAuthenticationToken.getAuthorities() in your application code (that's what do implicitely @PreAuthorise(hasAnyAuthority(...)) and @PreAuthorise(hasAnyRole(...)))
  • @WithMockKeycloakAuth(authorities= {...}) in your tests

from spring-addons.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.