Hi I have a custom authentication in my asp.net core mvc project and now I have a problem. First I explain my authentication: this is startup config :
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(options =>
{
options.LoginPath = "/Login";
options.LogoutPath = "/Logout";
options.AccessDeniedPath = "/AccessDenied";
options.ExpireTimeSpan = TimeSpan.FromDays(60);
});
and this is my permission checker class :
public class PermissionCheckerAttribute : AuthorizeAttribute, IAuthorizationFilter
{
private readonly string _permissionName;
public PermissionCheckerAttribute(string permissionName)
{
_permissionName = permissionName;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
var permissionList = context.HttpContext.User.Claims
.Where(claim => claim.Type == "permission").ToList();
var hasPermission = permissionList.Any(claim => claim.Value == _permissionName);
if (!hasPermission)
{
context.Result = new RedirectResult("/AccessDenied");
}
}
}
and this is a sample of my permissions :
[PermissionChecker(TestControllerPermissions.Create)]
public async Task<IActionResult> Privacy()
{
return View();
}
and when user login I get user permissions from database and store it on claims. all is working fine but the problem is how can i update this ? I mean for instance i am admin and i will change some users permissions to affect that user must logout and login again but this is not what i want. how can i update my user claims base on my database every time? should i check that in my permission checkerClass ? that means i should conncet to database for every permision request? please give me some idias.
CodePudding user response:
That's how it works. Either work with the cached information in the user claims, which could lead to use outdated information or make a lookup every time a user comes in. The first you are currently doing. The latter is making a request against your DB within OnAuthorization()
.
Another possibility depends if changing the permissions can only be done through your project. If that's true, all your methods changing the permissions would write some timestamp into some cache (e.g. memory or distributed). When the user comes in, you compare the lifetime of the claim (in case of Bearer token, there is a nbf field saying (mostly), when the token was created) with the last update of the database. If the database update is older, take the value from the claim, if the database update is younger, make a request against the database. After some time the old tokens are aged out, the users get new tokens and you can work with the info in the token again.
So, if this approach works, heavily depends if you know (without an explicit query) when the database was updated last time. Also be aware that this can lead to spikes in your database usage, cause after a permission change, each request will lead to a database query till all tokens are outdated, but if really needed these results could also be cached in a similar way, but could lead to a high memory load, depending on your number of users.