构造一个签名的 SAML2 注销请求 [英] Construct a signed SAML2 LogOut request
问题描述
我的目标是实现单点注销协议.首先,我了解标准的工作原理以及如何将其适应我的场景:ADFS 2.0 作为 IdP,对我来说就像一个黑匣子"
我现在正在做的是下一个:
向我的 IdP 发送
IdP 要求我提供凭据,我提供凭据并成功登录.
从 中获取 SessionIndex 值并构造一个
<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_135ad2fd-b275-4428-b5d6-3ac3361c3a7f" Version="2.0" Destination="https://idphost/adfs/ls/" IssueInstant="2008-06-03T12:59:57Z"><saml:颁发者>myhost</saml:Issuer><NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" NameQualifier="https://idphost/adfs/ls/">myemail@mydomain.com</NameID<samlp:SessionIndex>_0628125f-7f95-42cc-ad8e-fde86ae90bbe</samlp:SessionIndex></samlp:LogoutRequest>
采用上面的
并用Base64 编码构造下一个字符串:
SAMLRequest=base64encodedRequest&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1
用上面的字符串生成签名
以 base64 编码签名
发送请求:
https://"https://idphost/adfs/ls/?SAMLRequest=base64encodedRequest&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1&Signature=base64EncodedSignature
但是 IdP 正在回答我:SAML 消息签名的验证失败.
为了签名,我使用我的私钥(2048 字节),并且为了验证它,假设 IdP 使用我的公钥(我在注册我的主机时发送的那个)
签署请求的代码如下所示:
//检索私钥KeyStore keyStore = KeyStore.getInstance("JKS", "SUN");FileInputStream 流;stream = new FileInputStream("/path/to/my/keystore.jks");keyStore.load(stream, "storepass".toCharArray());PrivateKey key = (PrivateKey) keyStore.getKey("keyAlias","keyPass".toCharArray());//创建签名签名签名 = Signature.getInstance("SHA1withRSA");签名.initSign(key);signature.update(SAMLRequest = jVJda8IwFH2e4H8ofW%2BbVmvboGWCDApusDn2sBdJm1sNtEmXmw7x1y92KDrY2Ov5uueEzJG1TUfXaqd68wIfPaBxDm0jkQ7Mwu21pIqhQCpZC0hNRTfLxzWNfEI7rYyqVONeWf52METQRijpOsVq4W7JoSzjJJnWAEAmwLMMpmRG0jCrYJICIcR13kCjdSxcG%2BA6K9tQSGYGZG9MhzQIGrUT0uPw6VegpV%2FtA8ZrDBq0ZxB7KCQaJo2NICT1yMwjk9cwonFG4%2BTdzceju%2FmpOx3EOu8qYThgGJ3j5sE1fZE%2F2X3FynlQumXm9%2BGhHw6I4F49SCm0TDRLzjWgrXiKee5ZI2oB%2BJ%2Bj8qYX6GvFtdj1cPRryzPJ4Xh%2F2%2Fe736VvRzf2nn24wmoP%2BZbMojSM4tpL6iz2plFVeYyn4NUc0hmDjJQlfCf9cI5HZ%2Fjm4%2BRf&安培;的RelayState = NULL&安培; SigAlg = HTTP%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1".getBytes());String signatureBase64encodedString = (new BASE64Encoder()).encodeBuffer(signature.sign());
我终于找到了正确的配方:
- 生成 SAMLRequest 值
- 以 Base64 编码 SAMLRequest 值
- 对 SAMLRequest 值进行 URL 编码
- 对 SigAlg 值进行 URL 编码:http://www.w3.org/2000/09/xmldsig#rsa-sha1
- 将算法签名 (SHA1withRSA) 与SAMLRequest=value&SigAlg=value
- 对生成的签名进行 URL 编码
我们可以使用 SAML 2.0 Debugger 执行第 2 步和第 3 步(https://rnd.feide.no/simplesaml/module.php/saml2debug/debug.php).而对于URL 编码使用经典的 w3schools(http://www.w3schools.com/tags/ref_urlencode.asp)>
警告!确保 ADFS2 中您的信赖方的算法设置为 SHA1!
最好的问候,
路易斯
ps:现在我必须写一点代码......
pps:你可以在这里找到代码:https://github.com/cerndb/wls-cern-sso/tree/master/saml2slo
My aim is to implement the Single Log Out Protocol. First I am understanding how the standar works and how I can fit it in my scenario: ADFS 2.0 as IdP, for me is like a "black box"
What I am doing at the moment is the next:
Send an
<AuthnRequest>
to my IdPIdP asks me for credentials, I provide them and get succesfully login.
Get the SessionIndex value form the and constructs a
<LogoutRequest>
<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_135ad2fd-b275-4428-b5d6-3ac3361c3a7f" Version="2.0" Destination="https://idphost/adfs/ls/" IssueInstant="2008-06-03T12:59:57Z"><saml:Issuer>myhost</saml:Issuer><NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" NameQualifier="https://idphost/adfs/ls/">myemail@mydomain.com</NameID<samlp:SessionIndex>_0628125f-7f95-42cc-ad8e-fde86ae90bbe</samlp:SessionIndex></samlp:LogoutRequest>
Take the above
<LogoutRequest>
and encode it in Base64Contructs the next string:
SAMLRequest=base64encodedRequest&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1
With the above string generates the signature
Encode the signature in base64
Send the request:
https://"https://idphost/adfs/ls/?SAMLRequest=base64encodedRequest&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1&Signature=base64EncodedSignature
But the IdP is answering me: The verification of the SAML message signature failed.
For signing I am using my private key (2048 bytes), and for verifying it is supposed that the IdP is using my public key (the one that I sent it when I registered my host)
The code for signing the request looks like:
// Retrieve the private key
KeyStore keyStore = KeyStore.getInstance("JKS", "SUN");
FileInputStream stream;
stream = new FileInputStream("/path/to/my/keystore.jks");
keyStore.load(stream, "storepass".toCharArray());
PrivateKey key = (PrivateKey) keyStore.getKey("keyAlias","keyPass".toCharArray());
// Create the signature
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(key);
signature.update("SAMLRequest=jVJda8IwFH2e4H8ofW%2BbVmvboGWCDApusDn2sBdJm1sNtEmXmw7x1y92KDrY2Ov5uueEzJG1TUfXaqd68wIfPaBxDm0jkQ7Mwu21pIqhQCpZC0hNRTfLxzWNfEI7rYyqVONeWf52METQRijpOsVq4W7JoSzjJJnWAEAmwLMMpmRG0jCrYJICIcR13kCjdSxcG%2BA6K9tQSGYGZG9MhzQIGrUT0uPw6VegpV%2FtA8ZrDBq0ZxB7KCQaJo2NICT1yMwjk9cwonFG4%2BTdzceju%2FmpOx3EOu8qYThgGJ3j5sE1fZE%2F2X3FynlQumXm9%2BGhHw6I4F49SCm0TDRLzjWgrXiKee5ZI2oB%2Bj%2Bj8qYX6GvFtdj1cPRryzPJ4Xh%2F2%2Fe736VvRzf2nn24wmoP%2BZbMojSM4tpL6iz2plFVeYyn4NUc0hmDjJQlfCf9cI5HZ%2Fjm4%2BRf&RelayState=null&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1".getBytes());
String signatureBase64encodedString = (new BASE64Encoder()).encodeBuffer(signature.sign());
Finally I got the right recipe:
- Generate the SAMLRequest value
- Encode the SAMLRequest value in Base64
- URL-encode the SAMLRequest value
- URL-encode the SigAlg value: http://www.w3.org/2000/09/xmldsig#rsa-sha1
- Feed the algorithm signature (SHA1withRSA) with the SAMLRequest=value&SigAlg=value
- URL-encode the generated signature
We can perform the steps 2 and 3 with the SAML 2.0 Debugger (https://rnd.feide.no/simplesaml/module.php/saml2debug/debug.php). And for the URL-encoding use the classic w3schools (http://www.w3schools.com/tags/ref_urlencode.asp)
Warning! Ensure that the algorithm for your relying party, in the ADFS2, is setup to SHA1!
Best regards,
Luis
ps: now I have to code a little bit...
pps: You can find the code here: https://github.com/cerndb/wls-cern-sso/tree/master/saml2slo
这篇关于构造一个签名的 SAML2 注销请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!