Skip IdentityServer3 login screen

2020-02-21 07:57发布

问题:

We have configured Client App to use IdentityServer3 authentication via OpenID Connect protocol (it's ASP.NET MVC App that uses OWIN middleware to support OIDC).

The IdentityServer3 itself is configured to use both local login and external login (Azure AD, for instance).

In the regular flow once App need to authenticate user it redirects him to the IdentityServer3 login screen - it's fine. But in some cases, on per-request basis, I want to bypass login screen by somehow letting IdentityServer3 know that user want to login with specific external identity provider right away.

Is that possible to do?

回答1:

Just found the solution in the 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

How to pass additional parameters using OWIN OpenID Connect middleware: https://katanaproject.codeplex.com/workitem/325

Here is the sample of the authorization request:



回答2:

I know this is old but thought I'd still put this here to help someone out if they want to automatically redirect to an external login:

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

You can basically override the PreAuthenticateAsync on UserServiceBase and change the property IdP on the context.SignInMessage to be the external providers name that has been setup in your startup. And this will redirect.



回答3:

When you configure identtyserver with external provider, In AuthenticationOptions you typically set AutheticationType to some string. Like below

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

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

Then in client application you can set the acrvalues to Authentication-type like below

        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);
                }
            }

Also note that the idp value is case sensitive.

The other option (which i have NOT tried). Instead of setting idp you set the tenant in client application.

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

And as @TheRock mentioned, In IndentityServer check the tenant in SignInMessage and override Idp

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

In this way as you keep adding new external providers, you don't have to change code in client application. You only to update IndentityServer code. This especially help if you have multiple client applications connecting to same identity server.