HttpContext.GetOwinContext().Authentication.GetExternalLoginInfoAsync() 使用 OKTA SAML2.0 成功登录后总是 return null

HttpContext.GetOwinContext().Authentication.GetExternalLoginInfoAsync() always return null after successfully login using OKTA SAML2.0

我目前正在尝试让 Okta 与我们基于 ASP.Net MVC 4.7 的应用程序一起工作。我观察到 okta 登录成功但不幸的是在身份验证(接受 saml 响应)质询之后,调用 ExternalLoginCallback 然后检查是否存在 Okta 信息以用于自己的身份验证但它总是 return null 引用 ExternalLoginCallback 方法。或 https://github.com/bvillanueva-mdsol/OktaSaml2OwinSample/issues/1 作为代码库,并在 git hub 中针对各自所有者提出了问题。

     <add key="ApplicationBaseUri" value="https://localhost:2687" />
  <add key="IdentityProviderIssuer" value="http://www.okta.com/exk3js0t73vBlN4Vq5d7" />
  <add key="IdentityProviderSsoUri" value="https://dev-00349616.okta.com/app/dev-00349616_httpslocalhost2687signinsaml_1/exk3js0t73vBlN4Vq5d7/sso/saml" />


 

public void Configuration(IAppBuilder app)
    {
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            AuthenticationMode = AuthenticationMode.Active
        });
        
        app.UseSaml2Authentication(CreateSaml2Options());
    }

    private static Saml2AuthenticationOptions CreateSaml2Options()
    {
        var applicationBaseUri = new Uri(ConfigurationManager.AppSettings["ApplicationBaseUri"]);
        var saml2BaseUri = new Uri(applicationBaseUri, "saml2");
        var identityProviderIssuer = ConfigurationManager.AppSettings["IdentityProviderIssuer"];
        var identityProviderSsoUri = new Uri(ConfigurationManager.AppSettings["IdentityProviderSsoUri"]);

        var Saml2Options = new Saml2AuthenticationOptions(false)
        {
            SPOptions = new SPOptions
            {
                EntityId = new EntityId(saml2BaseUri.AbsoluteUri),
                
                ReturnUrl = applicationBaseUri
                
            }
        };

        var identityProvider = new IdentityProvider(new EntityId(identityProviderIssuer), Saml2Options.SPOptions)
        {
            AllowUnsolicitedAuthnResponse = true,
            Binding = Saml2BindingType.HttpRedirect,
            SingleSignOnServiceUrl = identityProviderSsoUri
        };

        identityProvider.SigningKeys.AddConfiguredKey(
            new X509Certificate2(
                HostingEnvironment.MapPath(
                    "~/App_Data/okta.cert")));

        Saml2Options.IdentityProviders.Add(identityProvider);

        return Saml2Options;
    }

AccountController.cs 文件

 [AllowAnonymous]
    public ActionResult Login(string returnUrl)
    {
        //ControllerContext.HttpContext.Session.RemoveAll();
        return new Saml2ChallengeResult(Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
    }

    [AllowAnonymous]
    public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
    {
        var loginInfo = await  HttpContext.GetOwinContext().Authentication.GetExternalLoginInfoAsync();
        if (loginInfo == null) // always return null 
        {
            return RedirectToAction("LoginError");
        }

        var identity = new ClaimsIdentity(loginInfo.ExternalIdentity.Claims,
            DefaultAuthenticationTypes.ApplicationCookie);
        var authProps = new AuthenticationProperties
        {
            IsPersistent = true,
            ExpiresUtc = DateTime.UtcNow.AddMinutes(1)
        };            
        HttpContext.GetOwinContext().Authentication.SignIn(authProps, identity);

        return RedirectToLocal(returnUrl);
    }

    [AllowAnonymous]
    public ActionResult LoginError()
    {
        return Content("Error Logging in!");
    }

    private IAuthenticationManager AuthenticationManager =>
        HttpContext.GetOwinContext().Authentication;

    private ActionResult RedirectToLocal(string returnUrl)
    {
        if (Url.IsLocalUrl(returnUrl))
        {
            return Redirect(returnUrl);
        }
        return RedirectToAction("Index", "Home");
    }

    internal class Saml2ChallengeResult : HttpUnauthorizedResult
    {
        public string RedirectUri { get; set; }

        public Saml2ChallengeResult(string redirectUri)
        {
            RedirectUri = redirectUri;
        }
        
        public override void ExecuteResult(ControllerContext context)
        {
            context.RequestContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;

            var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
            context.HttpContext.GetOwinContext().Authentication.Challenge(properties, "Saml2");
        }
    }
}

解决方案与我错过的正确步骤更相关。

  1. 代码绝对没问题,它会起作用

为了 运行 应用程序,我们在 bin 文件夹中有 roslyn 文件夹,我错误地从 RUUNING https://localhost:44376 应用程序复制了 roslyn 文件夹。我们不应该将 roslyn 文件夹从 运行ning 应用程序复制并粘贴到 https://localhost:2687.

线索: 令人惊讶的是,IIS 显示 2 个应用程序 运行ning 甚至 https://localhost:44376 visual studio 应用程序已关闭。

现在我正在从 okta 获取登录信息详细信息