Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Service Providers can't verify the signature of the assertion #10

Closed
fedecastelli opened this issue Oct 16, 2019 · 8 comments
Closed

Service Providers can't verify the signature of the assertion #10

fedecastelli opened this issue Oct 16, 2019 · 8 comments

Comments

@fedecastelli
Copy link

I created my own Identity Provider using this repository and I tried to integrate it into Facebook Workplace and Dropbox Business for my company. What I currently can do is to receive and elaborate the SAML Request generated by the Service Provider, elaborate it, authenticate the user and create the assertion signed. When the SP provider receives the assertion, it's not able to verify the signature.
I was deep digging into this issue and I found this interesting thing: this repo generates the signature using this XML structure:

<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
	<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
	<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256"></ds:SignatureMethod>
	<ds:Reference URI="#_49aed2b8dc9743d0be117cf26707ca22">
		<ds:Transforms>
			<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
			<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
		</ds:Transforms>
		<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256"></ds:DigestMethod>
		<ds:DigestValue>{hash_generated}</ds:DigestValue>
	</ds:Reference>
</ds:SignedInfo>

And then, when I compose the final assertion containing the signature value, the XML structure is:

<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:CanonicalizationMethod>
		<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256"></ds:SignatureMethod>
		<ds:Reference URI="#_49aed2b8dc9743d0be117cf26707ca22">
			<ds:Transforms>
				<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
				<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
			</ds:Transforms>
			<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256"></ds:DigestMethod>
			<ds:DigestValue>VtPNWg/frnHlwF2S42/P2Y4wPVd8Bd9kmS/biB4F8wg=</ds:DigestValue>
		</ds:Reference>
	</ds:SignedInfo>
	<ds:SignatureValue>shM8MsFxHzhBZG0PsIrNliphVeKAkvZONA88/brE81ZO5bdn39KCLTR6wfBPlq6XN4F/Nw61jABaN2yrcNKyPnKo/9UB+uSbkZMNiBsHb6M+o9z8P4jiWFNCxIzWesAeKJwBtetX/wbq0vxA+w02+OmxMNuAKe1BnxQqBycTQpD7WqDEcQ6/LihbBpHnHl+ObjAZuE4+pLwJPifW1hN4hWLpdDYnfRPzEpg6tkf5lg/zKBor1f+zMwddi5jIqUJZWO8svjxXGHopRv6xgYuVYZz6WCpJUnMNuYCrtwSyyZ9scnDu8cyO8rSRVAdfQkXWXXxVh+7xKiG2CCvTks2CXA==</ds:SignatureValue>
	<ds:KeyInfo>
		<ds:X509Data>
			<ds:X509Certificate>MIIDVTCCAj0CCB5f3a7UpFWQMA0GCSqGSIb3DQEBCwUAMG0xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGQXVzdGluMRIwEAYDVQQKDAlJYW51bSBJbmMxEjAQBgNVBAsMCUlhbnVjIEluYzEVMBMGA1UEAwwMaWQuaWFudW0uY29tMB4XDTE5MTAwMTEzMjcwN1oXDTIzMDkzMDEzMjcwN1owbTELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMQ8wDQYDVQQHDAZBdXN0aW4xEjAQBgNVBAoMCUlhbnVtIEluYzESMBAGA1UECwwJSWFudWMgSW5jMRUwEwYDVQQDDAxpZC5pYW51bS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKA0/7RBUZ+WR7NZvJu/hQKNIwheek29elh4jlzIk7of2ZmvOyYIz+5ualYf4SOlMopM3WpfYhZ+Vm2P07LnDQuxDxNX6lvq5l/vucpiNsbCbV/vLxPu6eswP7LdZ+Igt7beTyG8OUOlV5oXqjwVU6iBSysNmyaOke48jn4rG8vSEBurKTnqBLLzuCXmZHnuU5tOVUrMLnQ9va7/yk8lWe4SV0w/ncSDhAdtYHYiFee7wT4kOoiBHXeJKD+CoGTysw3lRjXfu9TuPE3TS3zj8fISHyYt1hVfqxaA84RIe7yqeRO+xYpMKGMtmXa/RHmFMBZJqc8WiLcfCuw+SsmIEjAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAKkMLKqcMWP9XHC6sn6m5ec6wDz6QrFk6SM0OmAn16PxMhH85vtWmyFESb7Tw3rQ4dwGjFGs2S27PEI0W+apzc+sX8vSSq4acVdQQBd/pm3YRgOiFilXgNQ4gyYDjuJVaq+AqbeBVA5kp0aYiwqeBKuPr6aHBR0yMqi2wpNKONEgM/hBK6UbcC9iJEIl9YUz+nCuPzyg1kPEZmEYQw+wNvAzrxACLg1ma4wtuBKn81F+fSKyVuVx/Tn2V/u1qe2f8gMMtJO8lRgFuUNba4EI6Yz4jI6l2b8da4fj0/hWVOOG3AcGIrkVNAyatD4GnQPsz8AIauws14SIXuCHC+f/+DY=</ds:X509Certificate>
		</ds:X509Data>
	</ds:KeyInfo>
