2

I have a Spring web service where users only have access to specific resources. Any user can make a request to get the resource info, but I need to throw an Authorization exception if they don't have access to that resource. The API is as follows:

GET /resources/{resourceId}

The above API provides the user all info about a given resource.

Currently I do authentication using WebSecurityConfigurerAdapter. To add authorization, I have observed that I can set the granted authorities as part of the Authentication object. On doing so, I can use something like @PreAuthorize("hasRole('ROLE_USER')") to do the authorization.

However, for the mentioned API I am not sure if the mentioned authorization approach is suitable for the following reasons.

  1. I am authorizing based on the whether the user has privileges to access the specific resourceId. This is not exactly a Role. More like a Privilege. Is it still acceptable to use hasRole() for this use case?
  2. If I did use the hasRole() annotation I would need to do something like @PreAuthorize("hasRole('ACCESS_RESOURCEID12346')") where RESOURCEID12346 is the resourceId. But, we only have access to resourceId once we are in the API controller. So, how do I use that value for the authorization annotation?

If the specified approach is not the best way of solving the problem, I would appreciate any input/feedback on what would be the best approach. I'd like to avoid doing this check in the controller. I am trying to do it through Spring Security similar to how @PreAuthorize works. I think access to the resourceId is an authorization requirement and we should not even get into the API controller if the user doesn't have access to that resource.

RagHaven
  • 4,156
  • 21
  • 72
  • 113
  • You have the user info so I would provide a UserResouce table in the db and check for the relationship on get. – ChiefTwoPencils Dec 25 '16 at 18:46
  • 1. Wouldn't this be combining authentication and authorization? From my understanding by design it's better to separate authentication and authorization. 2. How do I get access to the resourceId I need to check against? It's only apart of the API path. – RagHaven Dec 25 '16 at 18:49
  • I don't see how it would be combining it. You have auth through preauth on ROLE_USER right? So, you're already auth-ed and you have the path and id. So, making assumptions, you could do `getResourceByUserAndResourceId(...)` where the query uses the table mentioned above. – ChiefTwoPencils Dec 25 '16 at 18:53
  • Are you suggesting something like this: @PreAuthorize("hasRole('ACCESS_" + @PathVariable("resourceId") + "')")? That doesn't compile. – RagHaven Dec 25 '16 at 19:02
  • I'd like to avoid doing this check in the controller. I am trying to do it through Spring Security similar to how @PreAuthorize works. – RagHaven Dec 25 '16 at 19:03
  • @ChiefTwoPencils I'm trying to make my implementation such that it doesn't go into the API controller if the user doesn't have access to that resource. I am assuming the approach you are suggesting requires doing that check within the controller? – RagHaven Dec 25 '16 at 19:06
  • 1
    @AndroidDev93 `RESOURCEID12346 ` pretty much looks like ACLs which should be dynamic and not in Java code directly. – Michael-O Dec 25 '16 at 19:10

1 Answers1

3

Distributing permissions through roles bound to a resource id seems like a potential maintenance nightmare. If you don't want to allow access to the controller then maybe access is the best thing to use.

The above link has examples for both Java and xml based configuration and shows how you can gain access to the path before entering the controller.

You would provide a method that you reference like:

boolean checkResourceAccess(Principal principal, int resourceId)

In your config you refer to the url argument like #resourceId mapping it to {resourceId}.

Java config example:

http.authorizeRequests()
    .antMatchers("/resources/{resourceId}")
    .access("@yourBean.checkResourceAccess(principal,#resourceId)")...

In that method you supply whatever logic needed to determine the user's access.

ChiefTwoPencils
  • 13,548
  • 8
  • 49
  • 75
  • Is this approach better than having a GrantedAuthority for that resourceId during authentication and then using @PreAuthorize("hasAuthority('ACCESS_#resourceId')") – RagHaven Dec 25 '16 at 19:44
  • 1
    I think "better" is subjective but I would think so. Have you read the accepted answer [here](http://stackoverflow.com/questions/19525380/difference-between-role-and-grantedauthority-in-spring-security)? – ChiefTwoPencils Dec 25 '16 at 19:53