生产环境外部登录后 2FA 不工作

2FA not working after External login on production

我已经构建了一个 ASP.NET 核心网站,其前端为 angular。它通过 ASP.NET Core Identity 实现 external logins(Facebook、Twitter、Google、Microsoft)。上周我实施了与 Authenticator 应用程序一起使用的 2 因素身份验证。

我已将 Web 应用程序发布到 Plesk 环境。使用 email/password 登录时,来自身份验证器应用程序的 2FA 代码工作正常。但是,当使用外部登录提供商登录时,身份验证器应用程序中的 2FA 代码似乎不起作用。

然而,当我在 IIS Express 上进行测试时,一切都按预期工作,并且我能够使用 Facebook 登录,从身份验证器应用程序输入 OTP 并登录。

该项目的代码托管在 Github 上。本质上是这样的:

// C#
// The user navigates to the url hosting the `Challenge` for the external login specified
var redirectUrl = Url.RouteUrl("web-v3-account-external-connect-callback", new { medium, provider });
var properties = signin_manager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);

// After the user successfully signed in into the OAuth provider's login page
var info = await signin_manager.GetExternalLoginInfoAsync();
var user = await user_manager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);
// ...
var signinResult = await signin_manager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, true, user.Bypass2faForExternalLogin);
if (signinResult.Succeeded) {
    // ...
} else if (signinResult.RequiresTwoFactor) {
    return View(new ExternalLoginResultVM {
        Status = LoginStatus.RequiresTwoFactor
    });
}


// Angular
// The above MVC response is messaged to the angular app, to which the angular app detects
// that it needs to show the page to ask for the 2-factor verification code
socialLoginDone(result: LoginResult) {
    switch (result.status) {
        case LoginStatus.requiresTwoFactor: {
            this.router.navigate(['/account', 'two-factor'], {
                queryParams: { return: this.returnUrl }
            });
            break;
        }
    }
}

// After  the user entered the verification code, an ajax is being sent
verifyCode() {
    this.httpClient.post<string[]>(`${this.baseUrl}/web/${this.apiVersion}/Account/two-factor-login`, {
        code: this.setupCode,
        remember: false
    }).subscribe((backupCodes) => {
        this.accountService.currentUser().then((user) => {
            this.loginComplete.next(user);
            this.router.navigateByUrl(this.returnUrl);
        });
    });
    return false;
}

// C#
// performing the following code, which is also used for PasswordSignin
// https://github.com/MintPlayer/MintPlayer/blob/master/MP.Data/Repositories/AccountRepository.cs#L453
var user = await signin_manager.GetTwoFactorAuthenticationUserAsync();
var result = await signin_manager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, true, remember);
// This doesn't succeed for external login, on live environment.
if (result.Succeeded)
{
    return userMapper.Entity2Dto(user, true);
}
else
{
    throw new LoginException();
}

为什么这不起作用?我该如何解决这个问题?

显然您不能从子域调用 ExternalLoginSigninAsync,而从主域调用 TwoFactorAuthenticatorSignInAsync。所以现在我只需要找到一种从网络浏览器打开 URL 的方法,并防止它在 PWA 中打开...