What is the possible value for the Concatenated String for generating SAML Signature - saml

> <samlp:LogoutRequest ID="_36167d94-d868-4c04-aee3-8bbd4ed91317"
> Version="2.0" IssueInstant="2017-01-05T16:21:55.704Z"
> Destination="https://werain.me/"
> xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"><Issuer
> xmlns="urn:oasis:names:tc:SAML:2.0:assertion">urn:federation:MicrosoftOnline</Issuer><NameID
> Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
> xmlns="urn:oasis:names:tc:SAML:2.0:assertion">4948f6ce-4e3b-4538-b284-1461f9379b48</NameID><samlp:SessionIndex>_eafbb730-b590-0134-a918-00d202739c81</samlp:SessionIndex></samlp:LogoutRequest>
Given my, Logout Request looks like this. If I have to verify the Logout request do I have to construct the string that looks like this (i.e raw string value)
SAMLRequest=<samlp:LogoutRequest ID="_36167d94-d868-4c04-aee3-8bbd4ed91317" ... </samlp:LogoutRequest>&SigAlg=http://www.w3.org/2000/09/xmldsig#rsa-sha1
and then verify the signature for the above string or should I encode the SAMLRequest and SigAlg value
i.e
SAMLRequest=Base64 encode value or raw logout request&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1
Reason for this confusion is
SAML spec says extracted from here
A string consisting of the concatenation of the raw, unencoded XML
making up the SAML protocol message (NOT the base64-encoded version),
But OneSAML Create a signature with the Base64 encode version of the request (logout request). Have a look at here
Not sure what is the correct implementation I have to use to verify the signature.
NOTE: HTTP-Redirect BINDING.

Your link and quote is not related with the HTTP-Redirect binding.
Check the 3.4.4.1 section of
https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf
Onelogin's SAML toolkits implement signatures following the standard.
You can see for example that the implementation of simpleSAMLphp build the signature on the Redirect binding on the same way:
https://github.com/simplesamlphp/saml2/blob/master/src/SAML2/HTTPRedirect.php#L22
Or opensaml
https://github.com/apigee/java-opensaml2/blob/master/src/main/java/org/opensaml/saml2/binding/encoding/HTTPRedirectDeflateEncoder.java#L162
You can play signing and validating SAML Messages with:
https://www.samltool.com/online_tools.php

Related

Prevent URL-encoding of values when adding headers to TRESTClient

I'm working on a Delphi REST client for a public API that requires an HMAC256/Base64 signed string to be added to the headers of the request to authenticate. I've spent hours trying to figure out why it's not working, so I compared the raw request from my Delphi client to that of a working C# library (using Wireshark).
It turns out my request matches perfectly the request generated by the working C# library, except that Delphi's REST client is URL-encoding the values added to the request's header, therefore invalidating the carefully crafted signature.
This is how I'm adding the signature string to the header:
RESTRequest1.Params.AddHeader('SIGNATURE', FSignature);
The signature string may have slashes, plus signs, and/or equal signs that are being URL-encoded when they shouldn't. For example when the value of the signature string is...
FSignature = '8A1BgACL9kB6P/kXuPdm99s05whfkrOUnEziEtU+0OY=';
...then the request should should output raw headers like...
GET /resource HTTP/1.1
User-Agent: Embarcadero URI Client/1.0
Connection: Keep-Alive
<snip>
SIGNATURE: 8A1BgACL9kB6P/kXuPdm99s05whfkrOUnEziEtU+0OY=
<snip>
...but instead Wireshark shows this as the real value being sent...
SIGNATURE: 8A1BgACL9kB6P%2FkXuPdm99s05whfkrOUnEziEtU%2B0OY%3D
Is there a way to prevent the URL-encoding of values when using AddHeader? Or maybe another way to add raw headers to a TRESTClient request?
PS: I already tried both TRESTRequest.Params.AddHeader and TRESTClient.AddParameter with TRESTRequestParameterKind.pkHTTPHEADER as the Kind parameter. Both resulted in URL-encoded values.
PS2: Using Delphi RAD Studio 10.3.
You should include poDoNotEncode in the Options property of the TRESTRequestParameter.
This can be done using:
RESTClient1.AddParameter('SIGNATURE', FSignature, pkHTTPHEADER, [poDoNotEncode]);
or by using:
RESTClient1.Params.AddHeader('SIGNATURE', FSignature).Options := [poDoNotEncode];

Should SAMLResponse contain extra line breaks?

I have been working on a solution that retrieves SAMLResponse from third-party IdP and we simply decode that SAMLResposne with jdk Base64 decoder,
However one of the cases is where we get SAMLResponse with line breaks (\n) after some characters and when we try to decode it with,
...
byte[] base64DecodedResponse = Base64.getDecoder().decode(authnResponse);
...
This authnResposne is SAMLResponse from HTTP header which has \n new line, this failed to parse in above code.
I have been looking for a confirmation whether any SAMLResponse received by SPs must be in Base64 encoded format hence should never contain line breaks or it can be and SP should handle it.
Applying fix from SP side is simple, simply .replaceAll("\n","") will do the job, but is it really industry standard to EDIT the SAMLResponse?
You probably need to use Base64.Decoder getUrlDecoder()
SAML2 is supposed to be encoded in base64url - basically Base 64 Encoding with URL and Filename Safe Alphabet https://www.rfc-editor.org/rfc/rfc4648#section-5.
getUrlDecoder also should reject embedded newlines in the base64 so it may not do you any good.
I would be interested in knowing which SAML provider you are using.
For those who looking for wisdom here,
Editing SAMLResponse after it's signed is bad practice.
According to SAML documentation, SAMLResponse encoding can have either BASE 64 Content-Transfer encoding RFC-2045 or Base64 Encoding RFC-4648.
From SAML 2.0 core-doc, section 5
Profiles MAY specify alternative signature mechanisms such as S/MIME or signed Java objects that contain SAML documents. Caveats about retaining context and interoperability apply
This leads to the justification that SPs should be able to decode Standard and MiMe decoding, hence a try and catch block with Base64.getMimeDecoder() to get around this issue.

