Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Identity, add another user to role instantly (they don't have to log out and in again)

First of all, I'm aware of this question: MVC 5 AddToRole requires logout before it works?

and this one: What is ASP.NET Identity's IUserSecurityStampStore<TUser> interface?

so please don't mark this as a duplicate.

I'm trying to add another user to a role (i.e. the user we're adding to the role is not the current user. If they are, the answer to first question I linked to is sufficient.)

Like so:

IdentityResult result = await userManager.AddToRoleAsync(userID, roleName);

The two situations I'm doing this in are: from an admin page, where the current user is the administrator; and a webhook secured with basic authentication (where there is no current user at all).

THE PROBLEM: if the user that this change applies to is logged in and using the app, I need the "add to role" change to apply instantly. They shouldn't have to log out and in again for the change to happen, and it needs to happen straight away.

Thanks everyone.

EDIT: By the way, User.IsInRole(roleName) requires logout and login to reflect being added to the new role. UserManager.IsInRole(userID, roleName) does not, because (I assume) it goes straight to the database tables to check. But if the user hits an action method secured with the role they've just been added to, they still have to log in again, which is fair enough. Still curious if there's a way around this.

EDIT: Here is the source code for the Authorize attribute: https://github.com/ASP-NET-MVC/aspnetwebstack/blob/4e40cdef9c8a8226685f95ef03b746bc8322aa92/src/System.Web.Mvc/AuthorizeAttribute.cs

It uses User.IsInRole, which is essentially why we need to log in again. It seems the method to override is AuthorizeCore(HttpContextBase httpContext). I'm not brave or good enough to mess with this right now but if you want to have a go lots of people will find this helpful.

like image 858
nmit026 Avatar asked Apr 21 '16 10:04

nmit026


2 Answers

For ASP.NET Core Identity 2 the solution is to use:

services.Configure<SecurityStampValidatorOptions>(options =>
{
    options.ValidationInterval = TimeSpan.FromMinutes(1);
});

To force an update every minute or use TimeSpan.Zero to force an update everytime the user accesses the page (notice that everytime a database request is performed).

Also make sure that if you overwrite the cookie events do not use:

        services.ConfigureApplicationCookie(options =>
        {
            options.Events = new CookieAuthenticationEvents(){
            ...
            };
        }

But overwrite the Events you need directly as otherwise validation is not called:

        services.ConfigureApplicationCookie(options =>
        {
            options.Events.OnRedirectToLogin = ctx => {
            ...
            };
        }
like image 188
Wolfspirit Avatar answered Sep 22 '22 08:09

Wolfspirit


In ASP.NET Core, SignInManager.RefreshSignInAsync() solves this.

like image 38
chadwackerman Avatar answered Sep 23 '22 08:09

chadwackerman