Okta和Sustainsys.SAML2的AuthenticateResult.Succeeded为假 [英] AuthenticateResult.Succeeded is false with Okta and Sustainsys.SAML2

查看:90
本文介绍了Okta和Sustainsys.SAML2的AuthenticateResult.Succeeded为假的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个利用Sustainsys.Saml2.AspNetCor2(2.7.0)的.Net Core 2应用程序.前端是Angular应用程序.我采用的SAML方法基于此参考实现中的方法,并且与之非常相似:

我不知道如何进一步调查.任何帮助将不胜感激!

在ConfigureServices方法中,如果有用的话,我将在相关部分添加以下内容:

  public void ConfigureServices(IServiceCollection服务){//[snip]如果(使用SAML){services.Configure< CookiePolicyOptions>(options =>{//SameSiteMode.None不需要支持SAML SSO.options.MinimumSameSitePolicy = SameSiteMode.None;options.CheckConsentNeeded =上下文=>错误的;//一些较旧的浏览器不支持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 =>{//参见https://stackoverflow.com/questions/46243697/asp-net-core-persistent-authentication-custom-cookie-authenticationoptions.ExpireTimeSpan =新的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 =新的EntityId(this.Configuration ["Saml:SPEntityId"]]);options.IdentityProviders.Add(新的IdentityProvider(新的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]已通过Saml响应Microsoft.IdentityModel.Tokens.Saml2.Saml2Id的签名验证2020-09-14 09:28:09.369 -05:00 [DBG]提取的SAML声明ID16228944165055934699991422020-09-14 09:28:09.385 -05:00 [INF]成功处理了SAML响应Microsoft.IdentityModel.Tokens.Saml2.Saml2Id和经过身份验证的bankoetest@sfi.cloud 

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

  var authenticateResult =等待HttpContext.AuthenticateAsync(ApplicationSamlConstants.External); 

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

  2020-09-14 09:28:09.432 -05:00 [ERR] SAML身份验证失败:authenticateResult.Failure(异常对象)为null;没有返回有关身份验证方案的信息;authenticateResult.Principal为null;authenticateResult.Properties为null.authenticateResult.Ticket为空. 

出什么问题了?

解决方案

此处的根本原因最终是Okta与重定向逻辑中的代码所使用的Url情况不同的结果.URL匹配,但大小写不匹配.这会导致Cookie不能被后来调用的方法读取,这些方法被发送到另一个URL,即使该区别只是路径的大小写不同.一旦确保所有路径完全匹配(一直到套管),它便开始工作.

I have a .Net Core 2 application which leverages Sustainsys.Saml2.AspNetCor2 (2.7.0). The front end is an Angular application. The SAML approach I'm taking is based on, and very similar to, the approach taken in this reference implementation: https://github.com/hmacat/Saml2WebAPIAndAngularSpaExample

*Everything works fine with the test IDP (https://stubidp.sustainsys.com).

But when we try to integrate with Okta, the AuthenticateResult.Succeeded property in the callback method (see below) is always false, even though the SAML posted to the ASC endpoint appears to indicate a successful authentication. We are not seeing any errors at all. It's just not succeeding.

(Note that my company does not have access to Okta - that is maintained by a partner company.)

Here is the server code in the controller:

[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
  
   }

Here is a screenshot of some of the SAML sent by Okta, captured using the Chrome extension, SAML-tracer:

I don't know how to investigate this further. Any help would be most appreciated!

In the ConfigureServices method, in case it's useful, I have the following (in relevant part):

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]
}

UPDATE: I modified the code to capture more logging information, and what I have found is that, at the Saml2/Acs endpoint, the user is being authenticated. In the log files, I see this:

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

However, when I get to the SamlLoginCallback method, this authentication information is not present in the AuthenticateResult obtained by this call:

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

My custom logging information for the authentication result object looks like this:

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.

What could be going wrong?

解决方案

The root cause here was ultimately the result of differences in the case of the Url used by Okta vs our code in redirect logic. The URLs matched, but the case did not. This caused cookies to be unreadable by later-invoked methods which were being sent to a URL which was different, even though the difference was only in the casing of the path. Once we made sure that all paths matched exactly, down to the casing, it started working.

这篇关于Okta和Sustainsys.SAML2的AuthenticateResult.Succeeded为假的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