Test Spring MVC controller with @PreAuthorize giving 403-Access denied
Asked Answered
S

0

4

trying to write some integration test with Spock framework for my controller that has @PreAuthorize annotation on it. When I run the app, this tag is working like a charm. However, when I run integration test I get 403.

My SecurityConfig.java:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
            .antMatchers("/test/**")
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .csrf().disable(); 
      }
    @Bean
    @Override
    protected AuthenticationManager authenticationManager() {
        return new   ProviderManager(Arrays.asList(getAuthenticationProvider()));
    }

}

My Controller:

@RestController
@Validated
@RequestMapping("/test")
public class TestController  {


    @PreAuthorize("hasPermission(#object, '')")
    @RequestMapping(method = RequestMethod.POST,
                    consumes = MediaType.APPLICATION_JSON_VALUE,
                    produces = MediaType.APPLICATION_JSON_VALUE,
                    headers = { "Accept=application/json", "Content-Type=application/json" })
    public ResponseEntity<List<String>> testController(@RequestBody @Valid TestObject object,
            @RequestHeader(ACCOUNT) String account)
            throws ResourceNotFoundException, ServletRequestBindingException,
            MethodArgumentNotValidException, NoSuchMethodException, SecurityException {
//return statement here!!
        }
}

and my PermissionEvaluator impl as follows:

@Component
public class TestPermissionEvaluator implements PermissionEvaluator {

        private HttpServletRequest request;
        private TestRepository<AccountRoles> repository;

@Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object
                    permission) {
            AccountRole accountRole;
            TestObject object = (TestObject) targetDomainObject;
                try {
                    accountRole = repository.find(object.getAccountID(), id);
                } catch (ResourceNotFoundException e) {
        //      throw new Exception here
                }

                return true;
            }

            @Override
            public boolean hasPermission(Authentication authentication, Serializable targetId, String
                    targetType, Object permission) {
                return false;
            }
        }

And finally my test class looks as follows:

@ContextConfiguration(locations = ['file:src/main/webapp/WEB-INF/spring/testWebmvc-config.xml',
    'file:src/main/webapp/WEB-INF/spring/appContext/servlet-context.xml'])
@WebAppConfiguration
public class TestControllerIntegration extends Specification {

    TestController controller
    MockMvc mockMvc

    @Inject
    WebApplicationContext wac


    @Inject
    ObjectMapper mapper

    @Autowired
    private FilterChainProxy filterChainProxy

    def setup() {
        controller = new TestController()
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(filterChainProxy).apply(SecurityMockMvcConfigurers.springSecurity()).build()
        SecurityContextHolder.clearContext()
        SecurityContextHolder.getContext().setAuthentication(new TestAuthenticationToken("145214741"))
    }

    @Unroll
    def 'valid post to /test'() {

        when:
        MvcResult result = mockMvc.perform(post('/test').
            content(readJsonFromFile(jsonFileLocation)).
            contentType(APPLICATION_JSON).
            header('account', account).
            accept(APPLICATION_JSON)).
            andDo(print()).
            andReturn()
        then:
        def ids = mapper.readValue(result.response.getContentAsString(), List.class)

    }

Everytime I try to run this test i get a 403 with following stacktrace:

MockHttpServletResponse:
           Status = 403
    Error message = Access Denied
          Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY]}
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
 at [Source: ; line: 1, column: 1]

What am I missing here, thanks in advance!!

South answered 28/3, 2017 at 15:20 Comment(2)
Have you tried adding som logging to your PermissionEvaluator to see if it is called?Ayakoayala
#29511259. This answer was based on this approach: docs.spring.io/spring-security/site/docs/4.0.x/reference/…Katelyn

© 2022 - 2024 — McMap. All rights reserved.