-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Closed
Closed
Copy link
Labels
Description
Is there an existing issue for this?
- I have searched the existing issues
Description
This is my flow set
Firstly, User Login with username/password
public override async Task OnPostAsync(string action)
{
await CheckLocalLoginAsync();
ValidateModel();
//Verify captcha token:
if (CaptchaToken is not null
&& !(await GoogleCaptchaService.VerifyTokenAsync(CaptchaToken)))
{
Alerts.Warning(L["CaptchaNotValidMessage"]);
return Page();
}
ExternalProviders = await GetExternalProviders();
EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);
await ReplaceEmailToUsernameOfInputIfNeeds();
await IdentityOptions.SetAsync();
var result = await SignInManager.PasswordSignInAsync(
LoginInput.UserNameOrEmailAddress,
LoginInput.Password,
LoginInput.RememberMe,
true
);
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = result.ToIdentitySecurityLogAction(),
UserName = LoginInput.UserNameOrEmailAddress
});
// check if we are in the context of an authorization request
//var context = await _interaction.GetAuthorizationContextAsync(ReturnUrl);
// var requires2Fa = context?.AcrValues.Count(t => t.Contains("mfa")) >= 1;
var disableMfa = await _settingProvider.GetOrNullAsync(SdgIdentitySettingNames.TwoFactor.Behavior)
== TwoFactorBehavior.Disabled.ToString();
if (result.RequiresTwoFactor && !disableMfa)
{
return await TwoFactorLoginResultAsync();
}
if (result.IsLockedOut)
{
Alerts.Warning(L["UserLockedOutMessage"]);
return Page();
}
if (result.IsNotAllowed)
{
Alerts.Warning(L["LoginIsNotAllowed"]);
return Page();
}
if (!result.Succeeded)
{
Alerts.Danger(L["InvalidUserNameOrPassword"]);
return Page();
}
var forceSetup2Fa = await _settingProvider.GetOrNullAsync(SdgIdentitySettingNames.TwoFactor.Behavior) == TwoFactorBehavior.Forced.ToString();
//TODO: Find a way of getting user's id from the logged in user and do not query it again like that!
var user = await UserManager.FindByNameAsync(LoginInput.UserNameOrEmailAddress) ??
await UserManager.FindByEmailAsync(LoginInput.UserNameOrEmailAddress);
if (user != null && !user.TwoFactorEnabled && forceSetup2Fa)
{
return RedirectToPage("/Account/EnableAuthenticator" , new {ReturnUrl = ReturnUrl, ReturnUrlHash = ReturnUrlHash});
}
Debug.Assert(user != null, nameof(user) + " != null");
// Clear the dynamic claims cache.
await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId);
return await RedirectSafelyAsync(ReturnUrl, ReturnUrlHash);
}
/// <summary>
/// Override this method to add 2FA for your application.
/// </summary>
protected override async Task<IActionResult> TwoFactorLoginResultAsync()
{
return RedirectToPage("./LoginWith2fa", new { ReturnUrl = ReturnUrl, RememberMe = LoginInput.RememberMe });
}
Secondly if user is TwoFactorEnabled = true , it will redirect to LoginWith2fa
public async Task OnPostAsync(bool rememberMe, string? returnUrl = null)
{
if (!ModelState.IsValid)
{
return Page();
}
returnUrl = ReturnUrl ?? Url.Content("~/");
var user = await SignInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
RedirectToPage("./Login", new {ReturnUrl = ReturnUrl, ReturnUrlHash = ReturnUrlHash} );
//throw new InvalidOperationException($"Unable to load two-factor authentication user.");
}
var authenticatorCode = Input.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty);
var result = await SignInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, Input.RememberMachine);
if (result.Succeeded)
{
// // Lấy principal hiện tại
// var principal = await SignInManager.CreateUserPrincipalAsync(await SignInManager.UserManager.GetUserAsync(User));
//
// // Thêm claim "amr" = "mfa"
// var identity = principal;
// identity.AddClaim(OpenIddictConstants.Claims.AuthenticationMethodReference,
// OpenIddictConstants.AuthenticationMethodReferences.MultiFactor);
//
// // Đăng nhập lại (hoặc update cookie) với principal đã thêm amr
// // await SignInManager.Context.SignInAsync(IdentityConstants.ApplicationScheme, principal);
if (user != null)
{
Logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", user.Id);
}
return LocalRedirect(returnUrl);
}
if (result.IsLockedOut)
{
//_logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id);
//return RedirectToPage("./Lockout");
Alerts.Danger(L["UserLockedOutMessage"]);
return Page();
}
Logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", user.Id);
//ModelState.AddModelError(string.Empty, "Invalid authenticator code.");
Alerts.Warning(L["InvalidAuthenticatorCode"]);
return Page();
}
but in .Web receive token do not have claim amr : mfa
Reproduction Steps
Here is Claims after logn with 2fa

And here is claims when openid issue token:
Expected behavior
No response
Actual behavior
No response
Regression?
No response
Known Workarounds
No response
Version
9.0
User Interface
MVC
Database Provider
EF Core (Default)
Tiered or separate authentication server
Tiered
Operation System
Windows (Default)
Other information
No response
