最近,我使用IdentityServer3为我的WebAPI实现了2FA。如果使用进行本地登录,则一切按预期工作。 现在,我希望能够通过发出部分登录cookie来进行此登录。这意味着我有一个API方法(POST),让用户在不输入主页面的情况下进行部分登录。 为了发出身份验证cookie,我执行以下操作(基于IdentityServer3 Extensions方法):
_owinContext.Environment.IssueLoginCookie(new AuthenticatedLogin
{
IdentityProvider = Constants.ExternalAuthenticationType,
Subject = userId,
Name = identityId,
Claims = new[] { new Claim(ClaimTypes.NameIdentifier, identityId) },
AuthenticationMethod = Constants.AuthenticationMethods.TwoFactorAuthentication
});
接下来,我将用户重定向回到登录页面,让他可以完全绕过2FA步骤进行登录。我本来希望这会使用户部分登录,但相反,它让用户完全登录了。
注意: 我实现双重认证的方式是基于 IUserService
的 AuthenticateLocalAsync
方法。在这里,我更新了 AuthenticateResult
以使用带有重定向路径的构造函数。API 方法不调用 IUserService
。它只发出登录 cookie。
编辑: 因此,在检查 IdentityServer3 的内部实现后,我现在能够让用户通过2FA屏幕。现在的问题是当部分登录成功(身份验证代码匹配)时,我将用户重定向到恢复 URL,但这会导致一个500错误页面(没有抛出异常或显示日志)。如果这发生在普通页面登录中,一切都正常。
处理用户的登录请求:
var messageId = clientIdentifier;
var claims = new List<Claim>();
(...)
var authenticationContext = new ExternalAuthenticationContext
{
ExternalIdentity = new ExternalIdentity() { Provider = "API", Claims = claims },
};
await _userService.AuthenticateExternalAsync(authenticationContext);
var authResult = authenticationContext.AuthenticateResult;
var ctx = new PostAuthenticationContext
{
AuthenticateResult = authResult
};
var id = authResult.User.Identities.FirstOrDefault();
var props = new AuthenticationProperties();
var resumeId = CryptoRandom.CreateUniqueId();
var resumeLoginUrl = _owinContext.GetPartialLoginResumeUrl(resumeId);
var resumeLoginClaim = new Claim(Constants.ClaimTypes.PartialLoginReturnUrl, resumeLoginUrl);
id.AddClaim(resumeLoginClaim);
id.AddClaim(new Claim(GetClaimTypeForResumeId(resumeId), messageId));
// add url to start login process over again (which re-triggers preauthenticate)
var restartUrl = _owinContext.GetPartialLoginRestartUrl(messageId);
id.AddClaim(new Claim(Constants.ClaimTypes.PartialLoginRestartUrl, restartUrl));
_owinContext.Authentication.SignIn(props, id);
// Sends the user to the 2FA pages (where he needs to insert the validation code).
// At this point the user is successfuly partially logged in.
var redirectUrl = GetRedirectUrl(authResult);
return Redirect(redirectUrl);
在输入双因素身份验证代码后,用户应该在输入简历URL后完全登录:
if (isAuthCodeValid)
{
var resumeUrl = await owinContext.Environment.GetPartialLoginResumeUrlAsync();
// Redirects the user to resume URL. This is not working if authentication is done by API but is working with normal local authentication.
// With API it redirects to a page which eventually will have 500 error (no logs or exceptions being shown)
return Redirect(resumeUrl);
}
你们有没有尝试过类似这样的事情,或者这是否可能?
idsrv.external
身份验证类型。在最后一个代码示例中,你期望进行部分登录,但这是不存在的,因为默认情况下部分登录具有idsrv.partial
身份验证类型,因此会出现500错误。 - laika