2
votes

AM trying to implement multiple authentication based on the organization request.I have some thing like below in startup.auth.cs

 foreach (OrganizationModel org in orgList)
    {
        if (org.AuthenticationType != "Azure")
        {
            var adfs = new WsFederationAuthenticationOptions
            {
                AuthenticationType = org.AuthenticationType,
                Caption = org.Caption,
                BackchannelCertificateValidator = null,
                MetadataAddress = org.MetadataUrl,
                Wtrealm = org.Realm,
                Notifications = new WsFederationAuthenticationNotifications
                {
                    AuthenticationFailed = context =>
                    {
                        context.HandleResponse();
                        context.Response.Redirect("Home/Error?message=" + context.Exception.Message);
                        return Task.FromResult(0);
                    }
                },
                TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false },

            };
            app.UseWsFederationAuthentication(adfs);
        }
        else
        {
            var azure = new WsFederationAuthenticationOptions
            {
                AuthenticationType = org.AuthenticationType,
                Caption = org.Caption,
                BackchannelCertificateValidator = null,
                MetadataAddress = org.MetadataUrl,
                Wtrealm = org.Realm,
                Notifications = new WsFederationAuthenticationNotifications
                {
                    AuthenticationFailed = context =>
                    {
                        context.HandleResponse();
                        context.Response.Redirect("Home/Error?message=" + context.Exception.Message);
                        return Task.FromResult(0);
                    }
                },
                TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false },

            };
            app.UseWsFederationAuthentication(azure);
        }
    }

I populate the various authentication provider for login. When I click on ADFS am able to authenticate, get claims, everything works fine. but when I try to authenticate against Azure AD I get Error "ID 4037", The key needed to verify signature could not be resolved. Note: If i try to do Azure AD alone (comment ADFS part) it works fine. Orglist gets populated from DB and it contains information like Metadata url, Realm etc. For Dev purpose i have configured https://localhost:44303 as realm for both.

My callback method after login is

 [AllowAnonymous]
        public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
        {
            var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

            if (loginInfo == null)
            {
                return RedirectToAction("Login");
            }

            // Sign in the user with this external login provider if the user already has a login
            var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
            switch (result)
            {
                case SignInStatus.Success:
                    return RedirectToLocal(returnUrl);
                case SignInStatus.LockedOut:
                    return View("Lockout");
                case SignInStatus.RequiresVerification:
                    return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false });
                case SignInStatus.Failure:
                default:
                    // If the user does not have an account, then prompt the user to create an account
                    ViewBag.ReturnUrl = returnUrl;
                    ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
                    return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.DefaultUserName});
            }
        }

guide me where am going wrong

1

1 Answers

2
votes

I figured out what is the issue. When we have multiple Authentication Providers, the Authentication type for each of Authentication option getting added to OWIN Middleware pipeline should be unique. For somebody who is trying to implement similar solution the code that worked for me is given below.

 foreach (OrganizationModel org in orgList)
            {
                switch (org.AuthenticationName)
                {
                    case "ADFS":
                                var adfs = new WsFederationAuthenticationOptions
                                      {
                                          AuthenticationType = org.AuthenticationType,
                                          Caption = org.Caption,
                                          BackchannelCertificateValidator = null,
                                          MetadataAddress = org.MetadataUrl,
                                          Wtrealm = org.Realm,
                                          SignOutWreply = org.Realm,
                                          Notifications = new WsFederationAuthenticationNotifications
                                          {
                                              AuthenticationFailed = context =>
                                              {
                                                  context.HandleResponse();
                                                  context.Response.Redirect("Home/Error?message=" + context.Exception.Message);
                                                  return Task.FromResult(0);
                                              }
                                          },
                                          TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false },
                                      };
                        app.UseWsFederationAuthentication(adfs);
                        break;
                    case "Azure":
                        OpenIdConnectAuthenticationOptions azure = null;
                        azure = new OpenIdConnectAuthenticationOptions
                        {
                            AuthenticationType = org.AuthenticationType,
                            Caption = org.Caption,
                            BackchannelCertificateValidator = null,
                            Authority = org.MetadataUrl,
                            ClientId = org.ClientId,
                            RedirectUri = org.Realm,
                      PostLogoutRedirectUri=org.Realm,
                            Notifications = new OpenIdConnectAuthenticationNotifications
                         {
                             AuthenticationFailed = context =>
                             {
                                 context.HandleResponse();
                                 context.Response.Redirect("Home/Error?message=" + context.Exception.Message);
                                 return Task.FromResult(0);
                             }
                         },
                        };
                        app.UseOpenIdConnectAuthentication(azure);
                        break;
                    case "Shibboleth":
                    break;
                    default:
                        break;
                }
            }