I have a Blazor app with custom AuthorizationHandler
and IAuthorizationRequirement
. Snippet from the AuthorizationHandler
:
internal class PermissionLevelAuthorizationHandler : AuthorizationHandler<PermissionLevelRequirement>
{
private readonly AuthService _authService;
public PermissionLevelAuthorizationHandler(AuthService authService)
{
_authService= authService;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionLevelRequirement requirement)
{
string? requiredResource = ((DefaultHttpContext?)context.Resource)?.Request.Path;
int requiredLevel = requirement.Level;
var canAccess = _authService.GetPermission(requiredResource, context.User, requiredLevel);
if (canAccess) {
context.Succeed(requirement);
}
}
}
AuthorizationHandler
has injected AuthService
, which does two things:
-
Fetches from database all the groups that current user belongs to
-
Checks (again in database) if any of the user’s groups can access the required page with required permission level.
Both AuthService
and AuthorizationHandler
are scoped services.
Since the AuthService
has to do two queries for each authorization check, I wanted to store the current user permissions in the AuthService
and only contact the database if I don’t have the permissions loaded yet.
Problem: The problem is that it seems that AuthorizationHandler
gets new instance of AuthService
every time even though they are both scoped. Therefore I can’t store any data in the service. Why is that and is there any way to fix that? Are there any better ways of doing that?
As far as I know the alternatives are:
- store claims in the authentication cookie. That would reduce my service from doing 2 queries to doing only the second one. But the problem is, user can have many groups so the cookie can become too big.
- store in browser’s local storage or session storage. I would prefer not to store permissions there.
- store permissions for all users in a singleton service and refresh them all periodically. That would work but I don’t like the fact that the user would have to wait for the refresh after we change permissions.
Also, the authentication is done by a central app. So the authentication cookie is shared amongst multiple apps. Which makes storage a bit more complicated because I would have to handle deletion of data correctly on all apps. That’s why it seems the best solution is to store data in DI service instance.