jenskeiner opened a new issue #3274:
URL: https://github.com/apache/apisix/issues/3274


   I'm opening this issue to get some feedback on some proposed changes to the 
`auth-keycloak` plugin before I shoot off and start working on them.
   
   The current incarnation of the plugin has some limitations that limit its 
usefulness. The most visible limitation, to me at least, is that you can only 
configure a static set of resource/scope pairs.
   
   Without delving into too many details of the Keycloak Authorization Services 
API (described here in all its glory: 
https://www.keycloak.org/docs/latest/authorization_services/index.html), it's 
worth mentioning that permissions are defined in terms of resource/scope pairs. 
If you think of some REST service that you want to protect, then a resource 
would typically be a subset of the available endpoints, defined by some URI 
pattern, e.g. `/foo/bar/*`. A scope typically describes the type of action to 
perform on the resource, e.g. read, write, delete, but can also really be 
something completely different and abstract, depending on the use case.
   
   To check if an incoming request should be allowed to proceed to the 
upstream, or if it should be rejected, the plugin currently uses the token 
endpoint (which is also used for OIDC authentication) with a special grant 
type. The requested permissions, specified by resource/scope pairs are sent as 
a parameter to that endpoint together with the bearer token from the request. 
Keycloak evaluates the permissions and answers with the decision, i.e. whether 
the permissions are granted or not. If yes, then the request can proceed, 
otherwise, it is rejected.
   
   As I said above, the set of resource/scope pairs is currently fixed in the 
plugin configuration. But often, what you want to do is to determine the 
resource and scope from features of the incoming request like HTTP method and 
URI. Actually, the documentation mentions this as future work, but that has so 
far not materialized.
   
   Just upfront: The changes I want to propose would need to be split into 
smaller PRs that build onto each other.
   
   Basically, I want to propose to implement (optional) dynamic resource and 
scope resolution as follows:
   - The scope is determined by the HTTP method of the request (i.e. a GET 
request maps to scope GET).
   - The resource is determined by using Keycloak's resource registration 
endpoint which can return the resources that match a given URI.
   
   I have a working example of this in a branch. There are some points to 
observe though:
   - Using the resource registration endpoint requires another request to 
Keycloak on top of the one to the token endpoint that returns the decision. 
Longer term, but maybe not in the first iteration, caching can be implemented 
to reduce the number of necessary requests.
   - To be able to invoke the resource registration endpoint, the plugin first 
needs to obtain a separate access token for itself from the token endpoint via 
client ID and secret. This is a special token that has the `uma_protection` 
scope which allows access to the Protection API and hence the resource 
registration endpoint. It's relative easy to obtain the token, but some 
management needs to be implemented because the token needs to be refreshed 
regularly as it will typically be short-lived. This will make the code base a 
bit more complex, but cannot be avoided.
   - Longer term, it may be better to load all resources from Keycloak once 
(maybe with periodic updates), and match the request URI to the resources in 
the plugin, e.g. with the help of the radix tree library already used for 
routes. This would avoid the requests that are needed just to determine the 
resource.
   
   To sum up, I would propose above changes, but with the focus on first 
getting the scope and resource discovery working properly, before focusing on 
further optimizations like caching.
   
   Would love to hear anyone's thoughts. Maybe @sshniro can chime in because 
you've worked a lot with the plugin already.
   


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to