Seam Identity Integration (Seam 1.2.1 - 2.0.0)

This page describes how to integrate Seam's Identity component (a.k.a - Seam Security) with a CAS Server.  My approach is based on the Yale CAS Client distribution. See also here and here

1.  web.xml
Configure your web.xml as directed in the Yale CAS Client distribution docs to use CAS for login and logout.

Login Block
<!-- CAS Authentication Filter (Login) -->
   <filter>
     <filter-name>CASFilter</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>https://YOUR_CAS_SERVER_HOST_ADDRESS_HERE/cas/login</param-value>
     </init-param>
     <init-param>
       <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>
       <param-value>https://YOUR_CAS_SERVER_HOST_ADDRESS_HERE/cas/serviceValidate</param-value>
     </init-param>

     <init-param>
       <param-name>edu.yale.its.tp.cas.client.filter.wrapRequest</param-name>
       <param-value>true</param-value>
     </init-param>

    </filter>
Logout Block
<!-- CAS Logout Filter and Logout Mapping-->
  <filter>
    <filter-name>LogoutFilter</filter-name>
    <filter-class>edu.yale.its.tp.cas.client.filter.LogoutFilter</filter-class>
    <init-param>
      <param-name>edu.yale.its.tp.cas.client.filter.logoutUrl</param-name>
      <param-value>https://YOUR_CAS_SERVER_HOST_ADDRESS_HERE/cas/logout</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>LogoutFilter</filter-name>
    <url-pattern>/logout/*</url-pattern>
  </filter-mapping>

2. Write a Seam-Identity authenticator class / component:

Sample Seam Identity Authenticator
@Name("ssoAuthenticator")
@Scope(ScopeType.SESSION)
public class SSOAuthenticator {

    @Logger
    private Log log;

    private UserPrincipal userPrincipal;

    // see http://www.jboss.com/index.html?module=bb&op=viewtopic&t=119167
    // This method is configured in pages.xml as an action called for all pages:
    // 	<page view-id="/*" login-required="true" action="#{authenticator.checkLogin}"/>
    public void checkLogin() {
        final boolean isLoggedIn = Identity.instance().isLoggedIn();
        // user may already be logged in - check
        if (isLoggedIn) {
          return;
        }
        authenticate();
    }

    public boolean authenticate() {
        Identity identity = Identity.instance();
        boolean authenticated = !(userPrincipal == null);
        if (!authenticated) {
            try {
                // Obtain authenticated UserPrincipal from Servlet container
                FacesContext facesContext = FacesContext.getCurrentInstance();
                Principal rawPrincipal = facesContext.getExternalContext().getUserPrincipal();
                userPrincipal = (UserPrincipal) rawPrincipal;

                // trigger the identity login sequence and add roles
                if (userPrincipal != null) {
                    // Identity must have 'fresh' credentials for authenticat() call to proceed
                    identity.setUsername(userPrincipal.getUserid());
                    identity.setPassword(userPrincipal.getUserid());
                    identity.authenticate();
                    // in my case, our system makes roles available in the UserPrincipal,
                    // do what is right for your system
                    Group[] roleGroups = userPrincipal.getUserRoles();
                    if (roleGroups != null) {
                        for (Group group : userPrincipal.getUserRoles()) {
                            Enumeration<? extends Principal> roles = group.members();
                            while (roles.hasMoreElements()) {
                                identity.addRole(roles.nextElement().getName());
                            }
                        }
                    }
                    authenticated = true;
                }
            } catch (Exception e) {
                log.error(e, e);
            }
        }
        return authenticated;
    }
}

2. pages.xml
Configure Seam's pages.xml file in your web app to use your authenticator.

<?xml version="1.0" encoding="UTF-8"?>
<pages xmlns="http://jboss.com/products/seam/pages"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.0.xsd"

       no-conversation-view-id="/index.xhtml">

  <page view-id="/index.xhtml" action="#{ssoAuthenticator.checkLogin}" login-required="false"/>

  <page view-id="/*" login-required="true"/>

  <exception class="org.jboss.seam.security.NotLoggedInException">
    <redirect view-id="/index.xhtml">
      <message>Please log in first</message>
    </redirect>
  </exception>

  ...

</pages>