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

Support for EncryptedAssertion #9172

Closed
nicolas-semaphor opened this issue Apr 8, 2024 · 6 comments
Closed

Support for EncryptedAssertion #9172

nicolas-semaphor opened this issue Apr 8, 2024 · 6 comments
Labels
enhancement New feature or request

Comments

@nicolas-semaphor
Copy link
Contributor

nicolas-semaphor commented Apr 8, 2024

Is your feature request related to a problem? Please describe.
Some SAML IdP's will deny your SAMLRequest if you do not require the Assertion to be encrypted in the SAMLResponse. I would like to add support for requiring and supporting the EncryptedAssertion element when setting up SAML Federation sources.

Describe the solution you'd like
A "simple" solution would be adding the option to use the signing key-pair for encryption and decryption when creating a SAML source. When enabled the metadata should be updated with an encryption Key Descriptor:

    def get_encryption_key_descriptor(self) -> Optional[Element]:
        """Get Encryption KeyDescriptor, if enabled for the source"""
        if self.want_assertions_encrypted:
            key_descriptor = Element(f"{{{NS_SAML_METADATA}}}KeyDescriptor")
            key_descriptor.attrib["use"] = "encryption"
            key_info = SubElement(key_descriptor, f"{{{NS_SIGNATURE}}}KeyInfo")
            x509_data = SubElement(key_info, f"{{{NS_SIGNATURE}}}X509Data")
            x509_certificate = SubElement(x509_data, f"{{{NS_SIGNATURE}}}X509Certificate")
            x509_certificate.text = strip_pem_header(
                self.source.signing_kp.certificate_data.replace("\r", "")
            ).replace("\n", "")
            return key_descriptor
        return None

When the SAMLResponse is received it should then contain an "EncryptedAssertion" element in the EncryptedData section. This needs to be decrypted, one could go about it this way:

    def _decrypt_response(self):
        """Decrypt SAMLResponse EncryptedAssertion Element"""
        
        manager = xmlsec.KeysManager()
        key = xmlsec.Key.from_memory(
            self._source.signing_kp.key_data,
            xmlsec.constants.KeyDataFormatPem,
        )
        
        manager.add_key(key)
        encryption_context = xmlsec.EncryptionContext(manager)
        
        encrypted_assertion = self._root.find(".//{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedAssertion")
        encrypted_data = xmlsec.tree.find_child(encrypted_assertion, "EncryptedData", xmlsec.constants.EncNs) 
        decrypted_assertion = encryption_context.decrypt(encrypted_data)

        
        index_of = self._root.index(encrypted_assertion)
        self._root.remove(encrypted_assertion)
        self._root.insert(
                index_of,
                decrypted_assertion,
        )

After the EncryptedAssertion element has been decrypted and replaced by the decrypted Assertion element, the flow should be able to continue as normal. I've tested the above to work but it is a "raw" implementation.

Describe alternatives you've considered
An alternate solution could be to make use of Authentiks API and maybe use something like OneLogins Ruby-SAML library (which has support for Encrypted Assertions) to federate and create users, but off course I would like to stick with the Python implementation. Maybe what I describe above is related to Outposts, but I'm not entirely certain.

@nicolas-semaphor nicolas-semaphor added the enhancement New feature or request label Apr 8, 2024
@janhalen
Copy link

janhalen commented Apr 9, 2024

This is a requirement for our Open Source foundation to adopt Authentik as our IDP middleware for our modern application portfolio.

What can i do to help move this along?

@janhalen
Copy link

janhalen commented Apr 12, 2024

@BeryJu: To move things along, I will fork the code into a repo under our foundations sandbox org. then @nicolas-semaphor can add the changes we have made and maybe make it easier to understand and test the proposed changes, eventually leading up to a PR.

Heres the fork: https://github.com/OS2sandbox/sandbox-myndighedsidentitet-authentik

Next time @nicolas-semaphor has a timeslot for the project, the code can be merged into the fork..

@janhalen
Copy link

First bit of code is comitted to this branch: https://github.com/OS2sandbox/sandbox-myndighedsidentitet-authentik/tree/9172-backend-support-for-encrypted-assertions.

Comments and suggestions are welcome. Its a bit hard to get answers from the maintainers at the moment, but in this was we can openly collaborate on a PR in a seperate fork, before submitting it..

@janhalen
Copy link

This will contain the backend code, for it to be configurable in the UI, more work should be done outside of this issue.

@nicolas-semaphor
Copy link
Contributor Author

I have submitted a PR: #10099

@BeryJu
Copy link
Member

BeryJu commented Aug 22, 2024

fully closed by #10934, both PRs will be included in 2024.8

@BeryJu BeryJu closed this as completed Aug 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants