SP-Initiated SLO 生成多个 SLO 请求

SP-Initiated SLO Generating multiple SLO requests

我正在使用 sustainsys saml2 owin 包,但我在 SP 启动的 SLO 方面遇到了问题。我是 saml 流程的新手,所以很有可能我做错了什么。

我们的注销工作流程如下:

  1. 用户点击我的应用。com/signout
  2. myapp 重定向到 myapp。com/saml2/logout
  3. owin包生成saml请求发送到Idp的slo路由
  4. Idp 以成功的 saml 响应响应相同的 url: myapp.com/saml2/logout
  5. 此时,owin 包正在生成另一个 saml 请求以将用户从 idp 中注销。如果 Idp 没有停止进程,它将陷入无限重定向。

这是我在 chrome 中的网络面板的快照:

我正在使用 https://github.com/mcguinness/saml-idp 作为开发 Idp,这是我的 owin 配置的存根:

我怀疑我配置错误或者我不恰当地使用了 saml2/logout 路由,但我也发现 owin 包在获得成功响应时会生成另一个请求很奇怪。

2018 年 9 月 11 日更新

这是我从注销过程开始的详细日志:

Expanded Saml2Url
  AssertionConsumerServiceUrl: http://locala.foliotek.com/saml2/linuxdev/Acs
  SignInUrl: http://locala.foliotek.com/saml2/linuxdev/SignIn
  LogoutUrl: http://locala.foliotek.com/saml2/linuxdev/Logout
  ApplicationUrl: http://locala.foliotek.com/
=================
Initiating logout, checking requirements for federated logout
  Issuer of LogoutNameIdentifier claim (should be Idp entity id): http://myidentityprovider.com
  Issuer is a known Idp: True
  Session index claim (should have a value): http://Sustainsys.se/Saml2/SessionIndex: 1926000282
  Idp has SingleLogoutServiceUrl: http://myidentityprovider.com/saml/slo
  There is a signingCertificate in SPOptions: True
  Idp configured to DisableOutboundLogoutRequests (should be false): False
=================
Expanded Saml2Url
  AssertionConsumerServiceUrl: http://myserviceprovider.com/saml2/linuxdev/Acs
  SignInUrl: http://myserviceprovider.com/saml2/linuxdev/SignIn
  LogoutUrl: http://myserviceprovider.com/saml2/linuxdev/Logout
  ApplicationUrl: http://myserviceprovider.com/
=================
Initiating logout, checking requirements for federated logout
  Issuer of LogoutNameIdentifier claim (should be Idp entity id): http://myidentityprovider.com
  Issuer is a known Idp: True
  Session index claim (should have a value): http://Sustainsys.se/Saml2/SessionIndex: 1926000282
  Idp has SingleLogoutServiceUrl: http://myidentityprovider.com/saml/slo
  There is a signingCertificate in SPOptions: True
  Idp configured to DisableOutboundLogoutRequests (should be false): False
=================
Expanded Saml2Url
  AssertionConsumerServiceUrl: http://myserviceprovider.com/saml2/samltestid/Acs
  SignInUrl: http://myserviceprovider.com/saml2/samltestid/SignIn
  LogoutUrl: http://myserviceprovider.com/saml2/samltestid/Logout
  ApplicationUrl: http://myserviceprovider.com/
=================
Initiating logout, checking requirements for federated logout
  Issuer of LogoutNameIdentifier claim (should be Idp entity id): http://myidentityprovider.com
  Issuer is a known Idp: False
  Session index claim (should have a value): http://Sustainsys.se/Saml2/SessionIndex: 1926000282
  Idp has SingleLogoutServiceUrl: 
  There is a signingCertificate in SPOptions: True
  Idp configured to DisableOutboundLogoutRequests (should be false): 
=================
Expanded Saml2Url
  AssertionConsumerServiceUrl: http://myserviceprovider.com/saml2/linuxdev/Acs
  SignInUrl: http://myserviceprovider.com/saml2/linuxdev/SignIn
  LogoutUrl: http://myserviceprovider.com/saml2/linuxdev/Logout
  ApplicationUrl: http://myserviceprovider.com/