</ds:Signature>

So the XML element <SignedInfo has the attribute xmlns:ds="http://www.w3.org/2000/09/xmldsig#" while I'm generating the signature and then that attribute disappears when the assertion is created.

Could it be the problem?

@mx-moth
Copy link
Owner

mx-moth commented Oct 17, 2019

XML signing works in the following way:

  • You have an element you want to sign. In the case of flask-saml2, it is anything that extends SignableTemplate, which is the <saml:Assertion> and <samlp:Response> elements.
  • You construct these elements including all their children
  • You transform these elements into a canonical string representation. Making a canonical string representation involves details such as the order of attributes, how and where to include namespace declarations, what to do with whitespace, etc.
  • You take this canonical string representation, make a digest, then sign the digest.
  • You make a <Signature> element that refers to the element you made the signature for, has the signed digest, and information about which digest and signature methods you used, and any public keys involved.
  • You include this <Signature> element somewhere in the document. In the case of a SignableTemplate subclass, the <Signature> is appended to the element, which is called an enveloped signature. XML signing libraries know about this strategy, and remove the <Signature> element before transforming the element into its canonical form for signing.

You're right that the xml namespace declarations shift about during signing. This is because the string representation is done using Exclusive XML Canonicalization. This is deliberate, and a reference to this is included in the <SignedInfo> element. I don't think this is the problem.

Can you post details about how you've configured your IdP, which Service Providers you're attempting to authorize with, and any configuration details for them? Some Service Providers such as Salesforce and Google Apps require responses in particular formats with particular elements, encodings, and compressions. These Service Providers have their own handlers in flask_saml2/idp/sp/. The Service Provider you're attempting to communicate with might require one of these unique handlers/

@mx-moth
Copy link
Owner

mx-moth commented Oct 18, 2019

I tried to integrate a flask-saml2 IdP with a SP from another provider. I used samlltest.id. The test SP had some problems with the metadata regarding the nameid format used, and with the SingleLogoutService url. I've fixed these in the samltest-id branch.

Could you please test your IdP with this branch and see if either Facebook Workplace or Dropbox Business work with these changes? I don't have an account on either system to test against, so I can not check myself unfortunately.

@fedecastelli
Copy link
Author

Thank you for your response and the explanation about how to generate the signature.

I tested the update into the samltest-id branch but it's not working. I tested it with Dropbox (I didn't test it with Facebook Workplace because I need to set up a server with the HTTPS-enabled) but the SP is not able to verify the assertion.

The only thing that I updated is the digest algorithm from SHA-1 to SHA-256 because it has been declared insecure and a lot of Service Providers don't support it. I also added these configurations to the Identity Provider:

