authenticate using OAuth + SAML bearer flow (invalid assertion) - single-sign-on

I am trying to authenticate using OAuth + SAML bearer flow (http://help.salesforce.com/help/doc/en/remoteaccess_oauth_SAML_bearer_flow.htm)
But i am stuck at the point where i am getting invalid assertion error:
{"error":"invalid_grant","error_description":"invalid assertion"}
Here's my assertion:
<?xml version="1.0"?>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="C625490D-C2B9-15BE-6DFA-7286288D9655" IssueInstant="2012-04-04T06:54:14Z" Version="2.0">
<saml:Issuer>3MVG9Y6d_Btp4.....d0jnN</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#C625490D-C2B9-15BE-6DFA-7286288D9655">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>f187DeCiwFhhH2etlU+5byskey4=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
MIID6zCCAtOgAwI...........4qbvd3sxAQmkhR98FSsQixMI+bTHq9zRgeFu6W5GWsun3tmqNE=
</ds:SignatureValue>
</ds:Signature>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">org2#dot.com
</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData Recipient="https://login.salesforce.com/services/oauth2/token" NotOnOrAfter="2012-11-20T06:35:42Z"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2012-11-19T06:34:42Z" NotOnOrAfter="2012-11-20T06:35:42Z">
<saml:AudienceRestriction>
<saml:Audience>https://login.salesforce.com/services/oauth2/token</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2012-11-20T06:35:42Z" SessionIndex="ED868FE5-841D-5192-766C-941A60D6602F">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
</saml:Assertion>
And here's how i am making the request:
curl https://login.salesforce.com/services/oauth2/token -H "Content-Type='application/x-www-form-urlencoded'" -d "grant_type=urn:ietf:params:oauth:grant-type:saml2-bearer" -d "assertion=`cat saml-assertion.base64`"
I have properly encoded the assertion to base64url (previously i was getting error regarding invalid chars in assertion, which i fixed)
Please advice me what/where I can check further on this to know why my assertion is invalid!
PS: Everything is copied from above url's sample assertion, and username,issuer and certificate are changed by me. Also I am setting the NotBefore as the exact login time of the user.

Grant type value needs to be encoded as well, when you are sending that.
urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Asaml2-bearer
Saml assertion needs to be single assertion. It needs to be Base64 encoded as you did and then remove padding or urlencode again.
The value of the "assertion" parameter MUST contain a single SAML 2.0
Assertion. The SAML Assertion XML data MUST be encoded using
base64url, where the encoding adheres to the definition in Section 5
of RFC 4648 [RFC4648] and where the padding bits are set to zero. To
avoid the need for subsequent encoding steps (by "application/
x-www-form-urlencoded" [W3C.REC-html401-19991224], for example), the
base64url encoded data SHOULD NOT be line wrapped and pad characters
("=") SHOULD NOT be included.
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-saml2-bearer-17#section-2.1
Send with post encoded values:
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Asaml2-bearer&
assertion=PHNhbWxwOl...[omitted]...ZT4

Related

PingFederate: Error Signature Required on SP Initiated Login

The PingFederate server responds with error Signature Required on SP initiated SSO, though we are sending Signature Value in the SAML auth request. Following is the request I am sending to Ping Federate:
<?xml version="1.0" encoding="UTF-8"?>
<samlp:AuthnRequest xmlns:ds="http://www.w3.org/2000/09/xmldsig#" > > xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" > AssertionConsumerServiceURL="https://mycompany.com/saml2/acs/" Destination="https://idp.com/idp/SSO.saml2" ID="id-1305fe524135c3980b2446c10dec5f08" IssueInstant="2017-11-21T18:27:17Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" ProviderName="My Service" Version="2.0">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://mycompany.com/</saml:Issuer>
<ds:Signature Id="Signature1">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#id-1305fe524135c3980b2446c10dec5f08">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>PgekvX9t5tSi2t……..KMSXBPFMlhjcpk=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>m0/……………….J5bmNQ==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MII………………o6jkYDUjhprKdQ+m4=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/>
</samlp:AuthnRequest>
I have shortened Signature Value and Certificate for better readability.
PingFederate is rejecting this request with SAML response
<samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Requester" />
<samlp:StatusMessage>Signature required</samlp:StatusMessage></samlp:Status>
Following are logs of PingFederate:
2017-11-21 13:27:17,222 tid:pSs3mUSSSSSSSSSSSSSSSXLK4 DEBUG [org.sourceid.websso.servlet.ProtocolControllerServlet] [qtp2106609649-286] ---REQUEST (GET)/idp/SSO.saml2 from 123.123.123.3:
---PARAMETERS---
SAMLRequest:
3VZJl6LYEt7nr/BYi1p4U……<shortened request for readability>…….zdsjP10u10KWIGwjw6it3/9v4/+l78B
RelayState:
/myAppDashboard/index.html?sso_user=user1%40myidp.com&tenant_domain=xyz.com#/
2017-11-21 13:27:17,222 tid:pSs3mUSSSSSSSSSSSSSSSXLK4 DEBUG [org.sourceid.saml20.bindings.BindingFactory] [qtp2106609649-286] GET
with Params: [SAMLRequest, RelayState]
assume binding: urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect
from: 123.123.123.3
Referer: https://mycompany.com/saml2/login/?email=user1%40myidp.com&tenantIdentifier=undefined(https://mycompany.com/saml2/login/?email=user1%40myidp.com&tenantIdentifier=undefined)
AuthType: null
Content-Type: null
2017-11-21 13:27:17,225 tid:pSs3mUSSSSSSSSSSSSSSSXLK4 DEBUG [org.sourceid.saml20.bindings.LoggingInterceptor] [qtp2106609649-286] Received InMessageContext:
InMessageContext
XML: https://mycompany.com/saml2/acs/" Destination="https://idp.com/idp/SSO.saml2" ID="id-1305fe524135c3980b2446c10dec5f08" IssueInstant="2017-11-21T18:27:17Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" ProviderName="My Service" Version="2.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig# (http://www.w3.org/2000/09/xmldsig) " xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
https://mycompany.com/ (https://mycompany.com/%3c/saml:Issuer) >
http://www.w3.org/2001/10/xml-exc-c14n#"/>
http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
http://www.w3.org/2001/10/xml-exc-c14n#"/>
http://www.w3.org/2001/04/xmlenc#sha256"/>
PgekvX9t5tSi2t/………………J5bmNQ==
MIIDpjCC……………………Q+m4=
entityId: https://mycompany.com/ (https://mycompany.com/) (SP)
virtualServerId: XYZSSO2.0
Binding: urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect
relayState: /myAppDashboard/index.html?sso_user=user1%40myidp.com&tenant_domain=xyz.com#/
SignatureStatus: NOT_PRESENT
Binding says to sign: true
2017-11-21 13:27:17,226 tid:pSs3mUSSSSSSSSSSSSSSSXLK4 DEBUG [org.sourceid.util.log.internal.TrackingIdSupport] [qtp2106609649-286] [cross-reference-message] entityid:null subject:null
2017-11-21 13:27:17,226 tid:pSs3mUSSSSSSSSSSSSSSSXLK4 ERROR [org.sourceid.saml20.profiles.idp.HandleAuthnRequest] [qtp2106609649-286] Exception occurred during request processing
org.sourceid.saml20.profiles.StatusResponseException: Signature required
……..
…….
2017-11-21 13:27:17,251 tid:pSs3mUSSSSSSSSSSSSSSSXLK4 DEBUG [org.sourceid.servlet.HttpServletRespProxy] [qtp2106609649-286] flush cookies: adding Cookie{PF=hashedValue:pSs3mUSSSSSSSSSSSSSSSXLK4; path=/; maxAge=-1; domain=null}
2017-11-21 13:27:17,252 tid:pSs3mUSSSSSSSSSSSSSSSXLK4 DEBUG [org.sourceid.saml20.bindings.LoggingInterceptor] [qtp2106609649-286] Transported Response. OutMessageContext:
OutMessageContext
XML: https://mycompany.com/saml2/acs/" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
XYZSSO2.0
http://www.w3.org/2000/09/xmldsig#">
http://www.w3.org/2001/10/xml-exc-c14n#"/>
http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
http://www.w3.org/2001/10/xml-exc-c14n#"/>
http://www.w3.org/2001/04/xmlenc#sha256"/>
vRc7z0pcj5wzfn/………….UV3nYqUjgsnwHx9tziUqFwmAI=
Signature required
entityId: https://mycompany.com/ (https://mycompany.com/) (SP)
virtualServerId: XYZSSO2.0
Binding: urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
relayState: /myAppDashboard/index.html?sso_user=user1%40myidp.com&tenant_domain=xyz.com#/
Endpoint: https://mycompany.com/saml2/acs/ (https://mycompany.com/saml2/acs/)
SignaturePolicy: BINDING_DEFAULT
2017-11-21 13:27:18,348 DEBUG [org.sourceid.servlet.HttpServletRespProxy] [qtp2106609649-101] adding lazy cookie Cookie{PF=hashedValue:E0oc11111111111111VkfIwa0I; path=/; maxAge=-1; domain=null} replacing null
2017-11-21 13:27:18,348 tid:E0oc11111111111111VkfIwa0I DEBUG [org.sourceid.websso.servlet.IntegrationControllerServlet] [qtp2106609649-101] GET: https://idp.com/idp/startSSO.ping
Need help how can we fix this problem, any knob/flag which could be set on Ping Federate to make it work.
It appears PingFed is expecting your message via Redirect Binding (you are making a GET request) but you are including the Signature in the Request like a Post binding.
PingFederate expects SigAlg and signature as URL parameters along with SAMLRequest in the redirect URL. You need to correct the way you generate the SAML authentication request.
The URL should look like this:
{IDP target URL}?SAMLRequest={url_encoded_SAML_auth_req}&Signature={signature}&RelayState={optional_landing_url}&SigAlg={signature_algorithm}
I am using PySaml2 library and in my case, I had to use the below call to get a working SAML Signed Authn request.
saml_client.prepare_for_authenticate(relay_state=landing_url, sign=True, sigalg=sig_dict[args.sigalg])
You should be able to find the similar flag (sign, sigalg) for your library too.

SAML Single logout through OKTA

I have got the following SP's Request and IDP's reponse:
<samlp:LogoutRequest xmlns="urn:oasis:names:tc:SAML:2.0:metadata" Destination="https://dev-nnn.oktapreview.com/app/somename_hped800eportal_1/exk8dlkd0tCutHWlj0h7/slo/saml" ID="_af6eaa4a-9d5b-41ce-b265-d39dfdc5248e" Version="2.0" IssueInstant="2016-10-14T12:31:59Z" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"><saml:Issuer xmlns:saml="http://www.w3.org/2005/Atom">https://HPED800E:444/SynPortal/login.aspx</saml:Issuer><saml:NameID xmlns:saml="urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified">CDA_Main\hjami</saml:NameID><samlp:SessionIndex>_d9f07562-3a7f-4c03-a62d-8a985f34058f</samlp:SessionIndex><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>bBbMvzSjRc0zc1jtIxmqmkO4bYo=</DigestValue></Reference></SignedInfo><SignatureValue>...5g==</SignatureValue><KeyInfo><X509Data><X509Certificate>...Cw==</X509Certificate></X509Data></KeyInfo></Signature></samlp:LogoutRequest>
<?xml version="1.0" encoding="UTF-8"?><saml2p:LogoutResponse xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://hped800e:444/SynPortal/logout.aspx" ID="id50277036872307661186452042" InResponseTo="_1eef2809-b49e-412e-a0c5-3596e3c0b158" IssueInstant="2016-10-14T00:32:05.949Z" Version="2.0"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://www.okta.com/exk8dlkd0tCutHWlj0h7</saml2:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="#id50277036872307661186452042"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>3k7z8GF3kBemyYm+6+mEbZMSAYw=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>...MA==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>...VNm</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml2p:Status xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"><saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:AuthnFailed"/></saml2p:Status></saml2p:LogoutResponse>
the request is encoded base-64 and then sent via post binding.
I am getting the AuthnFailed response.
I have set up only one sp for the IDP for simplicity.
Does anyone know what I am doing wrong here?
This information is insufficient to determine as what has gone wrong in your implementation for single logout. Can you please provide following information
1) Your single logout settings in Okta that can be found under SAML Settings -> Advanced Settings under General tab of your app?
2) Based on above settings please make sure you have uploaded certificate to Okta?
3) Which SAML toolkit are you using? Can you provide toolkit settings for your toolkit?
See the working SLO request below.
<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_d2be8c5de3aeeeac27c8xxxxyyyy"
Version="2.0"
IssueInstant="2016-04-27T16:15:06Z"
Destination="https://org-name.okta.com/app/simplesamlphpexample/exk4xxyyPcvdVq70x7/slo/saml"
>
<saml:Issuer>http://localhost:8888/simplesamlphp/www/module.php/saml/sp/metadata.php/example-okta-com</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference URI="#_d1be8c5dc2aeeeac27c8daf04b7xxxyyy6b36287bd6">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>{{some_value}}</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>{{some_value}}</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>{{some_value}}</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">{{email}}</saml:NameID>
<samlp:SessionIndex>{{some_value}}</samlp:SessionIndex>
Comparing the SLO settings for your request and mine few things stood out.
1) CanonicalizationMethod Algorithm in my case is set to http://www.w3.org/2001/10/xml-exc-c14n#. Yours is http://www.w3.org/TR/2001/REC-xml-c14n-20010315.
2) Name ID in your case is "CDA_Main\hjami". Can you please let me know which attribute in Okta is this? Also, have you overridden the userName of your app using the mappings from Okta to app (under profile editor -> your app mappings). For example, I am overriding the app userName from Okta login/email to be custom attribute.
If you are using another attribute (whose value is set to CDA_Main\hjami) from Okta as the username of the app, please make sure that you are overriding it like I am doing in the screenshot above.
I also had a hard time in making this Logout request successfully.
Here is the solution that worked for me:
You'll need the following keys:-
(a) Service provider's (your application's) private key, e.g. sp-pvt-key.pem
(b) Service provider's public key, e.g. sp-pub-key.pem
Note: You can generate these keys via openssl from your terminal.
Steps:
Provide SP's private key on SAML's configuration strategy in you application's code.
Upload SP's public key on okta's logout configuration.
Now you'll get successful logout response.

