Недавно я реализовал 2FA для своего веб-API с использованием Identity Server 3. Все работает, как и ожидалось, если вход выполняется локально (с использованием IUserService).Теперь я хочу иметь возможность войти в систему, выполнив частичный файл cookie для входа.Это означает, что у меня есть метод API (POST), который позволяет пользователям частично входить в систему, не заходя на главную страницу.Для выдачи куки аутентификации это то, что я делаю (на основе метода IS3 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.,Я прыгал, что это заставило бы пользователя частично войти в систему, но вместо этого он полностью вошел в систему пользователя.
Примечание: Способ, которым я реализовал Two Factor, основан на AuthenticateLocalAsync метод из IUserService.Здесь я обновляю 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);
После вставки кода 2FA пользователь должен войти в систему после ввода 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 works 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);
}
Ребята, вы когда-нибудь пытались сделать что-то подобное или это вообще возможно?