I have implemented the basic Spring Boot Security stuff in order to secure my web services. I know that you can grant access to some services only to some user Roles, but is it also possible to grant access to a specified user (user can be dynamic)?
Let's say we have a social app, where every user has their own profile. With the following rest-service, they should be the only one able to edit the profile:
@RestController
public class UserController {
@RequestMapping(method = RequestMethod.PUT, path = "/user/{userId}", ...)
public UserDetails updateUserDetails(@PathVariable("userId") String userId) {
// code for updating the description for the specified user
}}
}
How can i ensure with spring security, that only the user itself can update his personal profile? Any other user should be rejected. Is there an elegant way, how you can configure this behaviour?
I have tried to find a method for that inside my WebSecurityConfig, but with no success.
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// configure authorization for urls
.authorizeRequests()
// grant access to all users for root path and /home
//.antMatchers("/", "/home").permitAll()
// here i would like to grant access in the way, that only the user is allowed to perform this request by calling url with his userId
.antMatchers(HttpMethod.PUT,"/user/<userId>").and().httpBasic();
}
What is a good approach to implement this behaviour?
I think that the best way to implement something like this would be to inject the Principal (Object containing the user that is logged in for this request) into the controller and then check if the user id or username is matching.
@RestController
public class UserController {
@RequestMapping(method = RequestMethod.PUT, path = "/user/{userId}", ...)
public UserDetails updateUserDetails(@PathVariable("userId") String userId, Principal principal) {
CustomUserDetails userDetails = (CustomUserDetails) principal;
if (userDetails.getUserId().equals(userId)) {
// Update the user
}
}}
}
Note that you will need a custom UserDetails
interface if you want to add the user id, because it only provided the username by default. Check this question if you want to know how.
Use @PreAuthorize
annotation:
@PreAuthorize("#userId == principal.userId")
@RequestMapping(method = RequestMethod.PUT, path = "/user/{userId}", ...)
public UserDetails updateUserDetails(@PathVariable("userId") String userId) {
// code for updating the description for the specified user
}
This assumes that the class that implements UserDetails interface has a userId property.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With