Spring Verify OAuth Integration and Boot

What is the best way to start Spring? Boot integration tests are again configured on the web application configured by the OAuth Resource server.

I can imagine two theoretical approaches:

  • Refuse the security context on the resource server without directly invoking the authorization server.
  • Insert the authorization server as part of the test and redirect authentication to it.

I was wondering how others approach this problem.

+3
source share
2 answers

I am using spring security 4.x @WithSecurityContext('user') annotation to create a mock SecurityContext with 'user' logged in. Then, when calling my REST API using MockMvc I retrieve the SecurityContext and attach it to the call,

Like this:

 @Test @Transactional @WithSecurityContext('user') public void getAllParcels() throws Exception { // Initialize the database long size = parcelRepository.count(); parcelRepository.saveAndFlush(parcel); // Get all the parcels restParcelMockMvc.perform(get("/api/parcels").with(security())) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.[" + size + "].id").value(parcel.getId())) .andExpect(jsonPath("$.[" + size + "].lot").value(DEFAULT_LOT)) .andExpect(jsonPath("$.[" + size + "].localName").value(DEFAULT_LOCAL_NAME)); } 

where security() is the static method:

 public static RequestPostProcessor security() { return SecurityMockMvcRequestPostProcessors.securityContext(SecurityContextHolder.getContext()); } 

Thus, for my testing method, @WithSecurityContext('user') mock SecurityContext with an authenticated user with the username 'user' . Then in this method, I extract this SecurityContext layout and attach it to the REST API call to make my oAuth think the user is fully authenticated. This is basically the first approach you suggested in your question.

For this to work, you must switch your OAuth to a state sufficient for tests. Otherwise it will not work.

those. like this:

 @Configuration public class OAuth2ServerConfiguration { @Configuration @EnableResourceServer protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Autowired(required = false) @Qualifier("oauth2StatelessSecurityContext") private Boolean stateless = Boolean.TRUE; // STATEFUL switching for tests! @Inject private Http401UnauthorizedEntryPoint authenticationEntryPoint; @Inject private AjaxLogoutSuccessHandler ajaxLogoutSuccessHandler; @Override public void configure(HttpSecurity http) throws Exception { http .exceptionHandling() .authenticationEntryPoint(authenticationEntryPoint) .and() .logout() .logoutUrl("/api/logout") .logoutSuccessHandler(ajaxLogoutSuccessHandler) .and() .csrf() .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")) .disable() .headers() .frameOptions().disable().and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers("/api/authenticate").permitAll() .antMatchers("/api/register").permitAll() .antMatchers("/api/logs/**").hasAnyAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/api/**").authenticated() .antMatchers("/metrics/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/health/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/dump/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/shutdown/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/beans/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/configprops/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/info/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/autoconfig/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/env/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/api-docs/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/protected/**").authenticated(); } @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.stateless(stateless); super.configure(resources); } } ... 

You see my stateless property, which is introduced only in the test. In normal mode, it uses the default value of true (therefore, it has no state). For tests, I declare an oauth2StatelessSecurityContext Bean with false to make it statefull for tests.

I define this configuration for tests:

 @Configuration public class OAuth2Statefull { @Bean @Primary public Boolean oauth2StatelessSecurityContext() { return Boolean.FALSE; } } 

How i did it. I hope my explanation is clear.

+4
source

This answer is very similar to the one provided by Ondrej, but a bit simpler.

Spring Security 4 provides testing support. To use it, you have spring -security-test-4.0.2.RELEASE.jar (or a newer version in your classpath). You will also want to make sure that you are working with spring -test-4.1.0.RELEASE (or newer).

Next you can use MockMvc as another answer indicates. However, if you installed MockMvc with the following:

 import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @WebAppConfiguration public class OAuthTests { @Autowired private WebApplicationContext context; private MockMvc mvc; @Before public void setup() { mvc = MockMvcBuilders .webAppContextSetup(context) // ADD THIS!! .apply(springSecurity()) .build(); } 

It does so

  • You no longer need to worry about working in stateless mode or not
  • It also means that you do not need to use apply (springSecurity ()) as indicated in another answer.

In short, you should do something like this:

 @Test @WithSecurityContext('user') public void performOAuth() throws Exception { ... // No need for apply(security())!! restParcelMockMvc.perform(get("/api/some-resource")) .andExpect(...); } 

I would advise you to read the rest of Spring’s Security Testing section of the link, as it provides a lot of additional information including the use of user authentication.

+12
source

All Articles