What should be the signature value in the URL for HTTP-Redirect Binding SAML Request

This query is in addition to the question asked in post - HTTP-Redirect Binding SAML Request.
I am trying to implement the dotnet SSO solution by sending the SAML Authentication Request via HTTP-Redirect Binding.
After generating the SAML AuthnRequest and computing the signature using the private certificate of SP I have tried two ways to add the signature in the url.
Generate SAML AuthnRequest XML.
<?xml version="1.0" encoding="utf-8"?>
<AuthnRequest xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
ID="_d726aced-4c62-4562-8237-062f7faf0750"
Version="2.0" IssueInstant="2015-04-03T19:59:58.6709058Z"
Destination="https://idp.client.com/adfs/ls/"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
AssertionConsumerServiceURL="https://serviceprovider.clientportal.com/samlsso.aspx"
xmlns="urn:oasis:names:tc:SAML:2.0:protocol"
>
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://serviceprovider.clientportal.com</Issuer>
<NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" />
</AuthnRequest>
Compute Signature using the SAML AuthnRequest XML which generates an XML Signature tag as shown below
<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="#_d726aced-4c62-4562-8237-062f7faf0750">
<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/2000/09/xmldsig#sha1" />
<DigestValue>rxoGtdmI...rgY=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>XRLdJHIGWClJxp....fTPUfIghl5kTfV4=</SignatureValue>
Method-1 to add signature in the query string
Encode the AuthnRequest XML (without signature embedded) using Base64 encoding and URL encoding
Encode the above xml signature string using Base64 encoding and URL encoding
Construct the URL in the following way
https://IDP.com/adfs/ls/?SAMLRequest=UrlEncodedBase64AuthnRequest&RelayState=value&SigAlg=value&Signature=UrlEncodedBase64EncodedXMLSignature
Method-2 to add signature in the query string
Encode the AuthnRequest XML (without signature embedded) using Base64 encoding and URL encoding
Extract the value of tag from the above xml signature string to be sent as URL encoded value of "Signature" query string parameter.
Construct the URL in the following way
https://IDP.com/adfs/ls/?SAMLRequest=UrlEncodedBase64AuthnRequest&RelayState=value&SigAlg=value&Signature=UrlEncodedValueExtractedFromSignatureValueTag
In both the cases I am getting signature validation failure at the IDP. Any idea on how to generate the signature to be sent in the URL?
Any help on this would be of great help!
Thanks,
Piush
See "Section 3.4.4.1 DEFLATE Encoding" in the SAML 2.0 Bindings document for specific instructions on how you are supposed to include the DSig when using the REDIRECT Binding.
The signature used in the HTTP-Redirect binding is not an XML signature. I suggest taking another look at the SAML v2.0 Bindings Specification, section 3.4.
Alternatively, take a look at our ComponentSpace SAML v2.0 component. This is a commercial product for .NET/ASP.NET which fully supports the SAML specification.