app.config['SAML_SERVICE_PROVIDERS'] = [
    {
        'CLASS': 'flask_saml2.idp.SPHandler',
        'OPTIONS': {
            'display_name': 'SSO Dropbox',
            'entity_id': 'Dropbox',
            'acs_url': 'https://www.dropbox.com/saml_login',
            'certificate': certificate_from_file(keys / 'dropbox-sp.pem')
        },
    }
]

This is the SAML response created:

<samlp:Response
	xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://www.dropbox.com/saml_login" ID="_487b3b0c35bc4926812ff2ffc0cc2c3e" InResponseTo="id-035bc4bc48574b5585d1f43bc4069f6c" IssueInstant="2019-10-18T08:49:56.358687+00:00" Version="2.0">
	<saml:Issuer
		xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://localhost:8000/saml/metadata.xml
	</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:CanonicalizationMethod>
			<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256"></ds:SignatureMethod>
			<ds:Reference URI="#_487b3b0c35bc4926812ff2ffc0cc2c3e">
				<ds:Transforms>
					<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
					<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
				</ds:Transforms>
				<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256"></ds:DigestMethod>
				<ds:DigestValue>x/K6JuPz4RCX+F4A+UvCYtPyzTLmD6UmQHrJcT1B52Y=</ds:DigestValue>
			</ds:Reference>
		</ds:SignedInfo>
		<ds:SignatureValue>giNupYwbqu9HVsX7FsVDaDIg9/OWlVzB6m6DRSHqHPV3WPjqSG/A4ZoJx0xGnZ9JS3LtTxQeIiWs1CuoBizg5A==</ds:SignatureValue>
		<ds:KeyInfo>
			<ds:X509Data>
				<ds:X509Certificate>MIICKzCCAdWgAwIBAgIJAM8DxRNtPj90MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTEwODEyMjA1MTIzWhcNMTIwODExMjA1MTIzWjBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANcNmgm4YlSUAr2xdWei5aRU/DbWtsQ47gjkv28Ekje3ob+6q0M+D5phwYDcv9ygYmuJ5wOi1cPprsWdFWmvSusCAwEAAaOBpzCBpDAdBgNVHQ4EFgQUzyBR9+vE8bygqvD6CZ/w6aQPikMwdQYDVR0jBG4wbIAUzyBR9+vE8bygqvD6CZ/w6aQPikOhSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDPA8UTbT4/dDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA0EAIQuPLA/mlMJAMF680kL7reX5WgyRwAtRzJK6FgNjE7kRaLZQ79UKYVYa0VAyrRdoNEyVhG4tJFEiQJzaLWsl/A==</ds:X509Certificate>
			</ds:X509Data>
		</ds:KeyInfo>
	</ds:Signature>
	<samlp:Status>
		<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"></samlp:StatusCode>
	</samlp:Status>
	<saml:Assertion
		xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_b0be6e7a397445e9ab861a5e4ffb35b8" IssueInstant="2019-10-18T08:49:56.358687+00:00" Version="2.0">
		<saml:Issuer>http://localhost:8000/saml/metadata.xml</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:CanonicalizationMethod>
				<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256"></ds:SignatureMethod>
				<ds:Reference URI="#_b0be6e7a397445e9ab861a5e4ffb35b8">
					<ds:Transforms>
						<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
						<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
					</ds:Transforms>
					<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256"></ds:DigestMethod>
					<ds:DigestValue>b7PdH3BfRXQokoDPzZUvWVyeJpNx9zbqQ38XyR2PlHY=</ds:DigestValue>
				</ds:Reference>
			</ds:SignedInfo>
			<ds:SignatureValue>AOQo807nZHWmwWiWiVlLqVg+Ck6HhgrukAFfWGhlN5WGh5d0/arivgIgWpeWdCTKJHTH7xHa99Eu5wN6166GZA==</ds:SignatureValue>
			<ds:KeyInfo>
				<ds:X509Data>
					<ds:X509Certificate>MIICKzCCAdWgAwIBAgIJAM8DxRNtPj90MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTEwODEyMjA1MTIzWhcNMTIwODExMjA1MTIzWjBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANcNmgm4YlSUAr2xdWei5aRU/DbWtsQ47gjkv28Ekje3ob+6q0M+D5phwYDcv9ygYmuJ5wOi1cPprsWdFWmvSusCAwEAAaOBpzCBpDAdBgNVHQ4EFgQUzyBR9+vE8bygqvD6CZ/w6aQPikMwdQYDVR0jBG4wbIAUzyBR9+vE8bygqvD6CZ/w6aQPikOhSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDPA8UTbT4/dDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA0EAIQuPLA/mlMJAMF680kL7reX5WgyRwAtRzJK6FgNjE7kRaLZQ79UKYVYa0VAyrRdoNEyVhG4tJFEiQJzaLWsl/A==</ds:X509Certificate>
				</ds:X509Data>
			</ds:KeyInfo>
		</ds:Signature>
		<saml:Subject>
			<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" SPNameQualifier="Dropbox">f.castelli@ianum.com</saml:NameID>
			<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
				<saml:SubjectConfirmationData InResponseTo="id-035bc4bc48574b5585d1f43bc4069f6c" NotOnOrAfter="2019-10-18T09:04:56.358687+00:00" Recipient="https://www.dropbox.com/saml_login"></saml:SubjectConfirmationData>
			</saml:SubjectConfirmation>
		</saml:Subject>
		<saml:Conditions NotBefore="2019-10-18T08:46:56.358687+00:00" NotOnOrAfter="2019-10-18T09:04:56.358687+00:00">
			<saml:AudienceRestriction>
				<saml:Audience>Dropbox</saml:Audience>
			</saml:AudienceRestriction>
		</saml:Conditions>
		<saml:AuthnStatement AuthnInstant="2019-10-18T08:49:56.358687+00:00">
			<saml:AuthnContext>
				<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
			</saml:AuthnContext>
		</saml:AuthnStatement>
	</saml:Assertion>
