4

Some background: we have an integration test class that is used to test constant SPEL strings used with Spring authorization. Simple example:

@SpringBootTest
@RunWith(SpringRunner.class)
public class HasRoleConstantsTest {
    @Test
    @WithMockUser(username = "uname", roles = "ADMIN")
    public void test() {
        // just calling some test method with appropriate annotation
    }
}

Beforementioned constants are used like:

@PreAuthorize(PREDEFINED_AUTHORIZATION_RULE)

where constant could be some bit more complex checks like:

public static final String PREDEFINED_AUTHORIZATION_RULE =
    "hasRole('ADMIN') OR (hasRole('MAINTAINER') AND hasRole('#id'))"

We have configured our WebSecurityConfiguration as suggested here so adding bean like:

@Bean
GrantedAuthorityDefaults grantedAuthorityDefaults() {
    return new GrantedAuthorityDefaults(""); // Remove the ROLE_ prefix
}

Everything works like a charm except that test like shown at the top of the post fails because in test environment Spring security still adds prefix ROLE_ to each mock users role.

Could someone shed some light on how test class should be configured or - for example - how the SecurityContext should be manipulated to get rid of this prefix also on test?

pirho
  • 11,565
  • 12
  • 43
  • 70
  • 4
    Use the `authorities` instead of `roles` properties in the `@WithMockUser` annotation. – M. Deinum Aug 02 '19 at 10:08
  • @M.Deinum Thanks it seemed to resolve the problem. Should have tried that also myself but missed that property somehow :). If you are willing to provide this as an answer and preferably with some explanation I will at least upvote it. Of course the best answer would be that there was a way to make it like in the production code but for us this is sufficient for now. – pirho Aug 02 '19 at 10:21
  • 1
    `hasRole` and `hasAuthority` are the same, with this difference that `hasRole` adds the prefix (unless you disable it). So in your production code instead of using `hasRole` using `hasAuthority` will save you configuring the role prefix all together. – M. Deinum Aug 02 '19 at 14:08

2 Answers2

5

It is very simple, open javadoc of this annotation and use authorities instead of roles

0

This works fine for me:

configuration:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class GlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    private final ApplicationContext context;

    @Autowired
    public GlobalMethodSecurityConfig(ApplicationContext context) {
        this.context = context;
    }

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler handler = 
            new DefaultMethodSecurityExpressionHandler();

        handler.setDefaultRolePrefix("");
        handler.setApplicationContext(context);
        return handler;
    }
}

tests:

@Test
@WithMockUser(roles = "USER")
void getCard() {
    ...
}

if that's doesn't help, can you show a working sample of code on GitHub? (it may help to find a problem)