Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure Spring Boot Security so that a user is only allowed to update their own profile

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?

like image 208
Andy Avatar asked Dec 19 '22 05:12

Andy


2 Answers

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.

like image 178
Jean-Philippe Bond Avatar answered May 09 '23 07:05

Jean-Philippe Bond


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.

like image 33
holmis83 Avatar answered May 09 '23 08:05

holmis83