</samlp:Response>

@mx-moth
Copy link
Owner

mx-moth commented Oct 18, 2019 via email

@fedecastelli
Copy link
Author

Dropbox doesn't provide the metadata file. I had to understand the entity_id starting from the SAMLRequest received. This is what I'm receiving from Dropbox:

<samlp:AuthnRequest
	xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0" IssueInstant="2019-10-18T09:15:13Z" ID="id-b84e1ee60fed4d1c91c6ee7c74ab578c" AssertionConsumerServiceURL="https://www.dropbox.com/saml_login">
	<saml:Issuer
		xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">Dropbox
	</saml:Issuer>
	<samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"/>
</samlp:AuthnRequest>

@mx-moth
Copy link
Owner

mx-moth commented Oct 18, 2019 via email

@fedecastelli
Copy link
Author

fedecastelli commented Oct 18, 2019

At the moment, I don't have any other information I can provide. I opened a ticket 1 week ago but they didn't reply to me yet.
I tried to validate the assertion using this online tool: https://www.samltool.com/validate_response.php but it can't verify it.

I also looked for information about Assertions and SAML responses for Dropbox. I was thinking that the problem could be <samlp instead of <samlp2 (by the way, I didn't find any settings in the repo to create an assertion with that tag)

As you can see, they don't even put the Destination in the SAMLRequest so I had to comment the part of the code in which you verify if the destination is correct or not.

@fedecastelli
Copy link
Author

I finally fixed the issue. It was related to the DigestMethod used and the url associated with it.
I could not use SHA-1 because it has been declared insecure and most of the Service Providers doesn't accept it. So I decided to use SHA-256 algorithm and I had to update this part of the signature XML

<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>

with the new algorithm used. The correct URL for SHA-256 algorithm is http://www.w3.org/2001/04/xmlenc#sha256.

After I fixed it, I discovered another issue: the date format. For example now a date is in this format 2019-10-18T08:49:56.358687+00:00 but it has to be in this format 2019-10-18T08:49:56.358Z. This is the code I'm using to get the correct format:

import datetime

issue_instant = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants