Identity.TwoFactorRememberMe 的问题和更新的用户 SecurityStamp
Problems with Identity.TwoFactorRememberMe and updated user SecurityStamp
使用验证器应用程序使用双因素登录后,我将 rememberClient 设置为 true,如下所示:
await _signInManager.TwoFactorAuthenticatorSignInAsync(code: request.Code,
isPersistent: request.IsPersistent,
rememberClient: request.RememberClient);
登录正常,我得到了 .AspNetCore.Identity.Application
和 Identity.TwoFactorRememberMe
cookie。如果我退出并再次登录,则不需要使用双因素。这么久就没事了
问题是当我对用户进行一些更改时,例如 phone 号码,并且更改了 SecurityStamp。更改完成后,我使用 await _signInManager.RefreshSignInAsync(user)
。但是 Identity.TwoFactorRememberMe
cookie 没有更新。这会导致两个问题:
- 下次登录时,我必须再次使用双因素身份验证。
- 在同一个会话中,如果我检查用户是否记得浏览器,使用
await _signInManager.IsTwoFactorClientRememberedAsync(user)
,将导致错误 "Failed to validate a security stamp" 并且 .AspNetCore.Identity.Application
将被删除。
我尝试在 .AspNetCore.Identity.Application
cookie 的同时更新 Identity.TwoFactorRememberMe
cookie,如下所示:
await base.RefreshSignInAsync(user);
await RememberTwoFactorClientAsync(user);
它有效,但它也会为那些以前没有它的人设置 Identity.TwoFactorRememberMe
cookie。我无法检查它之前是否设置过,因为那时我得到了上面 (2) 中描述的错误。
接下来我要尝试的是在每个地方都做这样的事情,我会做一些改变用户 SecurityStamp 的事情:
var isTwoFactorClientRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user);
// do the changes...
await _signInManager.RefreshSignInAsync(user);
if (isTwoFactorClientRememberedAsync)
await _signInManager.RememberTwoFactorClientAsync(user);
我是否遗漏了什么,或者这是唯一的方法吗?
我正在使用 IdentityServer4 和 SPA 应用程序,但我认为这与问题无关。
我最终在我的自定义 ApplicationSignInManager 中添加了一个方法:
public async Task<TResult> KeepSignInAsync<TResult>(ApplicationUser user, Func<Task<TResult>> func)
{
var isTwoFactorClientRemembered = await IsTwoFactorClientRememberedAsync(user);
var result = await func();
await RefreshSignInAsync(user);
if (isTwoFactorClientRemembered)
await RememberTwoFactorClientAsync(user);
return result;
}
当我更改将更新用户 SecurityStamp 的内容时,我会这样使用它:
var result = await _signInManager.KeepSignInAsync(user, () => _userManager.SetPhoneNumberAsync(user, phoneNumber));
使用验证器应用程序使用双因素登录后,我将 rememberClient 设置为 true,如下所示:
await _signInManager.TwoFactorAuthenticatorSignInAsync(code: request.Code,
isPersistent: request.IsPersistent,
rememberClient: request.RememberClient);
登录正常,我得到了 .AspNetCore.Identity.Application
和 Identity.TwoFactorRememberMe
cookie。如果我退出并再次登录,则不需要使用双因素。这么久就没事了
问题是当我对用户进行一些更改时,例如 phone 号码,并且更改了 SecurityStamp。更改完成后,我使用 await _signInManager.RefreshSignInAsync(user)
。但是 Identity.TwoFactorRememberMe
cookie 没有更新。这会导致两个问题:
- 下次登录时,我必须再次使用双因素身份验证。
- 在同一个会话中,如果我检查用户是否记得浏览器,使用
await _signInManager.IsTwoFactorClientRememberedAsync(user)
,将导致错误 "Failed to validate a security stamp" 并且.AspNetCore.Identity.Application
将被删除。
我尝试在 .AspNetCore.Identity.Application
cookie 的同时更新 Identity.TwoFactorRememberMe
cookie,如下所示:
await base.RefreshSignInAsync(user);
await RememberTwoFactorClientAsync(user);
它有效,但它也会为那些以前没有它的人设置 Identity.TwoFactorRememberMe
cookie。我无法检查它之前是否设置过,因为那时我得到了上面 (2) 中描述的错误。
接下来我要尝试的是在每个地方都做这样的事情,我会做一些改变用户 SecurityStamp 的事情:
var isTwoFactorClientRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user);
// do the changes...
await _signInManager.RefreshSignInAsync(user);
if (isTwoFactorClientRememberedAsync)
await _signInManager.RememberTwoFactorClientAsync(user);
我是否遗漏了什么,或者这是唯一的方法吗?
我正在使用 IdentityServer4 和 SPA 应用程序,但我认为这与问题无关。
我最终在我的自定义 ApplicationSignInManager 中添加了一个方法:
public async Task<TResult> KeepSignInAsync<TResult>(ApplicationUser user, Func<Task<TResult>> func)
{
var isTwoFactorClientRemembered = await IsTwoFactorClientRememberedAsync(user);
var result = await func();
await RefreshSignInAsync(user);
if (isTwoFactorClientRemembered)
await RememberTwoFactorClientAsync(user);
return result;
}
当我更改将更新用户 SecurityStamp 的内容时,我会这样使用它:
var result = await _signInManager.KeepSignInAsync(user, () => _userManager.SetPhoneNumberAsync(user, phoneNumber));