I'm using spring OAuth2 and JWT tokens to secure an application. I am extending org.springframework.security.core.userdetails in order to add some additional attributes to the token which can then be used to perform authorization ones an endpoint is called.
public class CustomUser extends User {
private Set<String> bookIds;
public CustomUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
public CustomUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
}
}
I also have a custom implementation of org.springframework.security.access.PermissionEvaluator which is able to deserialize the token and check that the custom attributes are part of it which can be added to controller endpoints as such.
@PreAuthorize("hasPermission(authentication, #bookId,'read')")
Now it all works fine, I can test my application through postman and only users with a valid JWT token that has bookID in the URL part of their bookIds set can access the resource as such
@PreAuthorize("hasPermission(authentication, #bookId,'read')")
@GetMapping(value = "api/books/{bookId}")
public Book getBook(@PathVariable String bookId) {}
HOWEVER, I'm struggling to test this as this is part of a microservice application where authentication and services are not part of the same project and would run on separate VMs. IDEALLY, i'd like to be able to mock the token in each of the services and add whatever values I need inside of this bookId set. I know that after spring 4 we can use @WithMockUser, however, from what I can tell this is limited to username/password/role/authority, e.g. :
@WithMockUser(username = "ram", roles={"ADMIN"})
What I'd really like to do is either extend this annotation to support my custom attribute 'bookId' or a way to inject a mock set in it. Is this possible, and if not, what are my alternatives, as I wouldn't be able to call my authentication provider in my unit tests as the implementation would live in another spring context hosted on a separate app.
Many thanks in advance !