sustainsys.sAML2多授予实现,app.map()
我有多个租户应用程序,每个租户可以使用不同的IDP进行身份验证。以下代码正确地将其重定向到IDP,但问题是恢复对ACS端点的响应。
关键是配置路径及其身份验证的配置方法:
[assembly: OwinStartup(typeof(SSOSamlDemoASPNET.App_Start.Startup))]
namespace SSOSamlDemoASPNET.App_Start
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Map("/client/okta", (appx) =>
{
ConfigureAuthentication(appx, "/client/okta/Saml2", ...);
});
app.Map("/client/azuread", (appx) =>
{
ConfigureAuthentication(appx, "/client/azuread/Saml2", ...);
});
}
private static void ConfigureAuthentication(IAppBuilder app, string modulePath, string audience, string issuer, string metadataUrl)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
CookieName = "LoggedUser",
CookiePath = "/",
CookieManager = new SystemWebCookieManager(),
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
ConfigureSaml(app, modulePath, audience, issuer, metadataUrl);
}
private static void ConfigureSaml(IAppBuilder app, string modulePath, string audience, string issuer, string metadataUrl)
{
var saml2options = new Saml2AuthenticationOptions(false);
var spOptions = new SPOptions
{
EntityId = new EntityId(audience),
ModulePath = modulePath,
PublicOrigin = new Uri("https://localhost:44340/"),
};
spOptions.Logger = new ConsoleLoggerAdapter();
saml2options.SPOptions = spOptions;
saml2options.IdentityProviders.Add(new IdentityProvider(new EntityId(issuer), spOptions)
{
AllowUnsolicitedAuthnResponse = true,
MetadataLocation = metadataUrl,
LoadMetadata = true,
Binding = Saml2BindingType.HttpPost,
});
app.UseSaml2Authentication(saml2options);
}
}
}
针对单个IDP进行身份验证是这样的:
authProperties.Dictionary["idp"] = "https://sts.windows.net/xxx/";
authProperties.RedirectUri = "https://localhost:44340/client/azuread/ExternalLoginCallback";
HttpContext.Current.Request.GetOwinContext().Authentication.Challenge(authProperties, "Saml2");
检查sustapesainsys.saml2库的代码时(尤其是 saml2authenticationhandler )。我发现条件没有考虑到 owinrequest.pathbase 因此,身份没有返回应用程序。
一个示例可以是(saml2authenticationhandler.invoke方法)。
options.spoptions.modulepath =/client/azuread/saml2
request.path =/saml2/acs
==>因此,条件内的代码未执行。
public override async Task<bool> InvokeAsync()
{
var Saml2Path = new PathString(Options.SPOptions.ModulePath);
if (Request.Path.StartsWithSegments(Saml2Path, out PathString remainingPath))
{
if (remainingPath == new PathString("/" + CommandFactory.AcsCommandName))
{
var ticket = (MultipleIdentityAuthenticationTicket)await AuthenticateAsync();
if (ticket.Identities.Any())
{
Context.Authentication.SignIn(ticket.Properties, ticket.Identities.ToArray());
// No need to redirect here. Command result is applied in AuthenticateCoreAsync.
}
else
{
Response.Redirect(ticket.Properties.RedirectUri);
}
return true;
}
有什么方法可以改变这种行为吗?例如SAML2OPTIONS。
I have multi tenant application where each tenant can use different IdP to authenticate. Below code correctly redirects to IdP but problem is to get back the response to ACS endpoint.
Key is the Configuration method which configures the paths and their authentication:
[assembly: OwinStartup(typeof(SSOSamlDemoASPNET.App_Start.Startup))]
namespace SSOSamlDemoASPNET.App_Start
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Map("/client/okta", (appx) =>
{
ConfigureAuthentication(appx, "/client/okta/Saml2", ...);
});
app.Map("/client/azuread", (appx) =>
{
ConfigureAuthentication(appx, "/client/azuread/Saml2", ...);
});
}
private static void ConfigureAuthentication(IAppBuilder app, string modulePath, string audience, string issuer, string metadataUrl)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
CookieName = "LoggedUser",
CookiePath = "/",
CookieManager = new SystemWebCookieManager(),
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
ConfigureSaml(app, modulePath, audience, issuer, metadataUrl);
}
private static void ConfigureSaml(IAppBuilder app, string modulePath, string audience, string issuer, string metadataUrl)
{
var saml2options = new Saml2AuthenticationOptions(false);
var spOptions = new SPOptions
{
EntityId = new EntityId(audience),
ModulePath = modulePath,
PublicOrigin = new Uri("https://localhost:44340/"),
};
spOptions.Logger = new ConsoleLoggerAdapter();
saml2options.SPOptions = spOptions;
saml2options.IdentityProviders.Add(new IdentityProvider(new EntityId(issuer), spOptions)
{
AllowUnsolicitedAuthnResponse = true,
MetadataLocation = metadataUrl,
LoadMetadata = true,
Binding = Saml2BindingType.HttpPost,
});
app.UseSaml2Authentication(saml2options);
}
}
}
Authenticating against individual IdP is done like this:
authProperties.Dictionary["idp"] = "https://sts.windows.net/xxx/";
authProperties.RedirectUri = "https://localhost:44340/client/azuread/ExternalLoginCallback";
HttpContext.Current.Request.GetOwinContext().Authentication.Challenge(authProperties, "Saml2");
When inspecting code of the Sustainsys.Saml2 library (especially Saml2AuthenticationHandler). I found the conditions do not take into account OwinRequest.PathBase and therefore the identity is not coming back to the application.
An example can be (Saml2AuthenticationHandler.Invoke method).
Options.SPOptions.ModulePath = /client/azuread/Saml2
Request.Path = /Saml2/Acs
==> therefore the code inside the condition is not executed.
public override async Task<bool> InvokeAsync()
{
var Saml2Path = new PathString(Options.SPOptions.ModulePath);
if (Request.Path.StartsWithSegments(Saml2Path, out PathString remainingPath))
{
if (remainingPath == new PathString("/" + CommandFactory.AcsCommandName))
{
var ticket = (MultipleIdentityAuthenticationTicket)await AuthenticateAsync();
if (ticket.Identities.Any())
{
Context.Authentication.SignIn(ticket.Properties, ticket.Identities.ToArray());
// No need to redirect here. Command result is applied in AuthenticateCoreAsync.
}
else
{
Response.Redirect(ticket.Properties.RedirectUri);
}
return true;
}
Is there any way to change this behavioral? e.g. saml2Options.Notifications to get this working?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
显然,这是一个错误/缺乏功能,但是OWIN模块上没有什么可以固定的 - 它在生命支持上。
多租赁OWIN应用程序的解决方案是注册一个SAML2中间件,并向该备件添加多个IdentityProviders。中间软件将处理同一端点上的所有响应,并根据响应的来自位置使用正确的身份验证者的配置。
That is obviously a bug/lack of feature, but nothing that will be fixed on the Owin module - it's on life support.
The solution for a multi tenancy owin app is to register one Saml2 middleware and add multiple IdentityProviders to that one. The middleware will handle all responses on the same endpoint and use the configuration from the right IdentityProvider based on where the response came from.