Repository navigation
Replies: 1 comment
|
Disclosure up front: I work at Instruxi on Enforcer, which is an authorization service that returns a reason alongside allow/deny. Not pitching a switch, just offering what bit us building the same feature, because two of these were not obvious until we shipped them. The reason the PEP sees and the reason the log keeps are different objects. A detailed deny sent back to the caller is an oracle. "Denied: not in Finance approvers" tells whoever asked that the group exists, that it gates this action, and that membership is the lever. Enough denials with enough detail maps out your policy. That is fine for an internal PEP you own and a real problem for anything an untrusted client can hammer. What worked for us: a coarse, stable, machine-readable slug goes back to the PEP, the full reason goes to the audit record regardless, and the deployment decides whether an optional detail field travels with the slug. Concretely we return If The second one, which surprised us: when you have several possible deny reasons, the order you evaluate them in is part of the feature. We had a deny that correctly reported a tenancy mismatch. It was true and it was useless, because the real cause was that the request had not said which tenant or owner the resource belonged to, so nothing could match and the tenancy comparison was the first condition that happened to be literally true. People went hunting a tenancy bug that did not exist. We reordered so the more specific "you under-described the request" reason is checked before the generic one, and only ever renames a denial that was already going to happen. So a reason is not just a string attached to a |
- 7EB0
Uh oh!
There was an error while loading. Please reload this page.
Summary
When implementing custom
PolicyProviderfor Keycloak's Authorization Services, there is currently no way to communicate why a permission was denied back to the Policy Enforcement Point (PEP). The error response is always hardcoded to "not_authorized", which makes it impossible for clients to distinguish between different denial reasons.Use case
I'm developing authorization policy that fails on different case, and depending upon the case, I need to take action in the policy enforcement point. Currently when any of the conditions fail, the PEP receives the same generic response:
{ "error": "access_denied", "error_description": "not_authorized" }This forces the client application to make additional API calls to determine the actual reason.
Current Behavior
The Evaluation interface provides binary outcomes
And in AuthorizationTokenService, The error description is hardcoded:
Proposed solution
Add optional
deny(String reason)method to theEvaluationInterface with backward compatibility:Propagate this reason to the error response in the
AuthorizationTokenServiceExpected outcome
With this feature custom policy providers could do:
And PEP would receive:
{ "error": "access_denied", "error_description": "case_1_failed" }Backward Compatibility
PolicyProviderimplementations continue to work unchangeddeny()without arguments still works, defaulting to"not_authorized"Considered alternatives
addClaim()on permission - This only works for granted permissions, not denials.I'm happy to contribute the implementation if this proposal is accepted.
All reactions