SAML IDP 发起的 SSO 事务
Posted
技术标签:
【中文标题】SAML IDP 发起的 SSO 事务【英文标题】:SAML IDP initiated SSO transaction 【发布时间】:2022-01-23 23:00:13 【问题描述】:Webapp #1 有一个指向 webapp #2 的按钮。当我们的用户单击该按钮时,他们应该被重定向到 webapp #2,并自动登录。
集成是 SAML,因此 webapp #1(IDP)向 webapp #2(SP)发送一个 SAML“请求”,它返回一个重定向 URL,webapp #1 重定向到它。
SP 给了我一个指向 HTTP POST 的 URL,一个通过“email”属性识别用户的断言,所以我制作了这个:
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" IssueInstant="2021-12-22T16:59:43.999Z" Version="2.0"><saml2:Issuer>http://www.whatever.com</saml2:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod><ds:Reference URI=""><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform><ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod><ds:DigestValue>...</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>...</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>...</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml2:Conditions><saml2:OneTimeUse></saml2:OneTimeUse></saml2:Conditions><saml2:AuthnStatement AuthnInstant="2021-12-22T16:59:44.053Z" SessionIndex="cfb8f9b5-9616-47db-bc92-7588ce18cf62" SessionNotOnOrAfter="2021-12-22T16:59:44.068Z"><saml2:AuthnContext></saml2:AuthnContext></saml2:AuthnStatement><saml2:AttributeStatement><saml2:Attribute Name="email"><saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">si@captisintel.com</saml2:AttributeValue></saml2:Attribute></saml2:AttributeStatement></saml2:Assertion>
SP 以 302 和如下所示的 Location 标头响应:
Location: ?SAMLRequest=nVNNj9owEP0rke%2FkS4VtLc...
解码:
<?xml version="1.0"?><samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_f848f04c71671a745722" Version="2.0" IssueInstant="2021-12-22T18:36:19.337Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="http://auth.whatever2.com/saml/callback" Destination=""><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">whatever2</saml:Issuer><samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"/><samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Comparison="exact"><saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></samlp:RequestedAuthnContext></samlp:AuthnRequest>
当我访问该 URL 时,我会看到登录页面。 所以这是行不通的。
我对 SP 日志的可见性为 0,以了解问题所在。我能猜到的是我没有正确发布这个。那么这看起来对吗,还是我应该以不同的方式发布?我尝试将断言按原样发布在正文中,将其包装在“ 另一个线索是 SP 总是返回 302,无论我发送什么。即使我发送“BLAHBLAH”而不是实际的 SAML 负载,它们仍然会以 302 响应。 有什么建议吗?
【问题讨论】:
【参考方案1】:在 IdP 发起的流程中,IdP 像您一样在 POST 中发送包含断言的 SAML 响应。如果一切顺利,SP 现在应该认为用户已通过身份验证。
SAML 响应应该在名为 SAMLResponse 的输入控件中发送,并且应该是 Base64 编码的。
<input type="hidden" name="SAMLResponse" value="<Base64 encoded SAML Response>"/>
我猜想会发生什么,由于某种原因,SP 不接受您的 SAMLResponse,而是通过向 IdP 发送 SAML 请求以对用户进行身份验证来启动正常的 SP 发起的 SAML 流。
您的回复不被接受的原因可能有很多。如果没有 SP 日志,我们几乎可以猜测。
我看到你的断言缺少一个强制的不记名主题确认。
来自SAML Profiles spec4.1.4.2
使用此配置文件为消费而发出的任何断言都必须包含一个带有 at 的元素 至少一个包含方法的元素 瓮:绿洲:名称:tc:SAML:2.0:cm:承载者。这种断言称为不记名断言。 Bearer assertions 可以包含额外的元素。 同一章节对断言也有更多要求
不过还有一些其他的想法:
您应该在 SAML 响应中包含您的断言,但是需要设置几个样板元素。所以确保它是有效的 经常看到响应消息本身必须签名,而不仅仅是断言。我建议查看 SAML 配置文件规范 4.1.4.2 以了解断言和响应必须包含的内容。
另外,请尝试 agian 看看您是否可以从 SP 那里获得任何关于错误的反馈,以避免盲目尝试和失败而使您头疼。
SAML 并不是目前最直接的协议,要使其正常工作并确保其安全,还有很多工作要做。正如我总是试图对刚开始使用它的人说的那样:不要自己构建它,有很多很好的开源替代方案可以用于执行 SAML,这将使您的系统更加安全和可维护。
如果您想更好地了解 SAML 以及如何实现它,我可以推荐我的书,SAML 2.0: Designing secure identity federation
祝你好运!
【讨论】:
非常非常有用——感谢您的回答和本书!你能推荐一个可以做到这一切的Java库吗?到目前为止,我在我的 POC 中使用了 opensaml 和 onelogin,它们看起来不错,但我没有看到任何关于 Bearer 业务的明显内容...... 我不建议将 OpenSAML 用于标准集成,因为 OpenSAML 适合定制的东西。因为那是更好的去追求更高的水平。我认为 onelogin 工具包会很好地完成这项工作。我在这里也有关于带有 saml 支持的 spring 安全性的好东西。 关于承载,这是我的一个旧博客,显示了一个有效的断言。 blog.samlsecurity.com/2015/07/what-is-saml-assertion.html。您可以看到主题元素包含带有方法承载的主题确认。这是强制性的,并且可能是您的断言不被接受的原因之一。如果您认为这回答了您的问题,请将其标记为正确。 我添加了 Bearer,但没有成功。我接受了这个答案,因为它对找到解决方案最有帮助。如果您(或您推荐的任何人)愿意亲自尝试(您想要的任何客户端技术),请 LMK,即使我们从 SP 获得的帮助为零。我的电子邮件:我在 gmail dot com 的用户名。否则感谢您的帮助! 好的,是的,这只是可能出错的一件事。我现在很难按时完成项目,但正如我在书中提到的那样,开始与samltest.id 进行简单的集成,以查看您从 SP 中获得的东西。我看到我之前把事情搞混了。 Spring SAML 和 onelogin 工具包仅用于设置 SP 而不是 IdP。我对 IdP 的工具包不确定。我会看看,但也许尝试发布一个新问题【参考方案2】:您应该向 SP 发送包含 SAML 断言的 SAML 响应,而不仅仅是 SAML 断言。您还需要确保按照 SAML v2.0 绑定规范正确编码。
您确实需要 SP 来协助调试。希望他们的日志能够详细说明他们拒绝您的 HTTP Post 的原因。
【讨论】:
以上是关于SAML IDP 发起的 SSO 事务的主要内容,如果未能解决你的问题,请参考以下文章
Spring security SAML IDP 发起的 SSO