首页 > 解决方案 > Okta 和 Sustainsys.SAML2 的 AuthenticateResult.Succeeded 为假

问题描述

我有一个利用 Sustainsys.Saml2.AspNetCor2 (2.7.0) 的 .Net Core 2 应用程序。前端是一个 Angular 应用程序。我采用的 SAML 方法基于并且非常类似于此参考实现中采用的方法:https ://github.com/hmacat/Saml2WebAPIAndAngularSpaExample

*测试 IDP ( https://stubidp.sustainsys.com ) 一切正常。

但是当我们尝试与 Okta 集成时,回调方法(见下文)中的 AuthenticateResult.Succeeded 属性始终为 false,即使发布到 ASC 端点的 SAML 似乎表明身份验证成功。我们根本没有看到任何错误。它只是没有成功。

(请注意,我的公司无法访问 Okta - 这是由合作伙伴公司维护的。)

这是控制器中的服务器代码:

[AllowAnonymous]
    [HttpPost, HttpGet]
    [Route("api/Security/InitiateSamlSingleSignOn")]
    public IActionResult InitiateSamlSingleSignOn(string returnUrl)
    {
      return new ChallengeResult(
          Saml2Defaults.Scheme,
          new AuthenticationProperties
          {
            RedirectUri = Url.Action(nameof(SamlLoginCallback), new { returnUrl })
          });
    }

    [AllowAnonymous]
    [HttpPost, HttpGet]
    [Route("api/Security/SamlLoginCallback")]
    public async Task<IActionResult> SamlLoginCallback(string returnUrl)
    {
      var authenticateResult = await HttpContext.AuthenticateAsync(ApplicationSamlConstants.External);

      if (!authenticateResult.Succeeded)
      {
        return Unauthorized();
      }
  
     // more code below, never reached
  
   }

这是 Okta 发送的一些 SAML 的屏幕截图,使用 Chrome 扩展程序 SAML-tracer 捕获: 在此处输入图像描述

我不知道如何进一步调查。非常感激任何的帮助!

在 ConfigureServices 方法中,如果它有用,我有以下(在相关部分):

public void ConfigureServices(IServiceCollection services)
{
  // [snip]
  if (usingSAML)
  {
    services.Configure<CookiePolicyOptions>(options =>
    {
      // SameSiteMode.None is required to support SAML SSO.
      options.MinimumSameSitePolicy = SameSiteMode.None;

      options.CheckConsentNeeded = context => false;

      // Some older browsers don't support SameSiteMode.None.
      options.OnAppendCookie = cookieContext => SameSite.CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
      options.OnDeleteCookie = cookieContext => SameSite.CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
    });
    
    authBuilder = services.AddAuthentication(o =>
    {
      o.DefaultScheme = ApplicationSamlConstants.Application;
      o.DefaultSignInScheme = ApplicationSamlConstants.External;
      o.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
      o.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    });

    authBuilder.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
    {
      // see https://stackoverflow.com/questions/46243697/asp-net-core-persistent-authentication-custom-cookie-authentication
      options.ExpireTimeSpan = new System.TimeSpan(365, 0, 0, 0, 0);
      options.AccessDeniedPath = new PathString("/login");
      options.LoginPath = new PathString("/login");
    })
    .AddCookie(ApplicationSamlConstants.Application)
    .AddCookie(ApplicationSamlConstants.External)
    .AddSaml2(options =>
    {
      options.SPOptions.EntityId = new EntityId(this.Configuration["Saml:SPEntityId"]);
      options.IdentityProviders.Add(
          new IdentityProvider(
              new EntityId(this.Configuration["Saml:IDPEntityId"]), options.SPOptions)
          {
            MetadataLocation = this.Configuration["Saml:IDPMetaDataBaseUrl"],
            LoadMetadata = true,
          });
      options.SPOptions.ServiceCertificates.Add(new X509Certificate2(this.Configuration["Saml:CertificateFileName"]));
    });
  }
 // [snip]
}

更新:我修改了代码以捕获更多日志记录信息,我发现,在 Saml2/Acs 端点,用户正在接受身份验证。在日志文件中,我看到:

2020-09-14 09:28:09.307 -05:00 [DBG] Signature validation passed for Saml Response Microsoft.IdentityModel.Tokens.Saml2.Saml2Id
2020-09-14 09:28:09.369 -05:00 [DBG] Extracted SAML assertion id1622894416505593469999142
2020-09-14 09:28:09.385 -05:00 [INF] Successfully processed SAML response Microsoft.IdentityModel.Tokens.Saml2.Saml2Id and authenticated bankoetest@sfi.cloud

但是,当我使用 SamlLoginCallback 方法时,此调用获得的 AuthenticateResult 中不存在此身份验证信息:

 var authenticateResult = await HttpContext.AuthenticateAsync(ApplicationSamlConstants.External);

我的身份验证结果对象的自定义日志记录信息如下所示:

2020-09-14 09:28:09.432 -05:00 [ERR] SAML Authentication Failure: authenticateResult.Failure (Exception object) is null; 
No information was returned for the authentication scheme; 
authenticateResult.Principal is null; 
authenticateResult.Properties is null.
authenticateResult.Ticket is null.

可能出了什么问题?

标签: asp.net-coresaml-2.0oktasustainsys-saml2

解决方案


这里的根本原因最终是 Okta 使用的 Url 与我们在重定向逻辑中的代码不同的结果。URL 匹配,但案例不匹配。这导致后来调用的方法无法读取 cookie,这些方法被发送到不同的 URL,即使不同之处仅在于路径的大小写。一旦我们确保所有路径都完全匹配,直到外壳,它就开始工作了。


推荐阅读