Verify SAML Response from ADFS

I have problems verifying a SAML-response I get form an ADFS Server. I get the response as an url like CALLBACK_URL?SAMLResponse=ENCODED_XML&Signature=SIGNATURE_VALUE&SigAlg=SIGNATURE_ALGORITHMwhile SIGNATURE_ALGORITHM is http://www.w3.org/2001/04/xmldsig-more#rsa-sha256. I managed to decode the response but I am not able to find a way to verify the response using the given signature.
My main problem is that the signature has a very unexpected format. Because of the given signature algorithm I expect the signature to have a length of 32 bytes but what I get when I base64-decode the signature is a string with length 256.
I expect that decoding the signature using base64 is not sufficient. Unfortunately I have not been able to find out what to do next so far. So my question is: What do I have to do to correctly decode the signature to be able to verify it?
I believe you're conflating a hash with a signature.
The signature takes the hash of the message as input and encrypts it with a key. In your case the SigAlg parameter indicates that the 32 byte hash of the SAML message is encrypted with (apparently) a 2048 bits RSA private key, possibly using PKCS#1 v1.5 padding as described in https://www.rfc-editor.org/rfc/rfc6931#section-2.3.2 resulting in a 256 byte signature that can be verified with the associated 2048 bits RSA public key of the sender.
Apart from that: I assume your referring to a SAML request rather than a SAML response since the latter must not be sent by using the HTTP redirect binding as written down in the Web Browser SSO Profile specification, page 16: https://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf (top of the page):
Identity Provider issues to Service Provider In step 5, the identity provider issues a message to be delivered by
the user agent to the service provider. Either the HTTP POST, or HTTP
Artifact binding can be used to transfer the message to the service
provider through the user agent. The message may indicate an error, or
will include (at least) an authentication assertion. The HTTP Redirect
binding MUST NOT be used, as the response will typically exceed the
URL length permitted by most user agents.

IDP Initialized SSO, how to configure when dont have the pwd for PrivateKey

I am using spring-security saml extension to implement the IDP initiated SSO for my application. I am using https protocol and signature/encryption is ON. I dont need SLO/SP-Initiated SSO.
On the transport layer's encryption/decryption (because using HTTPS protocol), I am fine as My web container (SP one) is going to take care of the decryption part. And this certificate could be different then SP's certifiate.
At the SP end, I need the IDP's public key to verify the signature on SAMLAuthResponse Msg, which I have as part of the IDP's metadata file...so no issues here.
Couple of qns:
For decryption of the SAMLAuthResponse Msg, Do I need SP's
certificate's private key?
And If I need the private key, how to
create the bean definition for keyManager when I have the jks file,
jks-pwd, alias, but no pwd for privatekey? Can I pass the empty string (as "") in the password field in the alias-password value pair.
You can skip usage of private key in this case. You can find detail on how to use Spring SAML without keystore in the manual chapter 8.1:
In case your application doesn't need to create digital signatures
and/or decrypt incoming messages, it is possible to use an empty
implementation of the keystore which doesn't require any JKS file -
org.springframework.security.saml.key.EmptyKeyManager. This can be the
case for example when using only IDP-Initialized single sign-on.
Please note that when using the EmptyKeyManager some of Spring SAML
features will be unavailable. This includes at least SP-initialized
Single Sign-on, Single Logout, usage of additional keys in
ExtendedMetadata and verification of metadata signatures. Use the
following bean in order to initialize the EmptyKeyManager:
<bean id="keyManager" class="org.springframework.security.saml.key.EmptyKeyManager"/>

Are attributes allowed in a SAML authentication request?

Is it possible to send attributes in a SAML authentication request?
<samlp:AuthnRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="aaf23196-1773-2113-474a-fe114412ab72"
Version="2.0"
IssueInstant="2004-12-05T09:21:59Z"
AssertionConsumerServiceIndex="0"
AttributeConsumingServiceIndex="0">
<saml:Issuer>https://sp.example.com/SAML2</saml:Issuer>
<samlp:NameIDPolicy
AllowCreate="true"
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/>
</samlp:AuthnRequest>
Technically, yes, it is possible, since AuthnRequest can contain an Extensions element, which can contain anything - see the SAML 'core' spec: AuthnRequest (section 3.4.1) is derived from RequestAbstractType (section 3.2.1) which has an optional Extensions. The sender and recipient would have to agree on the syntax and semantics of data sent this way.
I can't see a more 'conventional' way to do this, since Attributes are usually in Assertions, rather than AuthnRequests.
There is a case where attributes are to be part of auth request.
so that we can get that attribute name from request to construct response assertion with the same.
because service provider validates the response by comparing the attribute names.we can take the example of Salesforce as service provider, where the same happens.