跳过 IdentityServer3 登录屏幕

Skip IdentityServer3 login screen

我们已将客户端应用程序配置为通过 OpenID Connect 协议使用 IdentityServer3 身份验证(它是 ASP.NET 使用 OWIN 中间件支持 OIDC 的 MVC 应用程序)。

IdentityServer3 本身配置为使用本地登录和外部登录(例如 Azure AD)。

在常规流程中,一旦应用程序需要对用户进行身份验证,它会将用户重定向到 IdentityServer3 登录屏幕 - 没问题。但在某些情况下,根据每个请求,我想通过某种方式让 IdentityServer3 知道用户想要立即使用特定的外部身份提供者登录来绕过登录屏幕。

可以吗?

刚刚在 IdentityServer3's Authorization/Authentication Endpoint documentation!

中找到了解决方案

acr_values (optional) allows to pass additional authentication related information to the user service - there are also values with special meaning: idp:name_of_idp bypasses the login/home realm screen and forwards the user directly to the selected identity provider (if allowed per client configuration) tenant:name_of_tenant can be used to pass a tenant name to the user service

如何使用 OWIN OpenID Connect 中间件传递附加参数:https://katanaproject.codeplex.com/workitem/325

这是授权请求的示例:

我知道这已经过时了,但我想我仍然会把它放在这里以帮助那些想要自动重定向到外部登录的人:

public override Task PreAuthenticateAsync(PreAuthenticationContext context)
{
    context.SignInMessage.IdP = "windows";
    return base.PreAuthenticateAsync(context);  
}

您基本上可以覆盖 UserServiceBase 上的 PreAuthenticateAsync 并将 context.SignInMessage 上的 属性 IdP 更改为已在启动时设置的外部提供商名称。这将重定向。

当您使用外部提供程序配置 identtyserver 时,在 AuthenticationOptions 中,您通常将 AutheticationType 设置为某个字符串。喜欢下面

           app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions
            {
                AuthenticationType = "Google",
                Caption = "Sign-in with Google",
                SignInAsAuthenticationType = signInAsType,

                ClientId = ConfigurationManager.AppSettings["google:clientid"],
                ClientSecret = ConfigurationManager.AppSettings["google:clientsecret"],
            });

然后在客户端应用程序中,您可以将 acrvalues 设置为身份验证类型,如下所示

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {           

            Notifications = new OpenIdConnectAuthenticationNotifications
            {            

                RedirectToIdentityProvider = (n) =>
                {
                    if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.AuthenticationRequest)
                    {
                        if(n.Request.Uri == "someurl")
                         {
                        //set acrvalues. the value of the `idp`, (which is `Google` in this case) must match with the `AutheticationType` you set in IdentityServer
                        n.ProtocolMessage.AcrValues = "idp:Google"; 
                        }
                    }


                    return Task.FromResult(0);
                }
            }

另请注意,idp 值区分大小写。

另一个选项(我没试过)。您可以在客户端应用程序中设置 tenant 而不是设置 idp

   n.ProtocolMessage.AcrValues = "tenant:" + n.Request.Uri.ToString();

正如@TheRock 提到的,在 IndentityServer 中检查 SignInMessage 中的租户并覆盖 Idp

public override Task PreAuthenticateAsync(PreAuthenticationContext context)
{
   if(context.SignInMessage.Tenant = "sometenant")
   {
      context.SignInMessage.IdP = "Google";
      return base.PreAuthenticateAsync(context);  
   }
}

通过这种方式,当您不断添加新的外部提供程序时,您不必更改客户端应用程序中的代码。您只需更新 IndentityServer 代码。如果您有多个客户端应用程序连接到同一身份服务器,这尤其有用。