Java how to specify scopes in calls (without rely on client)

I defined 5 scopes : create,read,update,delete,print.

I have a lot of Java classes exposed as web services that implements the same abstract class.

Suppose I have

@Path("orders")
public class OrderController implement AbstractController<Order>{
}

and the abstract class has the common methods

public abstract AbstractController<T>{

     @Path("read/{id}")
     public T getRecord(@PathParam(value="id") Long id ){
          ....
     }

     @Path("delete/{id}")
     public void deleteRecord(@PathParam(value="id") Long id ){
          ....
     }
}

I have created a resource for urls “orders/*”, let’s call OrderResource.
I have created 2 policies for 2 roles : role_manager, role_user

Now I want to create 2 scope permissions:

  1. resource = OrderResource, scope=read, policy=role_user

  2. resource = OrderResource, scope=read,delete, policy=role_manager

How can i specify that order/read requires the scope “read” and order/delete requires scope “delete” ?

If you are using Spring Security then you can use the @PreAuthorize annotation, for example:

  @GetMapping("/individuals/{id}")
  @PreAuthorize("hasAuthority('SCOPE_individual:read')")
  public ResponseEntity<EntityModel<Individual>> findById(
      @PathVariable("id") final Long id) throws ResponseStatusException {
    
    Individual entity = entityService.findById(id).orElseThrow(() -> 
        new ResponseStatusException(HttpStatus.NOT_FOUND));
    
    return ResponseEntity.ok(assembler.toModel(entity));
  }

Ref: Flowable OAuth2 Resource Server

I’am sorry but I’am not using Spring.

I’am trying with javax.ws.rs.container.ContainerRequestFilter. If it works, i’ll post my solution. I’am using the “picketlink way”, something like the old org.picketlink.http.authorization.PathAuthorizer

Anyway if a stardard way exists, I would use it.

I don’t know if I doing it in the right way…

In my methods I have added an annotation (i did it for picketlink)

 @RequiredPermission(scope="read")

So, i get an url = /webservice/order/get

I search what class match to the url ( @Path(“order”) -> OrderController.java ), then I get the method (@Path(“get”)-> getById(Long id) ) and I read the annotation.

So I know that the method require a read-permission.

@Provider
@Priority(value = Priorities.AUTHORIZATION)
public class SecurityFilter implements ContainerRequestFilter {

     @Override
     public void filter(ContainerRequestContext requestContext) throws IOException {
             ... // getting scopes by java reflection
            RefreshableKeycloakSecurityContext keycloakSecurityContext = (RefreshableKeycloakSecurityContext) servletRequest.getAttribute(KeycloakSecurityContext.class.getName());
            if(keycloakSecurityContext != null){
                AuthorizationContext authzContext = keycloakSecurityContext.getAuthorizationContext();
                Boolean result = true;
                if(scopes != null){
                    for(String scope : scopes){
                        result = result && authzContext.hasScopePermission(scope);
                    }
                }
                if(!result)
                    throw new NotAllowedException("Non hai i permessi");
            }

     }
}

Problem : supposing I resolve a class cast exception (:stuck_out_tongue: ), i have refused not allowed request, but how i can allow the other calls?

If it’s the wrong way, are there some headers to add saying “this method is requesting a read scope” ?

I have the url/request/java method, i have the scopes, now I need to match them together