0

In my Spring Boot application I have a REST controller with a following method:

@PreAuthorize("hasAnyRole('PERMISSION_UPDATE_OWN_COMMENT', 'PERMISSION_UPDATE_ANY_COMMENT')")
@RequestMapping(value = "/update", method = RequestMethod.POST)
public CommentResponse updateComment(@AuthenticationPrincipal User user, @Valid @RequestBody UpdateCommentRequest commentRequest) {
    Comment comment = commentService.updateComment(commentRequest.getCommentId(), commentRequest.getTitle(), commentRequest.getContent(), user);
    return new CommentResponse(comment);
}

Only users with PERMISSION_UPDATE_OWN_COMMENT or PERMISSION_UPDATE_ANY_COMMENT are allowed to use this endpoint.

Inside of this method I need to create two different flows - one for users with PERMISSION_UPDATE_OWN_COMMENT and another one for users with PERMISSION_UPDATE_ANY_COMMENTpermissions.

So my question is - what is best practice for Spring security in order to implement these different flows of logic inside of the single method ?

Should I validate inside of the updateComment method that the user has one or another permission and based on this condition implement my logic ?

alexanoid
  • 24,051
  • 54
  • 210
  • 410
  • Another approach would be to extend the request mapping mechanism so that you could implement a separate method for each role. See here for a starting point:http://stackoverflow.com/a/18313976/1356423. There also seems to be a project here with an example of a custom 'RoleMapping' annotation which seems exactly what you need. https://github.com/rstoyanchev/spring-mvc-31-demo – Alan Hay Apr 01 '15 at 18:39

1 Answers1

3

The easiest way is to do the logic inside updateComment function inside controller. Because, you can easily get the instance of SecurityContextHolderAwareRequestWrapper from the action param to find the role.

But the best practice is to put your logic inside service. This will make your life easier to reuse the logic in another place like RESTFul APIs.

So you may use the below code or something similar to check the role inside the Service.

Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
boolean authorized = authorities.contains(new SimpleGrantedAuthority("PERMISSION_UPDATE_OWN_COMMENT"));

(edited with further information)

Complete function which can be used to check the roles

protected boolean roleExist(String role) {
    SecurityContext context = SecurityContextHolder.getContext();
    Authentication authentication = context.getAuthentication();
    for (GrantedAuthority auth : authentication.getAuthorities()) {
        if (role.equals(auth.getAuthority()))
            return true;
    }
    return false;
}
Faraj Farook
  • 14,385
  • 16
  • 71
  • 97
  • Thanks, I think I'll follow this way ! One more question, how to get authentication inside of my service class.. or may be method ? – alexanoid Apr 01 '15 at 18:39
  • You can get it from SecurityContextHolder.getContext().getAuthentication(). Wait I will update the answer with the complete function which you can use. :) – Faraj Farook Apr 01 '15 at 18:43