SSO and Federated Identify Management

SSO, or Single Signon, is a way for organizations to centralize their identity management and authentication needs in a consolidated, single solution across multiple applications in the enterprise. There are quite a few solutions available to enterprise to implement SSO with. Jetspeed classifies SSO in two categories:

  • Jetspeed SSO
  • External Identity Management Solutions

The first, Jetspeed SSO, is a rather simpler solution for enterprise applications who do not need the complexity of a robust identity management SSO solution. In this case, Jetspeed provides a credential store for user credentials. Jetspeed can store encrypted credentials for users or groups of users to external sites. The second solution requires a third party open source project or product. In this case, Jetspeed integrates with an external SSO solution. These external solutions can often a single-signon solution for an organization, or even a federation of organizations.

Jetspeed SSO

Jetspeed SSO uses Jetspeed and Java security to implement a set of services and portlets for storing credentials. A management administrative portlet allows the editing of SSO sites and remote credentials. Jetspeed SSO comes with a secure IFrame and Web Content set of portlets. These portlets allow you to secure access to external sites. Authentication suport includes:

  • Basic authentication is the default and can be supported effectively without even setting the sso.type preference. Simply provide credentials for the domain, and basic authentication defaults. The credentials will not be sent preemptively, but if a 401 request is returned for Basic authentication, it will be handled properly. This is equivalent to setting the preference sso.type=basic (or sso.type=html (old - now deprecated in favor of calling it basic). if you set sso.type=basic.preemptive, it will send the credentials preemptively.
  • URL authentication (query args) is supported as sso.type=url or sso.type=url.base64. By definition, this type of authentication is preemptive, so no distinction is made there.
  • Form-authentication is supported with sso.type=form (which is equivalent to sso.type=form.post - you can also specify sso.type=form.get, if GET protocol is used on the login form). This form also requires a bunch of other data ( e.g. the action URL, other args, names of the fields for credentials, etc.). All of this is in an example that is in the demo portlet.xml. Form-based authentication is also considred "preemptive", in that it authenticates before any other content is read. However, it only does it once. If it succeeds, all should be well. If it fails, the user will have to login by hand (since the initial content URL will cause a redirect to the login page).
  • Here are some examples of preferences that can be set for the SSO IFrame and SSO Content portlets:
                <preference>
                    <name>sso.type</name>
                    <value>basic | url | form</value>
                </preference>
                <preference>
                    <name>sso.url.Principal</name>
                    <value>sso-principal</value>
                </preference>
                <preference>
                    <name>sso.url.Credential</name>
                    <value>sso-credential</value>
                </preference>            
                <preference>
                    <name>SRC</name>
                    <value>http://www.nytimes.com</value>
                </preference>
                <preference>
                    <name>sso.type</name>
                    <value>form</value>
                </preference>
                <preference>
                    <name>sso.form.Action</name>
                    <value>http://www.nytimes.com/auth/login</value>
                </preference>
                <preference>
                    <name>sso.form.Principal</name>
                    <value>USERID</value>
                </preference>
                <preference>
                    <name>sso.form.Credential</name>
                    <value>PASSWORD</value>
                </preference>
                <preference>
                    <name>sso.form.Args</name>
                    <value>Submit2=Log In;OP=;OQ=;is_continue=false</value>
                </preference>
    

Integrating with External SSO

To enable an identity management service, such as Site Minder, or Shibbboleth (see below), there are some general guidelines for integrating your SSO solution with Jetspeed. remove the Login Portlet from the custom build and delegate authentication to the authentication provider. Upon successful authentication, redirect to the portal.

  1. Remove the Login Portlet from your custom home page. You will no longer need it. The third party SSO will handle all authentication. You will need to configure the third party SSO to redirect to the Jetspeed portal upon successful authentication. All authentication activities are removed from Jetspeed.
  2. Modify the Jetspeed web.xml to include any required settings for your SSO solution. You might need to enable this filter and mapping:
    			
      <filter>
        <filter-name>PortalFilter</filter-name>
        <filter-class>org.apache.jetspeed.login.filter.PortalFilter</filter-class>   
      </filter>
      <filter-mapping>
        <filter-name>PortalFilter</filter-name>
        <url-pattern>/*</url-pattern>    
      </filter-mapping>  
    
  3. Additional edits to the Jetspeed web.xml recommended:
    • remove security-config for the login portlet
      							
        <login-config>
          <auth-method>FORM</auth-method>
          <realm-name>Jetspeed</realm-name>
          <form-login-config>
            <form-login-page>/login/login</form-login-page>
            <form-error-page>/login/error</form-error-page>
          </form-login-config>
        </login-config>
      
    • Remove the servlets: LoginProxyServlet, LoginServlet, LoginErrorServlet, LoginRedirectorServlet and LogoutServlet
    • Remove the servlet-mappings for the above servlets

Shibboleth

Jetspeed comes with a Shibboleth filter for performing Single Sign-on (SSO) with Shibboleth and the Jetspeed Portal. Shibboleth's Service Provider provides HTTP request headers. The filter reads and interprets the Shibboleth headers as single sign-on tokens. Shibboleth can also be configured to provide various user attributes that can be passed onto the portal. Refer to your Shibboleth documentation for more details. The Jetspeed Shiboleth filter is configured in the Jetspeed web.xml:

<filter>
    <filter-name>ShibbolethPortalFilter</filter-name>
    <filter-class>org.apache.jetspeed.security.impl.shibboleth.ShibbolethPortalFilter
    </filter-class>   
</filter>

If there are no Shibboleth headers present, Jetspeed will not authenticate the user. If there are Shibboleth tokens on the HTTP request, Jetspeed will use them and automatically authenticate users, bypassing Jetspeed's internal authentication and login mechanisms.

To configure Jetspeed to use Shibboleth headers, there is a Spring configuration file found under WEB-INF/assembly/alternate/shibboleth.xml:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="org.apache.jetspeed.security.shibboleth.ShibbolethConfiguration"
 class="org.apache.jetspeed.security.impl.shibboleth.ShibbolethConfiguration">
    <!-- map of common jetspeed-security principals to shibboleth headers -->
    <constructor-arg index='0'>
      <map>
        <entry key='username'>
          <value>shib-person-commonname</value>
        </entry>
	  </map>
	</constructor-arg>
	<!-- Always authenticate against Jetspeed (should be false if your jetspeed db != authentication users) -->
    <constructor-arg index='1'>
       <value type="boolean">true</value>    
	</constructor-arg>
    <constructor-arg index='2'>
	 	<ref bean="PortalConfiguration" />
	</constructor-arg>
  </bean>
</beans>

The first constructor argument is a map of common jetspeed security names. Currently we only support mapping the username from a Shibboleth principal. It is configured to map to the Shibboleth header/attribute named sub-person-commonname.

The second constructor turns on or off Jetspeed authentication. Turn this off if you simply want to trust Shibboleth or if you don't have passwords available in constructor-arg one.

CAS

The Central Authentication Service, CAS, is a single sign-on protocol for the web. Like other Single Sign-on systems (SSO), its purpose is to permit a user to access multiple applications while providing their credentials (such as userid and password) only once. It also allows web applications to authenticate users without gaining access to a user's security credentials, such as a password.

Jetspeed is distributed with a CAS servlet filter for performing Single Sign-on (SSO) with CAS and the Jetspeed Portal. CAS must first be installed into your application server. Once it is installed and configured, users can login via CAS. When they go to visit any Jetspeed pages, Jetspeed can check to see if CAS has successfully authenticated. If CAS has authenticated, Jetspeed participates in CAS SSO, by using the identity provided by CAS internally. The following sections describe how to configure Jetspeed with CAS.

Configuring the CAS Filter

Be sure to configure your application server with CAS here as described here: Configuring CAS with Java. Once you have configured the application server with CAS and verified that is working, then continue with the Jetpeed configuration instructions here. The CAS filter is configured in Jetspeed's web.xml. You will need to add the following lines to the web.xml. The CAS Filter should be placed in the web.xml before the Jetspeed Portal Filter. Note that the init-params values will be specific to your deployment. We provide some localhost examples here:

<filter>
   <filter-name>CAS Filter</filter-name>
   <filter-class>edu.yale.its.tp.cas.client.filter.CASFilter</filter-class>
   <init-param>
       <param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name>
       <param-value>http://localhost/login</param-value>			
   </init-param> 
   <init-param>
       <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>
       <param-value>http://localhost/serviceValidate</param-value>
   </init-param>
   <init-param>
       <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>
       <param-value>localhost</param-value>
   </init-param>
</filter>

Make sure to add the CAS filter mapping to your web.xml as well:

	<filter-mapping>
		<filter-name>CAS Filter</filter-name>
		<url-pattern>/portal/caslogin/*</url-pattern>
	</filter-mapping> 

Configuring the Jetspeed CAS Portal Filter

The Jetspeed CAS Portal filter reads and interprets the CAS session state to participate in CAS SSO. The Jetspeed CAS Portal filter is configured in Jetspeed's web.xml. You will need to add the following lines to the web.xml. Make sure to place the filter after(below) the CAS Filter described above.

  <filter>
    <filter-name>PortalFilter</filter-name>
    <filter-class>org.apache.jetspeed.security.impl.cas.CASPortalFilter</filter-class>   
  </filter>

Make sure to add the filter mapping to your web.xml as well:

    <filter-mapping>
      <filter-name>PortalFilter</filter-name>
      <url-pattern>/portal/*</url-pattern>    
    </filter-mapping> 

If there is no CAS session state, Jetspeed will not authenticate the user. If there is CAS session state, Jetspeed will use them and automatically authenticate users, bypassing Jetspeed's internal authentication and login mechanisms.

Logging out

To enable CAS session logout, add the following init parameter to the Jetspeed Logout Servlet in Jetspeed's web.xml. Note the param value will be specific to your CAS configuration.

 <servlet>
    <servlet-name>LogoutServlet</servlet-name>
    <servlet-class>org.apache.jetspeed.login.LogoutServlet</servlet-class>
    <init-param>
     <param-name>casLogoutUrl</param-name>
     <param-value>http://localhost/logout</param-value>
   </init-param> 
  </servlet>