1

We have the issue of testing the validity of our security expressions.

In tests, we are using an unsecured profile, meaning that method security is disabled. This was done at the start of the project to facilitate faster testing, due to correct (permission-wise) data being difficult to produce at the time. We also have a standard testing profile where security is enabled, which is used for separate 'security' tests.

It can happen that a developer refactors something (i.e. parameter name in method) yet neglects to update the permission expression. Not often, but it is still a source of errors.

I had the idea of scanning all methods on startup and looking for those which have a PreAuthorize("hasPermission(...)) annotation, and then using a SpelExpressionParser together with the proper MethodInvocation to verify the permission expression in the correct EvaluationContext. Unfortunately, I got as far as the PreInvocationExpressionAttribute which is a package-protected class - meaning my solution nor the intent behind it is not at all one that would be supported by the framework.

Having the following requirements in mind:

  • the application still has several legacy components which make it difficult to set up a proper authentication context (due to DB constraints as most domain tests are integration tests using an embedded DB),

  • writing tests for all cases is unrealistic, as there are already numerous roles with separate permissions (and more will come) which would necessitate duplication of many lines of code,

  • Ideally, the solution would get the list of security roles available and verify that both only the correct role can do it, and that the expression is valid,

what would be some good ways to achieve permission expression validity checking transparently without much overhead for the developer writing the tests?

filpa
  • 3,651
  • 8
  • 52
  • 91

1 Answers1

2

Spring gives you such tools (see @WithMockUser, @WithAnonymousUser, @WithUserDetails) with this annotations you just need create application context and add appropriate annotation to your test method and with the normal tests also the security level will be tested:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration 
public class WithMockUserTests {
    @Test
    @WithMockUser(username="admin",roles={"USER","ADMIN"})
    public void getMessageWithMockUserCustomUser() {
        String message = messageService.getMessage();
        ...
    }
}

and if the code you are testing are using @PreAuthorize ... methods or SecurityContextHolder.getContext() the user which you specified in the annotation will be given.

If there is a little complicated security flow, you can also create SecurityContextFactory for test with @WithSecurityContext.

You can use such approach also with mockMvc Run unit tests on controllers that require authentication.

But if you are testing the application without spring's testing tools (like MockMvc ...) for ex. with RestTemplate or RestAssure, then the best approach is overwriding the security configuration in your test and using the users from the new configuration

    @TestConfiguration
    @Order(1)
    @EnableGlobalMethodSecurity(prePostEnabled=true)
    static class TestSecurityConfiguration extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http....
        }
    } 
Andrew Sasha
  • 1,254
  • 1
  • 11
  • 21
  • Thank you for the information. I've begun to implement this in some of my test cases, and so far it seems quite useful. However, do you have an idea of how this might address integration test cases where multiple roles need to be used? For example: an integration test creates some data unit. Afterwards, the unit is edited with the user that has edit permissions. In this case, would it make sense to refactor tests completely to have the creation be part of a 'before' step? I would imagine these annotations work pretty well with Cucumber (though I dislike it). – filpa Jan 15 '19 at 08:40
  • I ended up extending the classes that the test security package has to offer and am quite pleased with the results. Thank you. – filpa Jan 30 '19 at 09:23