koralium / OPADotNet

Apache License 2.0
10 stars 2 forks source link

Support to give out reasons why a user does not have access #64

Closed Ulimo closed 2 years ago

Ulimo commented 2 years ago

This improvement will help applications to notify the user why they do not have access to perform a specific API operation or why they cannot see a specific page.

Scenario and user experience

Reasons exist

Given the following policy:

# REASON: You must have access to ...
allow {

}

# REASON: You must have access to other ....
allow {

}

Application calls:

var result = await _authorizationService.AuthorizeAsync(...)
if (!result.Succeeded) {
  var failureReason = result.Failure.FailureReasons.FirstOrDefault()?.Message;
}

And there is no match on either allow, the user should get both reasons as failures in the result as a failure. With the default reason formatter it would give a message of:

- You must have access to ...
- You must have access to other ....

No reasons exist

When no reasons exist, a failure will be called but the message will contain a generic text such as "Authorization Failed".

Design

The policies in use will be parsed for where the text REASON: is as a comment and saved with their location. A full partial evaluation is done on the used policies with explain together with location information to gather where "enters" are being made.

This information is then combined with the block name and its reason text.

When policy checks are being made in AspNetCore explain info will be taken if reason text output is enabled (will be enabled by default).

Either an "index" failure or a fail during an "enter" of a block that has a reason will be outputted as a reason.

Since the blocks can be seen as a tree, the reason text will also follow this structure.

Example:

# REASON: You are not allowed to see this page
allow {
  is_admin
  is_owner
}

# REASON: You must be an admin
is_admin {
  ...
}

# REASON: You must ben an owner
is_owner {
  ...
}

Would create the following reason:

- You are not allowed to see this page
  * You must be an admin
  * You must be an owner

Reason formatting will have a default implementation and also an interface that can be overridden to implement custom reason formatting.