=================
Http POST binding extracted message
<samlp:LogoutResponse xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_d02d42fbb8ed00bbee02" InResponseTo="idf75b17a7713e4f698f891edf1fcca117" Version="2.0" IssueInstant="2018-11-09T16:44:01Z" Destination="http://myserviceprovider.com/saml2/linuxdev/logout"><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://myidentityprovider.com</saml:Issuer><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI="#_d02d42fbb8ed00bbee02"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>X+93fiv6vuuy8sIhmFFxIVxNgAy/f1Zk62RRh/rn91I=</DigestValue></Reference></SignedInfo><SignatureValue>qXMlLe2fciQR6u7Ddx40RFI51IJ5r8A3m7X7mrgIMHBdFf2vypiCFxqOrEOKCSIqWzDUxVXujWyMQzO/zZtVyZlm6xXnb3lId0VDHLEIUT/8kyNsodzvzPIyTMaMMV/cmhQ3UZlYRv9BeyPswpkosFTn/xc6c+BX9z+w4AN4KDMFfYlTeu/uyDBa1u5zr/Ze6OXwP7///Mo/zdy2ZXyHJhia+yscWZ+Hrb49ekI9csJvuic0p6ttJPjS72tmEesGR1vLT0Y/5T+SqOVmmbmN8hZygRxrEwgfo9oNI+8BBC7aYK2PCtTZZFwoO3KsEEttQjxzKTbzja9s8XslGxfKkw==</SignatureValue><KeyInfo><X509Data><X509Certificate>MIIDgzCCAmugAwIBAgIJALOc35pt94LuMA0GCSqGSIb3DQEBCwUAMFgxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNaXNzb3VyaTERMA8GA1UEBwwIQ29sdW1iaWExFTATBgNVBAoMDEZvbGlvdGVrIEluYzEMMAoGA1UEAwwDSWRwMB4XDTE4MTEwOTE1MDI0MVoXDTM4MTEwNDE1MDI0MVowWDELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE1pc3NvdXJpMREwDwYDVQQHDAhDb2x1bWJpYTEVMBMGA1UECgwMRm9saW90ZWsgSW5jMQwwCgYDVQQDDANJZHAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhX8PX+C/1orPpFnOIRy7UkrLU7YCq6DNzB5QSUzT366++ZCWFzx+Ub+HFxbR/htY/EAramlCNFawOSGS6mnWev/tiokGObXdMK6tAXyZZMc/u9Rg65EjM892Oep6gIEWgjnE+l7M8v84QOWqAl+GaeM8YZJKHXAZ+7MVMgkMWeYKrksvQdKrQjhyzqoLmBNL5yGBgEH1KEtFy0A0qYdiwdWptvaeWkTk6tp3kfminRaQ1bj/BmMwAWeDbE7EFkk7wF1ig4QhTINoVFQhPGa/+sPg+NuDNlGszDBV3fmfpHwPpjRr4zzoNyJnMvf3u1+C63c7DPSC+uKGvYlgeWbc/AgMBAAGjUDBOMB0GA1UdDgQWBBQvczxcOnaazyGJ8H3vi1vY6g24xDAfBgNVHSMEGDAWgBQvczxcOnaazyGJ8H3vi1vY6g24xDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAoMsoDnrEPCS+VIqVlnlbxxd4lx5AYMvUTZPugJ88+Jjp/1kkKbxWzbJBR1yl0v9quLoQ/u5XkYoSI3u/azydywpADlgsKHrL7Ger+ZU2pdSCK9LTbOP3gnginmPldB7LW6jxWxuEYadWLpYocEFU6Ua7XJUDOzMpO3SXxmhiyhvQC2PF0Q1uehNkwIpUP+9I9ulAXxjScyputgYjkWjiLYu+gcWYW6DmeWqJKyYR6XSwaa+QV4/UPupBmSc1Bx7BuF29+1RwJyTEI6Uz5wQe+lbzZ5ay3J3oa3lilwYg/HYq4mQzVucHEhQLsU9ZIfuGStMHX23sdzWuEBbcQgCCd</X509Certificate></X509Data></KeyInfo></Signature><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /></samlp:Status></samlp:LogoutResponse>
=================

这是我在注销过程中的信息日志

