-
Notifications
You must be signed in to change notification settings - Fork 0
how it works authorization
Now that authentication is out the way, it's time to explain the different types of authorization used in this solution
There's two:
- Role-Based Access Control [RBAC]
- The role comes from the user's claims in the
id_token
and then configured to include in theaccess_token
in order to pass it downstream
- The role comes from the user's claims in the
- Policy-Based Access Control [PBAC]
- These are custom, and can include roles, assertions or your own custom requirements
Controllers and/or actions decorated with the [Authorize]
attribute require authentication
Authorize attributes can also optionally specify roles [Authorize(Roles = "Administrator")]
or policies [Authorize(Policy = "PolicyName")]
This uses Role-Based Access Control
[Authorize(Roles = "Administrator")]
public class AdminController : Controller
{
// ...
}
This uses Policy-Based Access Control
[Route("api/customers/{customerId}/[controller]")]
[ApiController]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme, Policy = "MustBeARegularCustomer")]
public class AddressesController : ControllerBase
{
// ...
}
Since the MustBeARegularCustomer
policy is used as an example, we'll have a look at how it's built
Here's the code in Program.cs that adds authorization and adds the policy
builder.Services.AddTransient<IAuthorizationHandler, CustomerIdFromClaimsMustMatchCustomerIdFromRouteHandler>();
builder.Services.AddAuthorizationBuilder()
.AddPolicy("MustBeARegularCustomer", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireAssertion(context => context.User.IsInRole("Administrator") is false);
policy.AddRequirements(
new CustomerIdFromClaimsMustMatchCustomerIdFromRouteRequirement());
});
It's built with one custom requirement CustomerIdFromClaimsMustMatchCustomerIdFromRouteRequirement
This means that custom logic is needed in order to be authorized to access resources provided by the AddressesController
Before this was in place, that custom logic was within the methods after the user was authorized, and isn't the best behavior
Users should be evaluated before even reaching the code within a method
A requirement implements the IAuthorizationRequirement
interface and may contain parameters for the requirement, however, the logic isn't implemented here
A dedicated handler is created - CustomerIdFromClaimsMustMatchCustomerIdFromRouteHandler
- that implements the AuthorizationHandler<T>
, T
in this case is CustomerIdFromClaimsMustMatchCustomerIdFromRouteRequirement
This is where the custom evaluation occurs and determines if a user is authorized or not
View the full implementation here
Custom authorization handlers have to be added to the services collection using any service lifetime [according to the docs]
builder.Services.AddTransient<IAuthorizationHandler, CustomerIdFromClaimsMustMatchCustomerIdFromRouteHandler>();
- Health Checks UI
- Mvc Frontend
- Web Backend-For-Frontend
- Address Service
- Address Worker
- Identity Service
- Order Service
- Order Worker
- Tyres Service