0

I am using JWT with spring security to handle the authorization for my REST API endpoints. In the following example the endpoint provides information about the user. Let's say I want only ADMIN users to be able to get the details of all the users, any other user should get only his/her account details. Can anyone think of a more declarative way to implement an equivalent to the following code using annotations or maybe AOP.

@RequestMapping(value = "user/{userId}", method = RequestMethod.GET)
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
public UserDetailsDto getUserDetails(
        @AuthenticationPrincipal JwtUser user, 
        @PathVariable String userId) {
    if (!user.getId().equals(userId) && user.getRole != Role.ADMIN)
        throw new BadCredentialsException("Jwt token id and requested ids do not match");
    //handle the request
}
samvel1024
  • 1,123
  • 4
  • 15
  • 39
  • I am not a Spring user, only found this question because of the `spring-aop` tag. So forgive me for the possibly stupid question, but if you know you only want to allow admins into this method, why don't you change the pre-authorize mapping to `@PreAuthorize("hasAnyRole('ADMIN')")`? If I understand correctly, currently you allow any user and then in the code exclude non-admins manually. If I misunderstood I can still suggest an AOP solution (my expertise), but first I want to clarify this. – kriegaex Apr 06 '17 at 07:57
  • I exclude users that are User but request an id not mapped to their user account, so that only admin users can get every others data, and ordinary users can get only their own data. I just want to reuse the same method, and configure it externally. – samvel1024 Apr 06 '17 at 19:06
  • Now I better understand your intent, thank you. One more thing before I can present an AOP answer: Would you please provide an [MCVE](http://stackoverflow.com/help/mcve) showing all the ways in which you provide the user id? In your snippet the current user method parameter #1, the id to get the details for is #2. You were also mentioning a `@RequestBody` annotation, but not showing how that is done. (I am not a Spring user, I need to see it in order to understand it.) In the meantime I can only present a solution for this concrete example. – kriegaex Apr 07 '17 at 09:03
  • Imagine just any @RequestBody annotated POJO in the argument which can have a field userId. – samvel1024 Apr 07 '17 at 14:09
  • I want to see, not to imagine. I cannot imagine anything I have no experience with. – kriegaex Apr 07 '17 at 14:45
  • http://ideone.com/W3tWsC – samvel1024 Apr 07 '17 at 15:23
  • Why do you link to external sources? Please edit your question instead, then notify me. Please learn [how to ask a question on SO](http://stackoverflow.com/help/how-to-ask) and provide a [minimal, complete, and verifiable example](http://stackoverflow.com/help/mcve) - or help yourself. I wasted too much time already, trying to get from you what I need in order to answer the question. Thank you. – kriegaex Apr 07 '17 at 15:39
  • I see, if you are able to give a solution to the current example maybe I will figure out the rest for myself, Thanks. – samvel1024 Apr 08 '17 at 19:34
  • You see, but you do not react. Just look how much unnecessary talk we already had because you hide information. I am out of here, bye. – kriegaex Apr 08 '17 at 20:06
  • Thanks a lot, bye. – samvel1024 Apr 08 '17 at 20:23

1 Answers1

0

You can define an Aspect Running on this method as pointcut reference.

  1. Include aop in your project. (Include apring-aop related jars, in spring-boot include spring-boot-starter-aop.)
  2. Enable AOP in your application configuration (Annotate Configuration class with @EnableAspectJAutoProxy annotation)
  3. Define your Aspect and configure Before advice to execute your Logic there. Eg:

    @Aspect
    @Component
    public class Test {
    
        @Before("execution(* com.package.name.*.getUser(..)) && args(user,dto)")
        public void getAllAdvice(JwtUser user, GetUserRequestDto dto){
            System.out.println("Service method getter called");
            if (!user.getId().equals(dto.getUserId()))
                throw new BadCredentialsException("Jwt token id and requested ids do not match");
            //handle the request
        }
    }
    

Now, your decision should be part of aspect and your business logic goes into your controller.

Hope this helps!!