Идентификатор Asp.Net с 2FA - помните cookie cookie, который не сохраняется после сеанса
Я использую последний образец кода для MVC5.2 с аутентификацией Asp.Identity и Two Factor.
С включенным 2FA, когда пользователь входит в систему, запрос запрашивает код (отправляется по телефону или электронной почте), и у них есть опция "Запомнить браузер" - так, чтобы они не запрашивали коды снова в этом браузере.
Это выполняется в действии VerifyCode
var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, isPersistent: model.RememberMe, rememberBrowser: model.RememberBrowser);
Обратите внимание, что model.RememberMe
не используется в шаблонах по умолчанию, поэтому он является ложным.
Я нахожу, когда я делаю это .AspNet.TwoFactorRememberBrowser
, который получает значение, заканчивается на конце сеанса (поэтому он не помнит браузер)
Теперь, если я устанавливаю isPersistent = true
, .AspNet.TwoFactorRememberBrowser
получает истечение 30 дней, что отлично, но .AspNet.ApplicationCookie
также получает истечение 30 дней - это означает, что когда я закрываю браузер и снова открываю, я я автоматически вошел в систему.
Я хочу, чтобы он не сохранял мой логин, но он сохранит мой выбор запоминания кода 2FA. Т.е. пользователю всегда нужно входить в систему, но им не следует запрашивать код 2fa, если он уже сохранил его.
Кто-нибудь еще видел это, или я чего-то не хватает?
Ответы
Ответ 1
Кажется, что этот код не был предназначен для установки более одного файла cookie идентичности в том же запросе/ответе, потому что обработчики cookie OWIN в конечном итоге используют одни и те же AuthenticationProperties. Это связано с тем, что аутентификацияResponseGrant имеет единственный основной, но руководитель может иметь несколько идентификаторов.
Вы можете обходить эту ошибку, изменяя и восстанавливая AuthenticationProperties в событиях ResponseSignIn и ResponseSignedIn, специфичных для поставщика cookie 2FA:
//Don't use this.
//app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
//Set the 2FA cookie expiration and persistence directly
//ExpireTimeSpan and SlidingExpiration should match the Asp.Net Identity cookie setting
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationType = DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie,
AuthenticationMode = AuthenticationMode.Passive,
CookieName = DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie,
ExpireTimeSpan = TimeSpan.FromHours(2),
SlidingExpiration = true,
Provider = new CookieAuthenticationProvider
{
OnResponseSignIn = ctx =>
{
ctx.OwinContext.Set("auth-prop-expires", ctx.Properties.ExpiresUtc);
ctx.OwinContext.Set("auth-prop-persist", ctx.Properties.IsPersistent);
var issued = ctx.Properties.IssuedUtc ?? DateTimeOffset.UtcNow;
ctx.Properties.ExpiresUtc = issued.AddDays(14);
ctx.Properties.IsPersistent = true;
},
OnResponseSignedIn = ctx =>
{
ctx.Properties.ExpiresUtc = ctx.OwinContext.Get<DateTimeOffset?>("auth-prop-expires");
ctx.Properties.IsPersistent = ctx.OwinContext.Get<bool>("auth-prop-persist");
}
}
});
Обязательно установите те же ExpireTimeSpan и SldingExpiration, что и ваш основной файл cookie Asp.Net Identity, чтобы сохранить эти настройки (поскольку они объединяются в AuthenticationResponseGrant).
Ответ 2
Это все еще кажется проблемой в Identity 2.2.1 (она может быть исправлена в Asp.Net Identity 3.0, но в настоящее время она предварительно выпущена и требует более поздней версии .Net framework, которая 4.5)
Следующая работа вокруг выглядит нормально:
Печенье устанавливается на SignInManager.TwoFactorSignInAsync с неправильными значениями, поэтому на Успех действия VerifyCode я reset cookie будет постоянным и дайте ему дату истечения срока действия, которую я желаю (в этом случае я установил ее в год)
public async Task<ActionResult> VerifyCode(VerifyCodeViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
} var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, isPersistent: model.RememberMe, rememberBrowser: model.RememberBrowser);
switch (result)
{
case SignInStatus.Success:
// if we remember the browser, we need to adjsut the expiry date as persisted above
// Also set the expiry date for the .AspNet.ApplicationCookie
if (model.RememberBrowser)
{
var user = await UserManager.FindByIdAsync(await SignInManager.GetVerifiedUserIdAsync());
var rememberBrowserIdentity = AuthenticationManager.CreateTwoFactorRememberBrowserIdentity(user.Id);
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = true, ExpiresUtc = DateTime.UtcNow.AddDays(365) }, rememberBrowserIdentity);
}
return RedirectToLocal(model.ReturnUrl);