SAML2 digital token request in NodeJS
I have the following SAML request that I want to digitally sign:
<samlp:AuthnRequest Version="2.0" ID="_9FE393FB-1C9C-4EDD-86A5-1AE9F2192A60" IssueInstant="2014-10-22T11:22:56.676Z" Destination="https://idp.ssocircle.com:443/sso/SSOPOST/metaAlias/ssocircle" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Issuer>http://app.localhost</saml:Issuer>
<samlp:NameIDPolicy AllowCreate="true" />
</samlp:AuthnRequest>
I am using the following coffeescript code which relies on nodejs xmlbuilder and xmlcrypto :
request = @xmlbuilder.create
'samlp:AuthnRequest':
'@xmlns:samlp':'urn:oasis:names:tc:SAML:2.0:protocol'
'@xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion'
'@Version': '2.0'
'@ID': requestId
'@IssueInstant': (new Date()).toISOString()
'@Destination': idpUrl
'saml:Issuer': '@@spEntityId'
,null
,headless: true
request.comment 'insert-signature-here'
request.element 'samlp:NameIDPolicy':
'@AllowCreate': 'true'
saml = request.end()
@fs.readFile "certs/my-cert.pem", (err, certificate)=>
return next @errorService.readFileError certFilePath, err if err?
signer = new @xmlcrypto.SignedXml()
signer.signingKey = certificate
signer.addReference "//*[local-name(.)='AuthnRequest']", ['http://www.w3.org/2000/09/xmldsig#enveloped-signature']
signer.keyInfoProvider = new =>
getKeyInfo: (key)=>
public_key = /-----BEGIN CERTIFICATE-----([^-]*)-----END CERTIFICATE-----/g.exec(key)[1].replace /[\r\n|\n]/g, ''
"<X509Data><X509Certificate>#{public_key}</X509Certificate></X509Data>"
signer.computeSignature saml
signature = signer.getSignatureXml()
signed = saml.replace '<!-- insert-signature-here -->', signature
console.log signed
Which generates the following digitally signed SAML request:
<samlp:AuthnRequest Version="2.0" ID="_5FEB2162-F4D0-4900-BC28-F2940188E45B" IssueInstant="2014-10-28T13:07:14.007Z" Destination="https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Issuer>http://app.localhost9de83841</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/2000/09/xmldsig#rsa-sha1" />
<Reference URI="#_5FEB2162-F4D0-4900-BC28-F2940188E45B">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>47MSlH9IpJf8vs37T3DnhZMZ7mo=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>T0Uw...KZkm00A==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIDg...OgMMxZ</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<samlp:NameIDPolicy AllowCreate="true" />
</samlp:AuthnRequest>
This appears to be valid.
However, when I test this with SSOCircle and TestShib they both report that the digest value does not match.
The certificate I'm using is a self-signed certificate (pem) with an unencrypted private key.
I double checked to make sure that the public key provided in sp-metadata was taken from the same pem file used to digitally sign SAML.
Do I need to encrypt the private key?
If not, can you guess why the signature verification should fail?
Thank.
source to share
The private key must not be encrypted. You can use this online tool https://www.samltool.com/validate_logout_req.php to validate your signature. If it does not pass, then your signature was created in the wrong way.
source to share