I\'m, using RC1 bits and external (Google) authentication, no Identity.EntityFramework.
During login, I set \'Remember me\' flag.
Logged-in user survives browser
Wow, I solved it!
TL;DR
I need to implement IUserSecurityStampStore<User>
on my custom UserManager
(aka SportCmsDb
).
Details
During AddIdentity
call (in Startup.cs
ConfigureServices
method) IdentityOptions are configured with default instance of IdentityCookieOptions. In constructor of IdentityCookieOptions
instance of ApplicationCookie
(of type CookieAuthenticationOptions
) is created with handler CookieAuthenticationEvents.OnValidatePrincipal
set to SecurityStampValidator.ValidatePrincipalAsync static method.
During UseIdentity
call (in Startup.cs
Configure
method) CookieAuthenticationMiddleware
is configured with IdentityOptions.Cookies.ApplicationCookie options.
CookieAuthenticationHandler
(created by CookieAuthenticationMiddleware
) in it's HandleAuthenticateAsync
method reads ticket from cookie and call Options.Events.ValidatePrincipal handler for validation.
Effectively, SecurityStampValidator.ValidatePrincipalAsync
is called. This method checks that enough time has elapsed since cookie was issued (30 min by default) and calls ISecurityStampValidator.validateAsync
(lines 81-82).
Default implementation of ISecurityStampValidator
is SecurityStampValidator<TUser>
. It calls SignInManager<TUser>.ValidateSecurityStampAsync and when null is returned - rejects principal and forces user to sign out (lines 30-40).
SignInManager<TUser>
in its ValidateSecurityStampAsync method tries to read security stamp from User
and returns null if it can't (if UserManager<User>
does not supports this interface) or stamp does not match saved one (in cookie).
My custom UserManager
does not implement IUserSecurityStampStore<User>
. Bingo.
Thank you very much for the previous answers, I worked with this problem today and I resolve with this:
1.- Custom UserStore.cs:
public class UserStore : IUserStore<User>,
IUserPasswordStore<User>,
IUserEmailStore<User>,
IUserRoleStore<User>,
IUserSecurityStampStore<User>
{
//omitted...
public Task SetSecurityStampAsync(User user, string stamp, CancellationToken cancellationToken = default(CancellationToken))
{
user.SecurityStamp = stamp;
return Task.FromResult(0);
}
public Task<string> GetSecurityStampAsync(User user, CancellationToken cancellationToken = default(CancellationToken))
{
if (user.SecurityStamp == null) {
return Task.FromResult("AspNet.Identity.SecurityStamp");
}
return Task.FromResult(user.SecurityStamp);
}
}
2.- In User.cs And DB Table User add SecurityStamp as string.
For TEST change default 30m to 1m in Startup.cs:
services.Configure<SecurityStampValidatorOptions>(options => {
options.ValidationInterval = TimeSpan.FromMinutes(1);
});