Sending logout request to http://myidentityprovider.com
=================
Sending logout request to http://myidentityprovider.com
=================
Federated logout not possible, redirecting to post-logout and clearing local session
=================
Received logout response Microsoft.IdentityModel.Tokens.Saml2.Saml2Id, redirecting to http://myidentityprovider.com/saml/slo?SAMLRequest=fZJdS8MwFIbvB%2FsPJbeyNv3Y1oatOBhCYXrhxAvvYpKu0XzUnlT2803rJpugkJvz8bznPYesgGqVtGRnD7Z3j%2BKjF%2BCCo1YGyHdpjfrOEEtBAjFUCyCOkf3mfkeSEJO2s84yq9Al8z9CAUTnpDUoqLZrJHmRFuw1LnKcUpYt2JImC1rXOc94yuZpnaHgWXTggTXyvKcAelEZcNQ4n8JxPovjGS6e4gXJUjLPX1Cw9WtIQ91INc61JIpqq6R%2Fpj9y8RmOkRPvIbOaLPESR4P3CJRF5XQSBKtxFTIO68qThLKMKnrFjlgSnXVX0RV3ofTgL1Ftgzvbaer%2BPlEcxmNG8lk9thKhqVQbzjsBgErXCN4Py4GWrrlxjdUU3m4PQ9Pg52zge9yFgZbsvYA%2FSGW4OJZxkSwwxkmenIhf9enkJ3%2F1Ocov&RelayState=MnZ2DPYtc9cY8CkEaR5CRJDz&SigAlg=http:%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=LS0QmYpXX2utWqmEKQJmMeQukm%2FFFVUZCP8I0C7sIt1LklVK0NzuqrJgG9VGwO6uPBZObpZ%2FU9%2BZVddCoIGmg3FCKrhhW7hspsQNN%2FGqpf0QY3kxW%2Bt956TqgynW0yM4I9%2Fc7X%2F9Sy4keFu1uxihjemm%2BCNlZdRS71ch4SyG4YStmKZrWJns1T6H4m8d2eBK7O2KVn9iqwIh6OaV5S6obhpMH9gzx5Y01uc5fTm2gfdoExuVNsKbZB8ycois1MEEz7Uox5zRm09gEfCNMHKf2Dp%2Fwd7GmQoK84VvPoNrxl5047WxfKxkhQPTRFbM5h50peFjOlnFN0yKw9C3DARSBw%3D%3D
=================

深入研究代码后,我发现如果我执行以下操作:

GetLogoutResponseState = (req) => { return null; }

...在我的 Saml2AuthenticationOptions.Notifications 中,它按预期工作。

从这里,我仍然怀疑我配置有问题,或者IDP发送了错误的数据,但我不知道StoredRequestState在哪里被初始化。它似乎包含错误的 returnUrl。

查看日志,我认为这是事件的顺序。

  1. 您的应用程序上的 SignOut 被命中并重定向到 Saml2 库中的注销端点。
  2. 注销端点被命中并向 Idp 发起注销请求。
  3. Idp 呈现页面(可能包含某种 SAML 响应 - 但可能不正确)。
  4. 再次点击注销端点,这是错误的
    • 这是一个重复的请求。
    • 或者是 Sustainsys.Saml2 库未正确检测到的响应

真正让我感到困惑的是,在第二个 运行 中,联合注销的所有要求都已满足。具体来说,它确实找到了 LogoutNameIdentifier。这应该是不可能的,因为本地会话 cookie 通常在重定向到 Idp 完成后被清除。

为了进一步了解发生了什么,我建议您直接下载 Sustainsy.Saml2 源 link 到项目并在 LogoutCommand.Run 处设置断点。这应该可以帮助您更好地理解并能够进一步检查请求。

我将我的问题追溯到 LogoutCommand.Run 在对 /saml2/logout 的初始 GET 请求期间被调用了两次。一次来自 Saml2AuthenticationHandler .ApplyResponseGrantAsync 方法,一次来自 Saml2AuthenticationHandler.InvokeAsync.

解决方案 是在我的 SPOptions 中设置 Compatibility = new Compatibility { StrictOwinAuthenticationMode = true }。这会阻止 LogoutCommand 在 ApplyResponseGrantAsync 方法中执行。

我不太清楚被动和主动身份验证模式,但我猜我是在向 Sustainsys 包指示我正在手动控制身份验证(包括注销)。也许安德斯可以解决这个问题?