Home > other >  How to make resource available to users with the corresponding userid
How to make resource available to users with the corresponding userid

Time:12-14

i secured my backend (spring boot) as a resource server with keycloak and my frontend calls the resources on the backend with a jwt token in the header, meaning that when User1 makes a GET /products call a json structure like this is returned:

{
    "id": "639242400f6cc412b5b29f26",
    "userid": "f114298c-8b38-47e7-b413-bd8f12exyz",
    "productname": "productOne"
},
{
    "id": "63924a050f6cc412b5b29f27",
    "userid": "f114298c-8b38-47e7-b413-bd8f12exyz",
    "productname": "productTwo"

}, ....

When a logged in User creates a product, the userid that the currently logged in user has is assigned to the product. For example, User1 with the userid (f114298c-8b38-47e7-b413-bd8f12exyz) created productOne and productTwo.

My question is: How do i make the products with the userid (f114298c-8b38-47e7-b413-bd8f12exyz) only available to the currently logged in User1 with the corresponding userid? So when User2 is logged in, he does not see the products assigned to User1. User2 only sees his own created products with the corresponding userid.

I hope I did not overcomplicate the question, thanks in advance!!

CodePudding user response:

Configure your spring REST API as resource-server. If you don't know how, refer to this tutorials I wrote (it could also show you how to simplify your security conf if you already have a resource-server configured).

Then, when request is authorized, you should have a sub-class of AbstractOAuth2TokenAuthenticationToken<?> in security context (unless you explicitly changed it like I do in 2nd and 3rd tutorials)

  • @EnableMethodSecurity in your security-conf
  • inject AbstractOAuth2TokenAuthenticationToken<?> as controller method parameter

From that point, two options depending on your needs & preference (samples below are designed for a @Controller already decorated with @PreAuthorize("isAuthenticated()")):

@GetMapping("/products")
@PreAuthorize("hasAuthority('READ_ANY_PRODUCT') || #auth.tokenAttributes['sub'] == #userid")
public List<ProductDto> listProducts(@RequestParam(required = true, name = "userid") @NotEmpty String userid, AbstractOAuth2TokenAuthenticationToken<?> auth) {
    final var products = productRepo.findByUserid(userid);
    ....
}

or

@GetMapping("/products")
public List<ProductDto> listProducts(AbstractOAuth2TokenAuthenticationToken<?> auth) {
    final var products = productRepo.findByUserid(auth.getTokenAttributes().get(StandardClaimNames.SUB).toString());
    ...
}

If you follow the tutorials linked above until the 3rd, you'll learn how to build a custom DSL for Spring security expressions to build something like:

@PreAuthorize("is(#userid) or isProductManager() or onBehalfOf(#userid).can('read_product')")
  • Related