Closed KyleChau-GamaTech closed 3 days ago
I'm not quite sure I understand the scenario here, but it sounds like you might be able to use Cedar annotations to accomplish this. First I'd split what you have into a single permit
policy plus multiple forbid
policies:
// this is the same permit as previously
permit(
principal,
action in [MyApplication::Action::"POST", MyApplication::Action::"CheckOut"],
resource
)
when {
context.token.client_id == "52n97d5afhfiu1c4di1k5m8f60" &&
context.token.scope.contains("MyAPI/purchaseOrder.write") &&
context.request.amount <= 1000 &&
context.request.item not in ["knife", "rocket_ship", "pistol"]
};
// then you put the other parts in separate forbid policies
forbid(
principal,
action in [MyApplication::Action::"POST", MyApplication::Action::"CheckOut"],
resource
)
when {
context.request.item in ["knife", "rocket_ship", "pistol"]
};
forbid(
principal,
action in [MyApplication::Action::"POST", MyApplication::Action::"CheckOut"],
resource
)
when {
context.request.amount > 1000
};
And then you can add annotations to the forbid
policies, so that when they fire, your application can respond appropriately. Specifically your application can look in the reason
field of the DENY response to see the forbid
policies which were responsible, and then use the annotations on those policies to decide what further actions to take, for instance, prompting the user to reauthenticate.
@max_age("1")
@acr_value("law_enforcement_fido")
forbid(
principal,
action in [MyApplication::Action::"POST", MyApplication::Action::"CheckOut"],
resource
)
when {
context.request.item in ["knife", "rocket_ship", "pistol"]
};
@acr_value("biometric")
forbid(
principal,
action in [MyApplication::Action::"POST", MyApplication::Action::"CheckOut"],
resource
)
when {
context.request.amount > 1000
};
I might be misunderstanding your intended logic; perhaps you want the expressions in your return
clauses to actually be unless
clauses attached to these forbid
policies, or something.
Closing this due to no activity. Please reopen if needed.
@adpaco-aws @cdisselkoen Thanks a lot for the suggestion. I think annotation would be sufficient for us to return the deny reason we need.
Category
Cedar language or syntax features/changes
Describe the feature you'd like to request
As described in rfc9470, in simple API authorization scenarios, an authorization server will determine what authentication technique to use to handle a given request on the basis of aspects such as the scopes requested, the resource, the identity of the client, and other characteristics known at provisioning time. Although that approach is viable in many situations, it falls short in several important circumstances. Consider, for instance, an eCommerce API requiring different authentication strengths depending on whether the item being purchased exceeds a certain threshold, dynamically estimated by the API itself using an opaque logic to the authorization server. An API might also determine that a more recent user authentication is required based on its risk evaluation of the API request.
Policy definition sounds to be a good place to include such a logic. To achieve this purpose, extra syntax is needed to support a comprehensive conditional definition of the return challenge. For instance:
Describe alternatives you've considered
I considered creating a wrapper to customize the request and response of the policy query interface, such as
if {authorizer.query(xxx) == deny} return "biometric"
. However, this approach would only work if the challenge condition is not complex. Otherwise, we would need to create a mapping in the wrapper to determine which acr_value to return based on the input when the Cedar authorizer returns a deny verdict. This doesn't seem to be an elegant approach, as it requires the wrapper to handle part of the policy decision.Additional context
No response
Is this something that you'd be interested in working on?