5

The problem can be defined by the following example:

I have a class MainClass which is related with another class called AssociatedClass by a @OneToOne relation. Both have an exposed Repository so I can do a GET on the URL /mainClasses/{some_id} and on the URL /associatedClasses/{some_id}. However, the AssociatedClassRepository has the following code:

@RepositoryRestResource
public interface AssociatedClassRepository extends PagingAndSortingRepository<AssociatedClass, String> {
    @Override
    @PreAuthorize("1 == 2")
    AssociatedClass findOne(String s);
}

So it will never authorize the GET method to an object of type AssociatedClass. However, as the object of type MainClass has an AssociatedClass object associated, I can obtain this object by doing a GET at /mainClasses/{some_id}/associatedClass.

I would like to block the access to /mainClasses/{some_id}/associatedClass but not for all the users. I'd like to define some condition in the same way I can do it through @PreCondition. So that I can allow the access only if the authenticated user is the owner of the resource, which is my real goal.

Any ideas?

bergacat1
  • 133
  • 9
  • Can you post your controller code? and repository code? – Moshe Arad Oct 11 '16 at 11:45
  • I don't have any controller because I'm using Spring Data Rest. I have edited the post so that you can see the full code of the AssociatedClassRepository. – bergacat1 Oct 13 '16 at 09:06
  • This rather looks to me like security is not activated at all. Spring Data REST is basically just invoking the method. If that doesn't trigger a security exception, your Spring Security setup seems to be incorrect. Are you sure you have method security activated? – Oliver Drotbohm Oct 18 '16 at 20:27
  • If I perform a GET on the URL `/associatedClasses/{some_id}` the response will always be a `403 Forbidden`. So the `@PreAuthorize` is working correctly. – bergacat1 Oct 20 '16 at 09:04

2 Answers2

1

One option is to secure Spring Data REST endpoints at the URL level. For example:

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
           .antMatchers("/entity/{[0-9]+}/{[A-Za-z][A-Za-z0-9]+}").hasRole("ADMIN").
           and().csrf().disable();
            }
        }

Public access:

  • /entities
  • /entities/entityId

Admin access:

  • /entities/entityId/associated entity
George
  • 66
  • 1
  • 4
  • This will work for most of the cases. Unfortunately, in my case I need to secure the resources based on whether the logged user is the owner of it or not. – bergacat1 Dec 05 '16 at 12:31
  • For example, in my user class I have annotated with `@PreAuthorize("principal.id == #id")` the `findOne` method. And I have another class ("CreatedEntity") which is related with the user who is the owner/creator of each object. So the problem will be on the URL `/createdEntities/id/createdBy`. – bergacat1 Dec 05 '16 at 12:44
0

Apply an excerpt projection to the associated entity's repository and add there security checks as described in

Spring Data Rest: Security based projection

The associated resource will be returned but you can hide certain fields or all of them.

Community
  • 1
  • 1
George
  • 66
  • 1
  • 4