0

Just like in this question, I want to sign out another user via updating the Security Stamp. However it doesn't work when testing on my local machine. I suspect the problem might be with the order of commands I'm using to reset a user and persisting the different properties to the db.

That's my Startup.Auth

public partial class Startup
{
    public static TimeSpan expireTimeSpan = TimeSpan.FromHours(24);
    public static IDataProtectionProvider DataProtectionProvider { get; private set; }

    public void ConfigureAuth(IAppBuilder app)
    {
        app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>());

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            ExpireTimeSpan = expireTimeSpan,
            Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            }
        });

        DataProtectionProvider = app.GetDataProtectionProvider();
    }
}

And this is a controller method that allows changing another users email == username. On changing the email, the user is supposed to be logged out and not have a valid password anymore.

public async Task<IHttpActionResult> UpdateUser(string id, ApplicationUser newUser)
{
    var user = await _userManager.FindByIdAsync(id);
    if (user == null) ...

    IdentityResult result;

    user.name = newUser.name;
    user.roles = newUser.roles;

    // sign out user and invalidate password
    if (user.email != newUser.email)
    {
        user.email = newUser.email;
        user.PasswordHash = null;

        result = await _userManager.UpdateSecurityStampAsync(user.Id);
        if (!result.Succeeded) throw new Exception("Security Stamp not updated.");

        await _account.SendPasswordEmail(user);
    }

    result = await _userManager.UpdateAsync(user);
    if (!result.Succeeded)
        return GetErrorResult(result);

    return Ok();
}

I have tried persisting the user first, then generating a new SecurityStamp, but that didn't work either.

Any ideas what could be wrong?

Thanks!

Community
  • 1
  • 1
Benjamin E.
  • 5,042
  • 5
  • 38
  • 65

1 Answers1

1

Apparently you didn't read the answer in the question you linked to clearly.

// important to register UserManager creation delegate. Won't work without it
app.CreatePerOwinContext(UserManager.Create);

This is further explained here:

https://aspnetidentity.codeplex.com/workitem/2209

However, you should be aware of this bug:

ExpireTimeSpan ignored after regenerateIdentity / validateInterval duration in MVC Identity (2.0.1)

This will be fixed in the forthcoming Identity 2.2/Owin 3.0 release, but is not yet final.

https://aspnetidentity.codeplex.com/workitem/2347

Also see this blog article:

http://tech.trailmax.info/2014/08/cookieauthenticationprovider-and-user-session-invalidation-on-change-of-securitystamp/

Community
  • 1
  • 1
Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • Updated `ConfigureAuth` to pass an instance of `UserManager` from my DI container to the OWIN context, but still not working. I don't think I'm affected by any of the other bugs described. – Benjamin E. Dec 08 '14 at 04:05
  • However I noticed that this callback `regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))` does not get called when updating the SecurityStamp – Benjamin E. Dec 08 '14 at 04:12
  • @BenjaminE. - are you sure that your DI is wired up at the point that this is called? Generally speaking, you need to call CreatePerOwinContext for several possible dependencies, such as ApplicationDbContext... If I were you, I would make sure calling GetService actually returns the instance. – Erik Funkenbusch Dec 08 '14 at 07:13
  • @BenjaminE. - try using it without the DI, using the UserManager.Create function, just to see if it works, then you have narrowed down the problem to your DI. – Erik Funkenbusch Dec 08 '14 at 08:07
  • You are right, `UserManager` is not resolved when `app.CreatePerOwinContext` requests it. – Benjamin E. Dec 08 '14 at 10:27