c# - IdentityServer4 和 Azure AD 在登录页面上自动选择用户

标签 c# azure azure-active-directory identityserver4 openid-connect

最近,当人们尝试通过我们的服务使用 Microsoft 帐户登录时,Microsoft 似乎改变了一些行为。

我们有一个设置,将 IdentityServer4 和 Azure AD 用于 Microsoft 帐户。当人们现在尝试登录时,只需单击我们网页上的登录按钮即可进入 Microsoft 登录。在这里,微软似乎自动选择已经登录的用户,然后继续登录该用户。

这会导致两个问题。

  1. 用户很难理解他们的帐户只是自动选择的。
  2. 如果用户速度足够快,他们可以点击自己的用户,这会向我们的服务器发送两个回调,并且会发生竞争条件,这会导致一半的时间出现 OperationCancelledException

我们的设置非常接近 IdentityServer4s 快速入门指南中给出的示例:

serviceCollection
    .AddAuthentication(o =>
    {
        o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddMicrosoftAccount("Microsoft", "Microsoft", o =>
    {
        o.SignInScheme = IdentityConstants.ExternalScheme;
        o.ClientId = _externalKeysOptions.MicrosoftClientId;
        o.ClientSecret = _externalKeysOptions.MicrosoftClientSecret;
        o.CallbackPath = new PathString("/signin-microsoft");
        new[]
        {
            "offline_access",
            "Calendars.Read.Shared",
            "Calendars.ReadWrite",
            "Tasks.Readwrite"
        }.ForEach(scope => o.Scope.Add(scope));
        o.SaveTokens = true;
    })

我们按照上面的方式设置身份验证方案。然后我们对提供者进行正常的挑战:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[Route("externallogin")]
public IActionResult ExternalLogin(ExternalLoginModel model)
{
    var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { model.ReturnUrl, termsOfServiceAccepted = model.AgreeToTerms, platform = model.Platform });
    var properties = _signInManager.ConfigureExternalAuthenticationProperties(model.Provider, redirectUrl);

    return Challenge(properties, model.Provider);
}

有人知道为什么会发生这种情况吗?我真的很想在用户使用 Microsoft 登录时禁用用户帐户的自动选择。因为这主要是让我们的客户感到困惑而不是帮助他们。

欢迎任何资源。提前致谢。

最佳答案

好吧,我终于弄清楚问题出在哪里了。我认为微软已经改用OIDC作为身份验证方法。

这意味着我们现在可以在查询字符串中发送prompt参数。

来自 OIDC documentation :

prompt
OPTIONAL. Space delimited, case sensitive list of ASCII string values that specifies whether the Authorization Server prompts the End-User for reauthentication and consent. The defined values are:
   none
     The Authorization Server MUST NOT display any authentication or consent user interface pages. An error is returned if an End-User is not already authenticated or the Client does not have pre-configured consent for the requested Claims or does not fulfill other conditions for processing the request. The error code will typically be login_required, interaction_required, or another code defined in Section 3.1.2.6. This can be used as a method to check for existing authentication and/or consent.
   login
     The Authorization Server SHOULD prompt the End-User for reauthentication. If it cannot reauthenticate the End-User, it MUST return an error, typically login_required.
   consent
     The Authorization Server SHOULD prompt the End-User for consent before returning information to the Client. If it cannot obtain consent, it MUST return an error, typically consent_required.
   select_account
     The Authorization Server SHOULD prompt the End-User to select a user account. This enables an End-User who has multiple accounts at the Authorization Server to select amongst the multiple accounts that they might have current sessions for. If it cannot obtain an account selection choice made by the End-User, it MUST return an error, typically account_selection_required.

这意味着我们现在需要在询问用户时将 prompt=select_account 添加到查询参数中。

不幸的是,MicrosoftAccount nuget 包目前不支持此功能。所以我必须添加一些技巧才能使其正常工作:

.AddMicrosoftAccount("Microsoft", "Microsoft", o =>
{
    o.SignInScheme = IdentityConstants.ExternalScheme;
    o.ClientId = _externalKeysOptions.MicrosoftClientId;
    o.ClientSecret = _externalKeysOptions.MicrosoftClientSecret;
    o.CallbackPath = new PathString("/signin-microsoft");
    new[]
    {
        "offline_access",
        "Calendars.Read.Shared",
        "Calendars.ReadWrite",
        "Tasks.Readwrite",
        "openid"
    }.ForEach(scope => o.Scope.Add(scope));
    o.SaveTokens = true;
    o.Events = new OAuthEvents
    {
        OnRedirectToAuthorizationEndpoint = context =>
        {
            var uriBuilder = new UriBuilder(context.RedirectUri);
            var query = HttpUtility.ParseQueryString(uriBuilder.Query);
            query["prompt"] = "select_account";
            uriBuilder.Query = query.ToString();
            var newRedirectUri = uriBuilder.ToString();
            context.Response.Redirect(newRedirectUri);
            return Task.CompletedTask;
        }
    };
})

修复此问题的代码是 OnRedirectToAuthorizationEndpoint,我将查询参数添加到 URL。

关于c# - IdentityServer4 和 Azure AD 在登录页面上自动选择用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56163695/

相关文章:

c# - Webview 控件在 WP 8.1 Runtime 中消耗过多内存

entity-framework - Azure SQL 数据仓库和 Entity Framework

azure - 没有角色分配的服务主体有什么用

Azure AD - token 中缺少角色声明

c# - 具有数据库生成的属性的 SubmitChanges 上的 NullReferenceException

c# - 如何确定字符串是 C# 中的有效 IPv4 还是 IPv6 地址?

c# - 将文本框绑定(bind)到 Listview GridViewColumn

.net - 如何阻止我的 Azure 网站将所有 HTTP 流量自动重定向到 HTTPS?

deployment - 为什么 Azure 部署需要这么长时间?

azure - 使用 MSAL 保护 Azure Function API