Saturday, May 20, 2017

Decrypting a SAML Assertion in OpenSAML v3

As you probably should know at this point, the SAML Assertion contains the description of a authenticated user and how it was autheunticitoted. The assertion is generally signed to prevent manipulation but there are also cases where you would want to encrypt the assertion to prevent someone to see the information within. For example the assertion can be used to communicate personal information about the user such as social security number and adress.

As most people reading my blog seem to be on the SP side of SAML I will explain how to decrypt an assertion.

The general method of encryption and subsequent decryption of a assertion uses two keys, one symetric and on asymetric.
The symtric key is generated during encryption and used to encrypt the actual assertion data. A  asymetric key, generally a SP key contained in the metadata, is then used to encrypt the symetric key which is then stored in the XML together with the ecrypted assertion.

TestIDP




TestIDP












THE ENCRYPTED SYMMETRIC KEY




THE ASSERTION ENCRYPTED USING THE SYMMETRIC KEY





To decrypt the reverse of this is done. The asymmetric is used to decrypt the symmetric key, which is then used to decrypt the assertion.

Now for the OpenSAML part.

First we get the assertion from the XML. The assertion is stored in a EncryptedAssertion object and is retrieved with the method getEncryptedAssertions() on the response instead of getAssertions() which is used otherwise.

StaticKeyInfoCredentialResolver keyInfoCredentialResolver = new StaticKeyInfoCredentialResolver(SPCredentials.getCredential());

Decrypter decrypter = new Decrypter(null, keyInfoCredentialResolver, new InlineEncryptedKeyResolver());
decrypter.setRootInNewDocument(true);

decrypter.decrypt(encryptedAssertion);

In this example a StaticKeyInfoCredentialResolver is used to point out the key that is used for decryption, in this case I have stored it in the static class SPCredentials. The InlineEncryptedKeyResolver is used to tell the decryptor that the symmetric encryption key can be found in the XML next to the encrypted assertion.

The decryptor returns a decrypted Assertion object.


TestIDP












UDJ762cOSK14nBjbFCq9a47x3WgSCJ1qZpeBYKdy5s0=



syb20Rjh1pDJTc6CY1nN3x1v8WNlG9lRf71A5ik3i97/A+q0NZCvoJLEBVM73K/U8hxo/hbHOmBs
7KkF4g3yYLVunRlm/tapnTESKqZ8v8SJZQcbY4xMzi0PUxiUJKBugiho114ijDPAYs+U1UZhXGHL
zyHVd7XJYoOATKVdh3U=



Some NameID value






http://localhost:8080/webprofile-ref-project/sp/consumer




bob


999999999




urn:oasis:names:tc:SAML:2.0:ac:classes:Smartcard




Wednesday, August 10, 2016

Signing and sending AuthnRequests in OpenSAML V3

Signing and sending a AuthnRequest in OpenSAML V3 is forutunatly not that different from how it was done in OpenSAML V2.

As described in this post on AuthnRequests OpenSAML V2, the AuthnRequest is the SAML request that starts a typical SSO authentication process. This is the SP requesting the IDP to authenticate a user.

As in V2 the HTTPRedirectDeflateEncoder is used, the main difference lays in the message context.

One of the major changes between V2 and V3 is the message contexts. I V2 the message contexts where basically one object containing general properties about the message and its destination. In V3 the message context concept has been expanded to be more flexible contain more information. In the new context structure there is a context object per purpose.

In my book A Guide to OpenSAML V3 I cover the use of the new message contexts in detail.

To sign and send a AuthnRequest, three contexts are needed.

The main context is created and the AuthnRequest is set.
MessageContext context = new MessageContext();
context.setMessage(authnRequest);

The SAMLPeerEntityContext and SAMLEndpointContext are created and configured to point to the endpoint of the message.
SAMLPeerEntityContext peerEntityContext = context.getSubcontext(SAMLPeerEntityContext.class, true);
SAMLEndpointContext endpointContext = peerEntityContext.getSubcontext(SAMLEndpointContext.class, true);
endpointContext.setEndpoint(idpEndpoint);

Next, the security parameters context is created and populated with signing information
SignatureSigningParameters signatureSigningParameters = new SignatureSigningParameters();
signatureSigningParameters.setSigningCredential(SPCredentials.getCredential());
signatureSigningParameters.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
context.getSubcontext(SecurityParametersContext.class, true).setSignatureSigningParameters(signatureSigningParameters);

Next, the HTTPRedirectDeflateEncoder is created and populated with context and the http request object.
HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
encoder.setMessageContext(context);
encoder.setHttpServletResponse(httpServletResponse);

Lastly the encoder is initialized and the message is encoded
encoder.initialize();
encoder.encode();

