ch4mpy / spring-addons

Ease spring OAuth2 resource-servers configuration and testing
Apache License 2.0
557 stars 90 forks source link

Error when using @WithMockKeycloakAuth #34

Closed KasperVaessen closed 2 years ago

KasperVaessen commented 2 years ago

Describe the bug When I use the @WithMockKeycloakAuth tag above my test, I get the following error:

java.lang.NoSuchMethodError: 'void org.keycloak.representations.AccessToken$Authorization.setPermissions(java.util.Collection)'
    at com.c4_soft.springaddons.security.oauth2.test.annotations.keycloak.AccessTokenBuilderHelper.authorization(AccessTokenBuilderHelper.java:61) ~[spring-security-oauth2-test-addons-3.1.5-jdk17.jar:na]
    at com.c4_soft.springaddons.security.oauth2.test.annotations.keycloak.AccessTokenBuilderHelper.feed(AccessTokenBuilderHelper.java:36) ~[spring-security-oauth2-test-addons-3.1.5-jdk17.jar:na]
    at com.c4_soft.springaddons.security.oauth2.test.annotations.keycloak.WithMockKeycloakAuth$Factory.lambda$authentication$0(WithMockKeycloakAuth.java:109) ~[spring-security-oauth2-test-addons-3.1.5-jdk17.jar:na]
    at com.c4_soft.springaddons.security.oauth2.test.keycloak.KeycloakAuthenticationTokenTestingBuilder.accessToken(KeycloakAuthenticationTokenTestingBuilder.java:79) ~[spring-security-oauth2-test-addons-3.1.5-jdk17.jar:na]
    at com.c4_soft.springaddons.security.oauth2.test.annotations.keycloak.WithMockKeycloakAuth$Factory.authentication(WithMockKeycloakAuth.java:109) ~[spring-security-oauth2-test-addons-3.1.5-jdk17.jar:na]
    at com.c4_soft.springaddons.security.oauth2.test.annotations.keycloak.WithMockKeycloakAuth$Factory.createSecurityContext(WithMockKeycloakAuth.java:101) ~[spring-security-oauth2-test-addons-3.1.5-jdk17.jar:na]
    at com.c4_soft.springaddons.security.oauth2.test.annotations.keycloak.WithMockKeycloakAuth$Factory.createSecurityContext(WithMockKeycloakAuth.java:84) ~[spring-security-oauth2-test-addons-3.1.5-jdk17.jar:na]
    at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.lambda$createTestSecurityContext$0(WithSecurityContextTestExecutionListener.java:123) ~[spring-security-test-5.6.0.jar:5.6.0]
    at ...

It seems that the .setPermissions method expects a list instead of a collection.

Code sample I use Keycloak 15

Test:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = {Application.class})
@Transactional
@AutoConfigureMockMvc
@Import({ KeycloakSpringBootConfigResolver.class })
public class ProjectControllerTest {

        ...

        @Test
        @WithMockKeycloakAuth
        public void getExistingProject() throws Exception {
            mvc.perform(get("/projects/1"))
                .andExpect(status().isOk());
        }
}

SecurityConfig:

@KeycloakConfiguration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        // securedEnabled = true,
        // jsr250Enabled = true,
        prePostEnabled = true)
@Import(KeycloakSpringBootConfigResolver.class)
public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        // adding proper authority mapper for prefixing role with "ROLE_"
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

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

    @Bean
    public org.keycloak.adapters.KeycloakConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.cors().and().csrf().disable()
                .authorizeRequests()
                .anyRequest().authenticated();
    }

}

Expected behavior I would expect no error. Do I need a specific version of something?

ch4mpy commented 2 years ago

This is quite strange: AccessTokenBuilderHelper.java:61 provides explicitely Authorization::setPermissions with a List<Permission> which is (implements) a Collection<Permission>

Do you have executable code somewhere?

If not, could you clone my repo and update com.c4_soft.springaddons.samples.webmvc.keycloak.KeycloakSpringBootSampleApp to reproduce? (currently the tests pass...)

ch4mpy commented 2 years ago

By the way, @KasperVaessen , did you carfully inspect your test classpath? Have you double checked the version of the keycloak-core that is loaded?

Maybe you did not include keycloak dependencies explicitly in your project and it is just missing when your test run: in this repo, Keycloak dependencies are flagged as optional => you must reference keycloak libs explicitely if you use it.

Libs in this repo can be used without Keycloak libs (I personally don't use Keycloak libs any more), reason for keycloak being flaged as optional here.

You could try with somthing like that in your pom:


    <properties>
        <com.c4-soft.springaddons.version>3.1.7-jdk1.8-SNAPSHOT</com.c4-soft.springaddons.version>
        <keycloak.version>15.0.2</keycloak.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.keycloak.bom</groupId>
                <artifactId>keycloak-adapter-bom</artifactId>
                <version>${keycloak.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.c4-soft.springaddons</groupId>
                <artifactId>spring-security-oauth2-test-addons</artifactId>
                <version>${com.c4-soft.springaddons.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-security-adapter</artifactId>
            <optional>false</optional><!-- default value is false, so removing this tag should work as well -->
        </dependency>
        <dependency>
            <groupId>com.c4-soft.springaddons</groupId>
            <artifactId>spring-security-oauth2-test-addons</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
KasperVaessen commented 2 years ago

Thanks for both your replies! It was indeed a problem with my keycloak version. I used a dependencyManager which set the keycloak version to 4.0.0.FINAL. I oversaw this. Sorry for the trouble an thank you so much for your help!