How to implement SAML logout to ADFS with openSaml?

I created Logout Request using openSaml library and added signature
<samlp:LogoutRequest ID="_f576971e-5123-49e4-8152-80653dcdfb1a"
IssueInstant="2015-07-23T15:21:42.254Z"
Reason="urn:oasis:names:tc:SAML:2.0:logout:user" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<samlp:Issuer xmlns:samlp="urn:oasis:names:tc:SAML:2.0:assertion">https://my_host/logout</samlp:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#_f576971e-5123-49e4-8152-80653dcdfb1a">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue/>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue/>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIC...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2:NameID
Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">_933c8876-9128-431f-b250-08975fde2a24</saml2:NameID>
<saml2p:SessionIndex xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">8ee4bf85-6792-42f5-b038-a3342a0e0e17</saml2p:SessionIndex>
</samlp:LogoutRequest>
And I encoded this and sended to ADFS-server like URL:
https://ADFS_HOST/adfs/ls/SignOut.aspx?SAMLRequest=nVbbk...
But, I got an error from ADFS:
The Federation Service encountered an error while processing the SAML
authentication request.
Additional Data Exception details: System.Xml.XmlException:
MSIS0018: The SAML protocol message cannot be read because it contains
data that is not valid. ---> System.InvalidOperationException: No
corresponding start element is open. at
System.Xml.XmlBaseReader.ReadEndElement() at
Microsoft.IdentityModel.Protocols.XmlSignature.SignedInfo.ReadFrom(XmlDictionaryReader
reader, TransformFactory transformFactory) at
Microsoft.IdentityModel.Protocols.XmlSignature.Signature.ReadFrom(XmlDictionaryReader
reader) at
Microsoft.IdentityModel.Protocols.XmlSignature.EnvelopedSignatureReader.ReadSignature()
at
Microsoft.IdentityModel.Protocols.XmlSignature.EnvelopedSignatureReader.TryReadSignature()
at
Microsoft.IdentityServer.Protocols.Saml.SamlProtocolSerializer.ReadCommonElements(XmlReader
reader, SamlMessage message) --- End of inner exception stack trace
--- at Microsoft.IdentityServer.Protocols.Saml.SamlProtocolSerializer.ReadCommonElements(XmlReader
reader, SamlMessage message) at
Microsoft.IdentityServer.Protocols.Saml.SamlProtocolSerializer.ReadLogoutRequest(XmlReader
reader) at
Microsoft.IdentityServer.Protocols.Saml.SamlProtocolSerializer.ReadSamlMessage(XmlReader
reader, NamespaceContext context) at
Microsoft.IdentityServer.Protocols.Saml.HttpSamlBindingSerializer.ReadProtocolMessage(String
encodedSamlMessage) at
Microsoft.IdentityServer.Protocols.Saml.Contract.SamlContractUtility.CreateSamlMessage(MSISSamlBindingMessage
message) at
Microsoft.IdentityServer.Web.Protocols.Saml.SamlProtocolManager.Logout(HttpSamlMessage
logoutMessage, String sessionState, String logoutState, Boolean
partialLogout, Boolean isUrlTranslationNeeded, HttpSamlMessage&
newLogoutMessage, String& newSessionState, String& newLogoutState,
Boolean& validLogoutRequest)
And I can't find some information about this problems.
Any ideas?
6.3.0.0 is ADFS on S2012R2 :-). I needed that to take a look in the executable. I didn't want to look in the wrong server. The exception says that there is something wrong with the signature. So true: the digest and signature values are missing.
No offense just a warning. It looks a bit as if you are trying to write this yourself. If so then do realize that it is a really serious amount of work. And requires major maintenance effort. And signatures is probably the trickiest part, steer away from that course if you can. Think in months of learning+work....
At first glimpse there seem to be other issues with the request. But discussing them is really a lot of work.... I suggest you do take at least a look at the XML of another implementation. One that comes of the shelve (Kantara certified even better). And make sure you have the same attributes and elements.

