javaspring-bootspring-securityuser-permissions

Control of user rights to change objects


Imagine that there is a user and he has a certain order that is issued for him. The user decides to "release" it and pulls the REST API handle:

@PreAuthorize("hasRole('USER') || hasRole('ADMIN')")
@PatchMapping(path = "/setFree", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<OrderDTO> setFree(@RequestParam(name = "id") int id) {
    final var order = this.orderService.findById(id).orElseThrow(() -> new OrderNotFoundException(id));
    if (order.getStatus() == OrderStatus.FREE.getId())
        return ResponseEntity.badRequest().build();

    final var free = this.orderService.setFree(order);
    return ResponseEntity.ok(this.modelMapper.map(free, OrderDTO.class));
}

An authorized user with the USER or ADMIN role has access to this handle. Question! What in this case prevents a user with the USER role from releasing an order for some other user. How can this be validated? So that the user can change the state of objects only those that are "allowed" to him or that are related to him? Take the current user in the security context and check that his "SpringSecurityHolder"#getId() == order#getUserId(); ? But this is too primitive. How can such validations be implemented correctly?


Solution

  • I believe when you say this is too primitive , you meant solution is not well abstracted and elegant in design.

    If that is the question, to make it more elegant you can follow this approach

    1. Define a AutoriationService within project.

    2. You can define method specific to validate authentication for this particular method ( getOrder). Method name could be - authenticationForToGetOrderAPI.

    3. You can define your custom implemenation of this method. Custom implemeantion could be "SpringSecurityHolder"#getId() == order#getUserId()".

    4. You can use Sprint Security annotation @PreAuthorize to attach this method on top of getOrder API call. The @PreAuthorize annotation checks the given expression before entering the method.

    More details for @PreAuthorize , please check it here - found this link helpful for Spring Security Features - https://www.baeldung.com/spring-security-method-security