Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Wiki Markup
{span:style=font-size:2em;font-weight:bold} JAX-RS: SAML Web SSO{span}


{toc}

h1. Introduction

[SSO|http://en.wikipedia.org/wiki/Single_sign-on] is about a user having to sign in only once when interacting with a custom web application which may offer of a number of individual endpoints. 

CXF 2.6.1 introduces a comprehensive service provider (SP) support for the SAML Web SSO [profile|http://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf]. This [page|http://en.wikipedia.org/wiki/SAML_2.0] also offers a good overview of the [profile|http://en.wikipedia.org/wiki/SAML_2.0#Web_Browser_SSO_Profile].

HTTP Redirect(via GET) and POST bindings are supported. The module has been tested against many IDP providers and is easily configurable.

The following components are required to get SSO supported:

- Identity Provider (IDP) supporting SAML SSO
- Request Assertion Consumer Service (RACS)
- Service Provider Security Filter
- SSO State Provider

The following sections will describe these components in more details

h2. Typical Flow

Typically, the following flow represents the way SAML SSO is enforced:

1. User accesses a custom application for the first time
2. Service Provider Security Filter checks if the security context is available 
   and redirects the user to IDP with a SAML SSO request
3. IDP challenges the user with the authentication dialog and redirects the user to
   Request Assertion Consumer Service (RACS) after the user has authenticated
4. RACS validates the response from IDP, establishes a security context and redirects the user 
   to the original application endpoint
5. Service Provider Security Filter enforces that a valid security context is available and lets the user
   access the custom application.

h1. Maven dependencies

{code:xml}
<dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-rs-security-sso-saml</artifactId>
  <version>2.6.1</version>
</dependency>
{code}

h1. Identity Provider

Identity Provider (IDP) is the service which accepts the redirect requests from application security filters, authenticates users and redirects them back to Request Assertion Security Service.

CXF does not offer its own IDP SAML Web SSO implementation but might provide it in the future as part of the [Fediz|http://cxf.apache.org/fediz.html] project.

However, CXF has been tested against a number of popular IDP implementations which support SAML SSO and thus should be interoperable with whatever IDP is being used in the specific production environment. The interoperability tests have shown that some IDPs may process SAML request and produce SAML response data the way which may not be exactly specification-compliant and thus CXF Request Assertion Consumer Service (RACS) and Service Provider Security Filter implementations have a number of configuration properties for adjusting the way SAML requests to IDP are prepared and SAML responsedresponses from IDP are processed.

h1. Service Provider Security Filter

SP Security Filter protects the application endpoints by checking that a valid SSO security context is available. Application Security Filter If it is then the filter lets the request to continue, if not then it redirects the current user to IDP.

CXF offers two SP Security filters, one for redirecting the user back to IDP via GET and another one - via POST.

h2. Redirect Binding Filter

Redirect Binding Filter is implemented by org.apache.cxf.rs.security.saml.sso.SamlRedirectBindingFilter.

Here is an example of a typical filter protecting a custom JAX-RS endpoint:
{code:xml}
<bean id="serviceBean" class="org.apache.cxf.samlp.sso.BookStore"/>

<jaxrs:server address="/app1"> 
       <jaxrs:serviceBeans>
          <ref bean="serviceBean"/>
       </jaxrs:serviceBeans>
       <jaxrs:providers>
          <ref bean="redirectGetFilter"/>
       </jaxrs:providers>
</jaxrs:server>

<bean id="redirectGetFilter" class="org.apache.cxf.rs.security.saml.sso.SamlRedirectBindingFilter">
      <property name="idpServiceAddress" value="https://localhost:9443/idp"/>
      <!-- both relative and absolute URIs are supported -->
      <property name="assertionConsumerServiceAddress" value="/racs/sso"/>
      <property name="stateProvider" ref="stateManager"/>
</bean>


<bean id="stateManager" class="org.apache.cxf.rs.security.saml.sso.state.EHCacheSPStateManager">
    <constructor-arg ref="cxf"/>
</bean>

{code}

Note that at the very minimum the filter needs to have 3 properties set-up:
1. IDP service address
2. RACS address - it can be absolute or relative if RACS is collocated 
  (shares the same web application context) with the application endpoint.
3. Reference to SSO State Provider.

h2. POST Binding Filter

POST Binding Filter is implemented by org.apache.cxf.rs.security.saml.sso.SamlPostBindingFilter.

Here is an example of a typical filter protecting a custom JAX-RS endpoint.
{code:xml}
<bean id="serviceBean" class="org.apache.cxf.samlp.sso.BookStore"/>
<jaxrs:server address="/app2"> 
    <jaxrs:serviceBeans>
       <ref bean="serviceBean"/>
     </jaxrs:serviceBeans>
     <jaxrs:providers>
          <ref bean="ssoRedirectPOST"/>
          <ref bean="samlRequestFormCreator"/> 
     </jaxrs:providers>
       
</jaxrs:server>

<bean id="ssoRedirectPOST" class="org.apache.cxf.rs.security.saml.sso.SamlPostBindingFilter">
        <property name="idpServiceAddress" value="https://localhost:9443/idp"/>
        <property name="assertionConsumerServiceAddress" value="/racs/sso"/>
        <property name="stateProvider" ref="stateManager"/>

        <property name="useDeflateEncoding" value="true"/>
</bean

<bean id="samlRequestFormCreator" class="org.apache.cxf.jaxrs.provider.RequestDispatcherProvider">
      <property name="dispatcherName" value="jsp"/>
      <property name="useClassNames" value="true"/>
</bean>
    
<bean id="stateManager" class="org.apache.cxf.rs.security.saml.sso.state.EHCacheSPStateManager">
    <constructor-arg ref="cxf"/>
</bean>


{code}

Note that the POST binding filter has the same base properties as org.apache.cxf.rs.security.saml.sso.SamlRedirectBindingFilter has but also 
sets a "useDeflateEncoding" property for getting a SAML request deflated. Some IDPs might not be able to process deflated SAML requests with POST binding redirects thus the compression may be optionally disabled.

What is actually different in this case from the GET-based redirect is that the filter prepares an instance of [SAMLRequestInfo|http://svn.apache.org/repos/asf/cxf/trunk/rt/rs/security/sso/saml/src/main/java/org/apache/cxf/rs/security/saml/sso/SamlRequestInfo.java] which is subsequently bound to an XHTML view via a JSP filter. The view will typically have a Java Script handler which will actually redirect the user to IDP when it is loaded into the browser. The data to view binding is facilitated by org.apache.cxf.jaxrs.provider.RequestDispatcherProvider, please see [this page|http://cxf.apache.org/docs/jax-rs-redirection.html#JAX-RSRedirection-WithRequestDispatcherProvider] for more information.
Here is a typical JSP handler for binding org.apache.cxf.rs.security.saml.sso.SAMLRequestInfo to the view:

{code:xml}
<%@ page import="javax.servlet.http.HttpServletRequest,org.apache.cxf.rs.security.saml.sso.SamlRequestInfo" %>

<%
    SamlRequestInfo data = (SamlRequestInfo)request.getAttribute("samlrequestinfo");
%>
<html xmlns="http://www.w3.org/1999/xhtml">
<body onLoad="document.forms[0].submit();">
   <form action="<%= data.getIdpServiceAddress() %>" method="POST">
       <div>             
        <input type="hidden" name="SAMLRequest"
                value="<%= data.getSamlRequest() %>"/>
        <input type="hidden" name="RelayState"
                value="<%= data.getRelayState() %>"/>
       </div>
        <div>
         <input type="submit" value="Continue"/>
       </div>
   </form>
 
</body>
</html>
{code}


h1. Request Assertion Security Service

h1. SSO State Provider