问题描述
我有一个利用Sustainsys.Saml2.AspNetCor2(2.7.0)的.Net Core 2应用程序。前端是Angular应用程序。我采用的SAML方法基于并非常类似于此参考实现中采用的方法:https://github.com/hmacat/Saml2WebAPIAndAngularSpaExample
*测试IDP(https://stubidp.sustainsys.com)一切正常。
但是,当我们尝试与Okta集成时,即使发布到ASC端点的SAML似乎表明身份验证成功,回调方法(请参见下文)中的AuthenticateResult.Succeeded属性始终为false。我们根本没有看到任何错误。只是没有成功。
(请注意,我的公司无权访问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);
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 [email protected]
但是,当我进入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 @R_1_4045@ion was returned for the authentication scheme;
authenticateResult.Principal is null;
authenticateResult.Properties is null.
authenticateResult.Ticket is null.
出什么问题了?
解决方法
这里的根本原因最终是Okta使用的Url与我们的重定向逻辑中的代码存在差异的结果。 URL匹配,但大小写不匹配。这会导致Cookie无法被后来调用的方法读取,这些方法被发送到另一个URL,即使该区别只是路径的大小写不同。一旦确保所有路径完全匹配(一直到套管),它便开始工作。