Идентификатор 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);