Tuesday, June 19, 2012

SAML Web SSO profile support in Apache CXF

Apache CXF has an impressive range of security features for JAX-RS endpoints. It also has excellent documentation in this space, see for example the JAX-RS documentation for OAuth, SAML Assertions and XML Encryption/Signature. Apache CXF 2.6.1 enhances the JAX-RS security story further by featuring support for the SAML 2.0 Web SSO profile.

The basic standard scenario for Web SSO involves a client browser accessing a secured (JAX-RS) endpoint. The endpoint constructs a SAML AuthnRequest and includes it in redirecting the browser to a Identity Provider (IDP) for authentication (via a dialog). The IDP constructs a SAML Response, and redirects the browser to a Request Assertion Consumer Service (RACS) URI contained in the AuthnRequest. The RACS validates the SAML Response and redirects the browser yet again to the original secured endpoint. The endpoint stores the session in a cookie (hence single sign-on) and access is granted to the resource. The following steps detail how to implement this scenario in Apache CXF using the new "cxf-rt-rs-security-sso-saml" module.

1) JAX-RS binding filters

The SAML 2.0 bindings specification defines HTTP redirect and HTTP POST bindings which can be used to "redirect" the client browser, e.g. from the secured endpoint to the IDP. Apache CXF 2.6.1 provides a separate JAX-RS filter to support these bindings. Therefore, the first step in securing a JAX-RS endpoint is to decide which of these two bindings to use. The SamlRedirectBindingFilter class providers support for the HTTP redirect binding, and the SamlPostBindingFilter provides support for the HTTP POST binding. Both of these filters share the following configuration properties.

1.1) Required Configuration Properties

Each filter implementation must be configured with the URL of the IDP, as well as the URL of the RACS. It must also be configured with a SPStateManager implementation to keep track of the Authenticated sessions. CXF ships with an EhCache based implementation:

The JAX-RS filters described above take care of creating a SAML AuthnRequest, optionally signing it, and redirecting the client browser to the IDP. The next step is to define a RequestAssertionConsumerService (RACS) which will intercept the SAML Response from the IDP. The RACS processes the SAML Response, and validates it in a number of ways:

The SAMLProtocolResponseValidator validates the Response against the specifications and checks the signature of the Response (if it exists), as well as doing the same for any child Assertion of the Response. It validates the status code of the Response as well.

If validation is successful the RACS redirects to the service provider endpoint.

2.1) Configuration properties shared with the filters

The RequestAssertionConsumerService
that ships with CXF shares a number of configuration properties with
the filters, mainly relating to state and signature configuration:

SPStateManager stateProvider - An object which keeps track of authenticated sessions. This is required.

long stateTimeToLive - The default value (in milliseconds) that a session is valid for. The default value is 2 minutes.

Crypto signatureCrypto - A WSS4J Crypto object to use to validate a signed Response.

String
signaturePropertiesFile - This points to a properties file that can be
used to load a Crypto instance for signature validation.

CallbackHandler callbackHandler - A CallbackHandler object to retrieve the private key password used to decrypt an encrypted request.

String callbackHandlerClass - A class name that is loaded for use as the CallbackHandler object.

Only the "stateProvider" property is required. Either the "signatureCrypto" or "signaturePropertiesFile" properties
must be set if you wish to support verifying signed Responses, or signed Assertions contained in a Response. Similarly, either
"callbackHandler" or "callbackHandlerClass" must be configured if you wish to support decrypting encrypted Assertions.

2.2) Additional Optional Configuration properties

The RACS supports the following additional (optional) configuration properties:

boolean supportDeflateEncoding - Whether Deflate encoding is used to inflate a token received via the Redirect binding. The default is true.

boolean supportBase64Encoding - Whether the token is Base64 decoded or not. The default is true.

boolean enforceAssertionsSigned - Whether the Assertions contained in a Response must be signed or not. The default is true.

boolean enforceKnownIssuer - Whether the Issuer of the Response (and child Assertions) is "known" to the RACS. This value is compared against the IDP URL configured on the filter. The default value is true.

TokenReplayCache<String> replayCache - A TokenReplayCache implementation to store Assertion ID's for the POST binding to guard against replay attacks. The default uses an implementation based on EhCache.

2.4) Sample Spring Configuration

Here is a sample spring configuration extract to set up a RACS, that could be used with the filter configuration in section 1.4:

The remaining piece of the puzzle is the Identity Provider (IDP) which receives the SAML AuthnRequest from the service provider, processes it accordingly, and then interacts with the client browser to authenticate the client. It then creates a SAML Response and redirects the client browser to the RACS defined in the AuthnRequest. Apache CXF does not (yet) ship with an IDP, although this may change in the near future. However, there are a number of open-source IDPs that can be used with a CXF JAX-RS endpoint that supports SAML Web SSO. These include Shibboleth, PicketLink, OpenAM, JOSSO, etc. I have tested against all of these products. Report any interop issues to the CXF JIRA.

4) Ongoing Development

SAML Web SSO profile support is still being actively developed. A number of bugs have been fixed that do not yet appear in a released version of CXF. For example, support for decrypting encrypted Assertions in a SAML Response, and some bugs relating to signed Assertions (CXF-4352 and CXF-4365).

10 comments:

Hi, Thank you for the article!Using Shibboleth, When secured cxf rs service is called from a browser, it does redirects to IDP site with login and password. Once authenticated IDP does not seems to redirect back to RACS. Can you please provide some idea on how this can be debugged or is there any missing piece you suggest to look at.Thank you.Susil

If the Shibboleth IDP is not redirecting back to the RACS then I suggest you take a look at the Shibboleth logs to see what is going wrong.

There are a number of steps you have to follow to get Shibboleth working with a CXF JAX-RS endpoint:

a) Add MetadataProvider configuration for the CXF endpoint in the Shibboleth "relying-party.xml" configuration.b) Look for the "ProfileConfiguration" of type "saml:SAML2SSOProfile" in "relying-party.xml" and change the "encryptAssertions" attributefrom "conditional" to "never" (this step is optional from CXF 2.6.2 onwards).c) Edit "attribute-filter.xml" and look for "AttributeFilterPolicy". Add the following:

You don't need to set the IDP metadata information on the service provider side...just have the correct idp service address ("http://localhost:8080/opensso/SSORedirect/metaAlias/idp") worked for me when testing with OpenAM. You do however need to add metadata for the service provider to OpenAM. Please redirect all future questions to the CXF user mailing list instead of here.

Thanks Colm. I was able to finish it (though i am updating a bit too late)I have checked in the code in github(https://github.com/SaurabhMIttal/SingleSignOn) so that it may help people reading this nice blog in future

"If validation is successful the RACS redirects to the service provider endpoint. "What happen if the service provider endpoint was called with POST and the service provider is able to serve only POST request? What I got is HTTP/1.1 405 Method Not Allowed

About Me

Security architect at Talend, security expert at ASF. Active committer on lots of Apache projects such as Apache Santuario, CXF, Camel, Syncope, WSS4J, Directory, Sentry, Ranger, etc. In what seems like another lifetime, I also acquired a PhD in the area of cryptography.
The views expressed on this site are mine alone and do not necessarily reflect the views of my employer.