SAML Secured AuthnRequest Fails

I'm not able to make a secured ECP AuthnRequest to my Shibboleth IdP. I've got a small proof of concept SP running which is based heavily on the Spring SAML extension sample app. My SP metadata was generated using the Spring SAML extension sample app's metadata generator. The signing key being used is the apollo one included with the sample app samlKeystore.jks key store, all of which is also in my own small SP app.
In my SP metadata, I have the AuthnRequestsSigned attribute set to true like so :
<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
If I set AuthnRequestsSigned to false and make the ECP SOAP POST to the IdP, it works just fine. I get the proper SOAP message back from the IdP. But if that value is true, I get a non-descriptive error message:
<env:Fault>
<faultcode>env:Client</faultcode>
<faultstring>An error occurred processing the request.</faultstring>
<detail/>
</env:Fault>
I look in the Shibboleth (IdP) logs and see:
Attempting to extract credential from an X509Data
Found 1 X509Certificates
Found 0 X509CRLs
Single certificate was present, treating as end-entity certificate
Credentials successfully extracted from child {http://www.w3.org/2000/09/xmldsig#}X509Data by provider org.opensaml.xml.security.keyinfo.provider.InlineX509DataProvider
A total of 1 credentials were resolved
This displays twice in the log for my transaction. My assumption is because it's finding the certificate in the request and in my SP metadata. Further down in the log during this same transaction I see this followed by a stack trace:
Attempting to validate signature using key from supplied credential
Creating XMLSignature object
Validating signature with signature algorithm URI: http://www.w3.org/2000/09/xmldsig#rsa-sha1
Validation credential key algorithm 'RSA', key instance class 'sun.security.rsa.RSAPublicKeyImpl'
Signature did not validate against the credential's key
Signature validation using candidate validation credential failed
Signature did not validate against the credential's key
I compared the certificate that is in the ECP POST AuthnRequest to the one in my SP metadata used for "signing" and they are the same. So I'm not sure why I'm getting this error.
My understanding is that the IdP will take the certificate found in the <ds:X509Certificate> tag of the request (which is the public key) and make sure that's the same one defined in the SP metadata. Then use that cert to verify the signature value which is also in the request in the <ds:SignatureValue> element. If it validates then it moves forward with the AuthnRequest. Is this accurate?
What piece am I missing?
Update 1: I've added the logging lines as suggested and here's all it shows for the ECP requests:
signatureMethodURI = http://www.w3.org/2000/09/xmldsig#rsa-sha1
jceSigAlgorithm = SHA1withRSA
jceSigProvider = SunRsaSign
PublicKey = Sun RSA public key, 2048 bits
modulus: <long value here>
public exponent: 65537
Signature verification failed.
One thing of note, if I make a request to my SP via a browser and I'm not signed in, I get redirected to my IdP login page as expected. I check the IdP logs and see that that request was also signed and it validates. I looked at the form data sent to the IdP from the SP and see that AuthnRequest is also signed using the same certificate but the SignatureValue value are different of course. That non-ECP request data XML looks very similar to the ECP request SOAP XML yet the ECP one fails.
UPDATE 2: I'm using spring-security-saml-1.0.0.RELEASE, and Shibboleth IdP v2.4.0. Here's a sample message I'm sending to the IdP:
<?xml version="1.0" encoding="UTF-8"?>
<soap11:Envelope
xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
<soap11:Header>
</soap11:Header>
<soap11:Body>
<saml2p:AuthnRequest
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="http://1XP21VRS.mydomain.com:8080/proofofconceptapp-sso/saml/SSO/alias/conceptSSO" ForceAuthn="false" ID="a3j6fd01d0ciahe25b56i326bhe212" IsPassive="false" IssueInstant="2014-10-24T19:37:43.207Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Version="2.0">
<saml2:Issuer
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://1XP21VRS.mydomain.com:8080/proofofconceptapp-sso
</saml2:Issuer>
<ds:Signature
xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#a3j6fd01d0ciahe25b56i326bhe212">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>mMJbjpmWr6OMP9eU70RA9TtfXGY=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>I6rHpgjWgl5l5sjst+VHuSUnjUaOBnPIbUrWwcAfdTDSFY2wxUuNdHpXt/YqBfP9ZKdTWZV1IjbTR666T7sa1bZawgT3UO07FoBVAc5z+AH0nCvIz+UNSqpunPTaEdUhSaGmNHSItvFtvz2fDmvZl18GwXrTz4g6vvxKkdo/FijgvYldfYYuO+obcjof1SJmpOOr1iRNvpyGQMxcaH9e07QfJO9SDcLP2elvPvwbJsGGl/n/3sIG+kIm0MECU3hv/4pLx6+SyHDXjdhdOD2HyxGL1t7iIYG1AaDX4dkIt2wH2WOyzhfO2MyykqChhRcYWFdEdgqaQW/IBLPxsVjN9g==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIDUjCCAjqgAwIBAgIEUOLIQTANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQGEwJGSTEQMA4GA1UE
CBMHVXVzaW1hYTERMA8GA1UEBxMISGVsc2lua2kxGDAWBgNVBAoTD1JNNSBTb2Z0d2FyZSBPeTEM
MAoGA1UECwwDUiZEMQ8wDQYDVQQDEwZhcG9sbG8wHhcNMTMwMTAxMTEyODAxWhcNMjIxMjMwMTEy
ODAxWjBrMQswCQYDVQQGEwJGSTEQMA4GA1UECBMHVXVzaW1hYTERMA8GA1UEBxMISGVsc2lua2kx
GDAWBgNVBAoTD1JNNSBTb2Z0d2FyZSBPeTEMMAoGA1UECwwDUiZEMQ8wDQYDVQQDEwZhcG9sbG8w
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCXqP0wqL2Ai1haeTj0alwsLafhrDtUt00E
5xc7kdD7PISRA270ZmpYMB4W24Uk2QkuwaBp6dI/yRdUvPfOT45YZrqIxMe2451PAQWtEKWF5Z13
F0J4/lB71TtrzyH94RnqSHXFfvRN8EY/rzuEzrpZrHdtNs9LRyLqcRTXMMO4z7QghBuxh3K5gu7K
qxpHx6No83WNZj4B3gvWLRWv05nbXh/F9YMeQClTX1iBNAhLQxWhwXMKB4u1iPQ/KSaal3R26pON
UUmu1qVtU1quQozSTPD8HvsDqGG19v2+/N3uf5dRYtvEPfwXN3wIY+/R93vBA6lnl5nTctZIRsyg
0Gv5AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFQwAAYUjso1VwjDc2kypK/RRcB8bMAUUIG0hLGL
82IvnKouGixGqAcULwQKIvTs6uGmlgbSG6Gn5ROb2mlBztXqQ49zRvi5qWNRttir6eyqwRFGOM6A
8rxj3Jhxi2Vb/MJn7XzeVHHLzA1sV5hwl/2PLnaL2h9WyG9QwBbwtmkMEqUt/dgixKb1Rvby/tBu
RogWgPONNSACiW+Z5o8UdAOqNMZQozD/i1gOjBXoF0F5OksjQN7xoQZLj9xXefxCFQ69FPcFDeEW
bHwSoBy5hLPNALaEUoa5zPDwlixwRjFQTc5XXaRpgIjy/2gsL8+Y5QRhyXnLqgO67BlLYW/GuHE=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</saml2p:AuthnRequest>
</soap11:Body>
</soap11:Envelope>
I'm pretty much just copying the response from the initial PAOS request to the SP (Spring SAML), removing the header innards, and sending that along to the Shibboleth IdP. The headers that I send are:
Content-Type: text/xml
Authorization: Basic <base64 encoded credential string here>
Update 3: Signed non-ECP AuthnRequests validate just fine. So it's only SOAP ECP AuthnRequests to the IdP where the signature fails. Any ideas?
Update 4: Still can't get this working. Any help would be appreciated.