如何在针对AzureAD的.net 4.5中实现SAML2身份验证? (使用代币)

时间:2016-02-13 00:42:29

标签: c# .net wif saml-2.0

我想允许对我的网络应用进行SAML身份验证,包括针对AzureAD作为身份提供商以及ADFS。 (任何人都可以向我指出一个很好的教程或演练吗?)我已经生成了SAML请求,从AzureAD获取SAMLP响应,并验证其签名(包括事实SHA256默认情况下不起作用)。

现在,我想从中提取信息以验证发卡行,并获取用户的电子邮件以识别它们。通过XML手动执行此操作是否“可以”,还是应该使用Saml2SecurityTokenHandler之类的类?他们看起来应该这样做,但我发现很难理解所需的所有配置,以及从安全角度来看是否有必要使用这些类。

我的应用是多租户,因此我需要代码而不是配置来处理Saml,因为不同的租户将使用不同的身份验证选项。

This blog表示不使用ConfigurationBasedIssuerNameRegistry而是指向[ValidatingIssuerNameRegistry][3]。好的,这似乎适合我的场景。

this question中有一些代码以编程方式配置受信任的颁发者,因此我可以调整为使用ValidatingIssuerNameRegistry,然后我可以使用tokenHandlers从SAMLP响应中读取Assertion,然后提取声明包括姓名(电子邮件)。但是我在哪里可以获得指纹&从AzureAD元数据传递给它的名称?确切地说,使用这些类而不是自己解析响应的价值是什么?这绝对感觉就像使用图书馆这样做是正确的,但WIF的复杂性以及缺乏关于这样做的漫画文章使得它感觉不适合那些在身份世界深处的人。

我的猜测是,如果我已在本地存储证书以验证SAML响应的颁发者的身份,并且我在XML中验证签名,那么我可以愉快地使用SAML响应的内容。即用户的身份。尽管如此,手动执行此操作仍然是错误的方法,但如果没有明显的缺点,我也可以。

一些相关的SO问题&文章:

1 个答案:

答案 0 :(得分:6)

正如您已经发现的那样 - 即使支持SAML2令牌,.NET中也没有针对SAML2协议的内置支持。

我建议您不要自己动手,而是建议您查看SAML2P for ASP.NET的可用开源和商业库。除了在.NET框架中提供的服务之外,还有很多工作要建立可靠的服务提供商。 (我知道,因为我已经建立了一个,如果我知道我现在所知道的,我不会认为我再做一次)。

如果您选择继续自己,Saml2SecurityTokenHandler包含从XML读取断言的重要工具,将它们转换为声明身份并验证断言上的签名。请注意,处理程序希望对断言进行签名 - AFAIK没有内置支持来处理签署整个SAML响应的情况(也包括嵌入的断言)。

使用Kentor.AuthServices

此处描述的方案是直接使用Kentor.AuthServices API,这是一种不建议作为首选的高级方案。对于Web API和现代MVC应用程序,使用Kentor.AuthServices.Owin包中的Owin中间件要好得多。

此处的代码使用Kentor.AuthServices.HttpModule包中的API。

配置

要直接使用AuthServices API,首先必须创建配置,如docs中所述。可以在代码和web.config中同时执行这两项操作。对于此示例,我只是引用Options属性IOptions实例。它可以通过Options.FromConfiguration属性从web.config加载。

发送AuthnRequest

身份验证的第一步是发送AuthnRequest。 dummyUrl只是任何非null的Uri对象。它不会在这种情况下使用,但不允许为空。

var idp = Options.IdentityProviders.Default;
var urls = new AuthServicesUrls(fullUrlOfYourAcsService, dummyUrl, applicationUrl);

var authnRequest = idp.CreateAuthenticateRequest(dummyUrl, urls);

// Apply will call Response.End
idp.Bind(authnRequest).Apply(new HttpResponseWrapper(HttpContext.Current.Response));

即使OP已经成功完成了这项工作,也必须通过AuthServices来正确注册待处理的请求,然后将其与返回的响应进行匹配。

收到回复

下一步是接收返回的SAML2Response。此代码应位于" fullUrlOfYourAcsService"发送AuthnRequest时指定的位置。

var result = CommandFactory.GetCommand(CommandFactory.AcsCommandName)
  .Run(new HttpRequestWrapper(HttpContext.Current.Response), Options);

// result.Principal will now contain the received identity.