For more detailed information on AuthnRequest, message context and all the new stuff in OpenSAML V3, please consider buying my book A Guide to OpenSAML V3.
A Guide to OpenSAML V3

Verifying signatures with OpenSAML v3

Here is the happy news of the day. Verifying a signature in OpenSAML V3 is done almost identical to how it is done in V2, so the blog post on the process from OpenSAML V2 is still very much relevant and worth checking out.

The only difference between the two version is that the SignatureValidator is no longer instantiated. Instead the validate method of SignatureValidator is now static and takes both the credentials and the signature object.

Below is the code for verifying signatures in OpenSAML V3
SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
profileValidator.validate(assertion.getSignature());
SignatureValidator.validate(assertion.getSignature(), cred);

Thursday, June 23, 2016

New book release: OpenSAML version 3

As many of you know, version 2 of OpenSAML will officially reach its end of life at July 31 of 2016. This means that the library will not be receiving any new updates, not even critical security updates.

Because of this, everyone currently using version 2 of OpenSAML is strongly advised to migrate to OpenSAML version 3.

In light of this, I have done a fair amount of research on version 3 and am now releasing a new edition of A Guide to OpenSAML.

The new edition includes:
  • Sample project updated for V3
  • Updated code and explanatory text
  • New chapters on message handlers and message contexts
  • A rudimentary migration guide from V2 to V3 (based on changes needed in the sample project)
For the convenience of those of you that have read my previous book and are just migrating to V3, I have provided a chapter in the beginning, summarising all the changes since the last edition.


Monday, April 25, 2016

OpenSAML V3 Javadocs

So, as those of you working with OpenSAML probably have noticed, the version 2 of the OpenSAML library is closing in on its end of life. After July 31st no more security maintenance will be done at this version. Those using is asked to move to version 3 of the library.

I have had many questions on how to use the new version and unfortunately the documentation is not yet produced. I have started to dig into it and will post what I find out.

The first thing I noticed was a structure change in the maven setup. The library have been divided into many submodules as listed below. This makes the Javadoc a bit more hard to find but below are links the the javadoc for each module.

I hope this is of help.


The combined version Java doc is availible here
Java docs

Wednesday, October 28, 2015

SAML Chrome Extension Published!

I have been working with SAML for a while now and I have always used Firefox for debugging instead of my favorite browser, Chrome. Why? you ask. Because there is a plugin called SAML tracer on firefox that is excellent for viewing the SAML messages going across the browser. There have been no such plugin for Chrome.

Finally I have decided to take things into my own hands and build one.

And now it's done! SAML DevTools extension


Feature summary

  • The extension adds a panel to the Developer Tools
  • Shows all network requests for the current window
  • SAML requests are highlighted in green for usability
  • Can filter out SAML requests
  • Show request and response details
  • Displays syntax highlighted SAML message
  • Custom syntax highlighting for SAML to allow for easier reading

Wednesday, July 15, 2015

Adding KeyInfo to a SAML message

When a message is signed with a private key, the receiving end will need to verify the message using the corresponding public key/certificate. But in order to do this, the receiving end must have the certificate.

The certificate is transported in encoded form in a KeyInfo element. Below is a example


        
          MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==
        
      


There are many ways to give the receiving end the certificate. Two common methods is metadata and in the message.

When using the metadata method the KeyInfo object is embedded in the metadata inside the KeyDescriptor element. When attaching KeyInfo to the SAML message the element is embedded in the Signature object.

To create and add a KeyInfo object and add it to a SAML message signature, add this call to SecurityHelper before generating the signature.

SecurityHelper.prepareSignatureParams(signature, IDPCredentials.getCredential(),
                    Configuration.getGlobalSecurityConfiguration(), null);
This helper method does not only add a the key info but it also sets the

  • signature algorithm URI
  • canonicalization algorithm URI
  • and HMAC output length (if applicable and a value is configured)

Customising the KeyInfo

The above statement only uses the default configuration of for generating KeyInfo. To customise the KeyInfo you create your own instance of KeyInfoGeneratorFactory, set it up as preferred and use it in the statement. 
The example below shows how to use a X509KeyInfoGeneratorFactory to create a KeyInfo with properties from the X509 certificate used as credential.

X509KeyInfoGeneratorFactory x509Factory = new X509KeyInfoGeneratorFactory();
x509Factory.setEmitEntityCertificate(true);
x509Factory.setEmitEntityCertificateChain(true);
x509Factory.setEmitX509IssuerSerial(true);
x509Factory.setEmitX509SubjectName(true);

Configuration.getGlobalSecurityConfiguration().getKeyInfoGeneratorManager().registerFactory("x509emitingKeyInfoGenerator", x509Factory);

SecurityHelper.prepareSignatureParams(signature, SPCredentials.getCredential(), null,  "x509emitingKeyInfoGenerator");