Search code examples
javaspringspring-bootspring-securitypagination

How to allow some User only access his own data in endpoint in Spring Boot / Spring Security with pagination?


I have a question related to the limiting of the products list to specific User in my application. Ive got an API: "/api/v1/{userId}/products" and I want to use pagination in my UserRestController which I have already used in AdminRestController:

@GetMapping
    public Response<Page<Product>> getProductPage(@PageableDefault(sort = "id") Pageable pageable) {
        return Response.ok(productService.findAll(pageable));
    }

I have read some threads and find some solutions with "@PreAuthorize("#userId == authentication.principal.id")". Now, I want to implement pagination in my endpoint in UserRestController which should return only the products list related to the specific User (not the list of all products). I have tried to use the following:

@GetMapping("/api/v1/{userId}/products")
@PreAuthorize("#userId == authentication.principal.id")
public Response<Page<Product>> getProductPage(@PageableDefault(sort = "id") Pageable pageable) {
    SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    return Response.ok(productService.findAll(pageable));
}

But I have got the access problem, could you help me to figure out?

Thanks in advance!


Solution

  • It is already implemented into Spring-Secutiry and Spring-Data.

    In config, you need to add a @Bean to provide your principal into the queriing :

    @Configuration
    public class Conf{
        // `principal` provider for the Spring-Data JPQL requests
        @Bean
        public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
          return new SecurityEvaluationContextExtension();
        }
    }
    

    After that you'll be abble to write things like that :

    @RepositoryRestResource(path = "datas", exported = true)
    public interface DataRepository extends PagingAndSortingRepository<Data, Long> {
    
      @Override
      @Query(value = "Select d From Data d Where d.ownerId = ?#{principal?.username}")
      Page<Data> findAll(Pageable pageable);
    
    }
    

    Also, read the official doc : https://docs.spring.io/spring-security/reference/features/integrations/data.html