0

I have an app that previously was running tests using Spring Boot 1 and which I have updated to 2.0.9.RELEASE.

There are now issues with Spring Security. I know this is the case because if I remove

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <scope>test</scope>
</dependency>

(and any new WebSecurityConfigurerAdapter classes) the tests still succeed. The tests are essentially going to a project controller 'HomeController' and from there going to a service and using a RestTemplate to perform various operations. In reality this is a different app, and if I were writing it from scratch, I would probably do a wiremock but for now and the purposes of this question there is a controller in the test package simulating the required behaviour.

By adding this simple class, I have got past the 403 on the local controller

@TestConfiguration
@EnableWebSecurity
@Order(500)
public class DefaultSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure( HttpSecurity http) throws Exception{
        http.authorizeRequests().antMatchers("/").permitAll();
    }
}

However, I'm struggling to get past the security on using the RestTemplate. The restTemplate bean is created with basic user and password (simplified a little here)

@Bean
public RestTemplate restTemplate( RestTemplateBuilder restTemplateBuilder ) {
    return restTemplateBuilder
            .basicAuthorization( "user", "password" )
            .build();
}

I can tell by debugging and looking at the interceptors that these are being set.

Now I have added a new configuration class

@TestConfiguration
@EnableWebSecurity
@Order (50)
public class RestTemplateSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure( AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder encoder =
            PasswordEncoderFactories.createDelegatingPasswordEncoder();

        auth.inMemoryAuthentication()
            .withUser("user")
            .password(encoder.encode("password"))
            .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests().antMatchers("/otherpath/**")
            .authenticated()
            .and()
            .httpBasic();

    }
}

But this seems to have no effect on the RestTemplate calls which are consistently called with basic security of user and password and consistently return 403 Forbidden.

The test class is annotated like this

@AutoConfigureMockMvc
@RunWith( SpringRunner.class )
@SpringBootTest( classes = { DefaultSecurityConfiguration.class, ResttemplateSecurityConfiguration.class }, webEnvironment = DEFINED_PORT ) 
@TestPropertySource( "classpath:test.properties" )
public class HomeControllerTest {
...

And triggered with a 'standard' mockMvc.perform( ...

With the DefaultSecurityConfiguration class in place these fire without issue it is the later calls in the app code using the restTemplate that fail

Is there anything obvious?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
gringogordo
  • 1,990
  • 6
  • 24
  • 60
  • 2
    This may help you https://stackoverflow.com/questions/19468209/spring-security-403-error – Mohamed Ismail M Mar 24 '21 at 10:09
  • Thanks for info on the previous answer. Thought I'd read them all but missed this one. Seems to be the issue. I actually don't seem to need the more complex auth config at all just disable csrf! Thanks. – gringogordo Mar 24 '21 at 12:23

1 Answers1

1

Replace:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests().antMatchers("/otherpath/**")
        .authenticated()
        .and()
        .httpBasic();

}

By this:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests().antMatchers("/otherpath/**")
        .authenticated()
        .and()
        .httpBasic();
    http.csrf().disable();
}
  • 1
    If anyone uses this later actually all I needed was to add and().csrf().disable(); to my DefaultSecurityConfiguration class. – gringogordo Mar 24 '21 at 12:25