我最近开始关注新的ASP.Net Identity框架和Katana中间件,那里有大量的代码和文档,但我看到的似乎是很多相互矛盾的信息,我猜这是因为代码更新频率越来越高。
我希望对内部ADFS 2服务使用WsFederation身份验证,但是OWIN身份验证管道的工作方式让我有些困惑,我希望有人可以提供一些权威性信息。
具体来说,我对中间件应该连接的顺序以及在各种场景中需要哪些模块感兴趣,我想摆脱任何不需要的东西。在那里,同时确保过程尽可能安全。
例如,似乎UseWsFederationAuthentication
应该与UseCookieAuthentication
一起使用,但我不确定正确的AuthenticationType
是什么({{3} } post表明它只是一个标识符字符串,但它的值是否显着?)或者即使我们仍然需要使用SetDefaultSignInAsAuthenticationType
。
我还注意到Katana项目讨论板上的this帖子,Tratcher在那里提到了一个常见错误,但对于哪部分代码出错是不是非常具体。
就个人而言,我现在正在使用以下内容(使用自定义SAML令牌处理程序将令牌字符串读入有效的XML文档),它对我有用,但它是否最佳?
var appURI = ConfigurationManager.AppSettings["app:URI"];
var fedPassiveTokenEndpoint = ConfigurationManager.AppSettings["wsFederation:PassiveTokenEndpoint"];
var fedIssuerURI = ConfigurationManager.AppSettings["wsFederation:IssuerURI"];
var fedCertificateThumbprint = ConfigurationManager.AppSettings["wsFederation:CertificateThumbprint"];
var audienceRestriction = new AudienceRestriction(AudienceUriMode.Always);
audienceRestriction.AllowedAudienceUris.Add(new Uri(appURI));
var issuerRegistry = new ConfigurationBasedIssuerNameRegistry();
issuerRegistry.AddTrustedIssuer(fedCertificateThumbprint, fedIssuerURI);
app.UseCookieAuthentication(
new CookieAuthenticationOptions
{
AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType // "Federation"
}
);
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = appURI,
SignOutWreply = appURI,
Configuration = new WsFederationConfiguration
{
TokenEndpoint = fedPassiveTokenEndpoint
},
TokenValidationParameters = new TokenValidationParameters
{
AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
},
SecurityTokenHandlers = new SecurityTokenHandlerCollection
{
new SamlSecurityTokenHandlerEx
{
CertificateValidator = X509CertificateValidator.None,
Configuration = new SecurityTokenHandlerConfiguration
{
AudienceRestriction = audienceRestriction,
IssuerNameRegistry = issuerRegistry
}
}
}
}
);
非常感谢您提供的任何帮助,以帮助我解决这个困惑。
答案 0 :(得分:49)
正如@Tratcher所说,AuthenticationType
参数被Microsoft.Owin.Security
用作查找身份验证中间件实例的密钥。
下面的代码将使用以下简单的帮助程序方法来要求验证所有请求。在实践中,您更有可能在敏感控制器上使用[Authorize]
属性,但我想要一个不依赖于任何框架的示例:
private static void AuthenticateAllRequests(IAppBuilder app, params string[] authenticationTypes)
{
app.Use((context, continuation) =>
{
if (context.Authentication.User != null &&
context.Authentication.User.Identity != null &&
context.Authentication.User.Identity.IsAuthenticated)
{
return continuation();
}
else
{
context.Authentication.Challenge(authenticationTypes);
return Task.Delay(0);
}
});
}
context.Authentication.Challenge(authenticationTypes)
调用将从每个提供的身份验证类型发出身份验证质询。我们只是提供我们的WS-Federation身份验证类型。
首先,这是"最佳"的一个例子。对于一个只使用WS-Federation的站点的Owin Startup配置,如下:
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
{
AuthenticationType = "WS-Fed Auth (Primary)",
Wtrealm = ConfigurationManager.AppSettings["app:URI"],
MetadataAddress = ConfigurationManager.AppSettings["wsFederation:MetadataEndpoint"]
});
AuthenticateAllRequests(app, "WS-Fed Auth (Primary)");
app.UseWelcomePage();
}
请注意使用"WS-Fed Auth (Primary)"
AuthenticationType
来唯一标识我们已配置的WS-Federation中间件实例。这意味着,如果您有这样的要求,您可以使用带有单独WS-Federation服务器的"WS-Fed Auth (Secondary)"
作为后备。
此配置将执行以下操作:
CookieAuthenticationDefaults
类上的常量字符串,它是CookieAuthenticationOptions.AuthenticationType
属性使用的默认值。)AuthenticationType
密钥。Microsoft.Owin.Security
方法向任何未经身份验证的请求发出质询) 所以有几种方法你可以在这里出错。
为了实验,我试着这样做,你马上就能看到问题所在:
public void Configuration(IAppBuilder app)
{
var x = app.GetDefaultSignInAsAuthenticationType();
app.SetDefaultSignInAsAuthenticationType(x);
}
第一次通话将为您提供您在第一条评论中提到的例外情况:
"在IAppBuilder属性中找不到SignInAsAuthenticationType的默认值。如果您的身份验证中间件以错误的顺序添加,或者如果缺少一个,则会发生这种情况。"
正确 - 因为默认情况下,Microsoft.Owin.Security
管道并未假设您将要使用的中间件(即,Microsoft.Owin.Security.Cookies
甚至不知道是现在),所以它不知道应该是什么默认值。
今天我花了很多时间,因为我真的不知道自己在做什么:
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType("WS-Fed AAD Auth");
// ... remainder of configuration
}
因此,在每次通话时,都会继续尝试使用WS-Federation 来验证呼叫者。这不是那种超级昂贵的,它和&# #97; WS-Federation中间件实际上会对每个请求发出挑战。所以你无法进入,并且你会看到很多登录URL都飞过你身边。 :P
因此,在管道中拥有所有这些灵活性的好处是你可以做一些非常酷的事情。例如,我有一个域内有两个不同的Web应用程序,在不同的子路径下运行,例如:example.com/foo
和example.com/bar
。您可以使用Owin的映射功能(如app.Map(...)
中所述)为每个应用程序设置完全不同的身份验证管道。在我的例子中,一个使用WS-Federation,而另一个使用客户端证书。试图在整体System.Web
框架中这样做会很可怕。 :P