2 Replies Latest reply on May 22, 2011 12:06 AM by ajaygupta0512

    Seam 2.2.0 and JBoss negotiation SPNEGO without login form

    jeroenkoek

      To help others that are struggeling with SSO,


      I have got SPNEGO authentication working using the JAAS module of JBoss (jboss-negotiation). The user is auto logged in using the information stored in the servlet.


      Steps to follow;



      Ensure that the web.xml is handling the security




      <security-constraint>
        <display-name>Restrict raw XHTML Documents</display-name>
        <web-resource-collection>
        <web-resource-name>XHTML</web-resource-name>
        <url-pattern>*.xhtml</url-pattern>
        </web-resource-collection>
        <web-resource-collection>
        <web-resource-name>SEAM</web-resource-name>
        <url-pattern>*.seam</url-pattern>
        </web-resource-collection>
        <auth-constraint>
          <role-name>*</role-name>
        </auth-constraint>
      </security-constraint>
      
      <login-config>
        <auth-method>SPNEGO</auth-method>
      </login-config>
      




      Enable jaas component;


      In the components.xml set the identity configuration. This is the JAAS login-config that is defined by you in the login-config.xml as described in the manual of JBOSS negotiation.



      <security:identity jaas-config-name="SPNEGO" /> 





      Disable the Identity httprequestwrapper in the components.xml



      <web:identity-filter disabled="true"/>



      By doing this the http servlet information such as remote-user and the userprincipal are available to be used in a identity class (next step). If you do not do this the Identity store is retrieving it's own information, resulting in a stack overflow in my case.


      Create a identity class that overrules the standard SEAM identity class



      The getPrincipal() will now be used in the super class to see that there is a principal. Seam security will conclude that the user is logged in.


      The hasRole will still be using the servlet isUserInRole function, but




      import java.security.Principal;
      import java.util.Collection;
      
      import javax.faces.context.FacesContext;
      import javax.security.auth.Subject;
      import javax.security.auth.login.LoginContext;
      import javax.security.auth.login.LoginException;
      import javax.servlet.http.HttpServletRequest;
      
      import org.jboss.seam.ScopeType;
      import org.jboss.seam.annotations.Install;
      import org.jboss.seam.annotations.Logger;
      import org.jboss.seam.annotations.Name;
      import org.jboss.seam.annotations.Scope;
      import org.jboss.seam.annotations.Startup;
      import org.jboss.seam.annotations.intercept.BypassInterceptors;
      import org.jboss.seam.core.Expressions.MethodExpression;
      import org.jboss.seam.log.Log;
      import org.jboss.seam.security.Credentials;
      import org.jboss.seam.security.Identity;
      
      @SuppressWarnings("serial")
      @Name("org.jboss.seam.security.identity")
      @Scope(ScopeType.SESSION)
      @Install(precedence = Install.APPLICATION)
      @BypassInterceptors
      @Startup
      public class CustomIdentity extends Identity {
      
      @Logger     Log log;
      
      
      @Override
      public Principal getPrincipal() {
           Principal principal = super.getPrincipal();
           if ( principal == null ) {
                 // get the remote user name from the session
       getCredentials().setUsername(
      FacesContext.getCurrentInstance().getExternalContext().getRemoteUser());
            log.info( "session user:" + FacesContext.getCurrentInstance().getExternalContext().getRemoteUser() );
            log.info( "session principal:" + FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal() );
            principal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
            acceptExternallyAuthenticatedPrincipal(principal);
            }
           return principal;
           }
      
      
      @Override
      public boolean hasRole(String arg0) {
           boolean result = super.hasRole(arg0);
           if ( !result ) {
                result = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).isUserInRole(arg0);
           //bit by bit we are extending the role set of this user, this is a kind of caching of the roles.
           //the servlet interface doesn't provide us with a function to get all roles
           //so we are retrieving them on a request basis.
           if ( result ) {
                super.addRole(arg0);
           }
      }
           log.info("hasRole:" +arg0 + " " + result);
           return result;
      }
      
      }
      





      Ensure that the login-required flag is on your page.xml





      <page no-conversation-view-id="/main.xhtml"
           view-id="/main.xhtml"
           login-required="true" .....
      





      Annotation


      If I'm right it should work. You can verify it by annotating a seam javabean




      @Name("yourbean")
      @Scope(ScopeType.PAGE)
      @MeasureCalls
      @Restrict("#{s:hasRole('your defined rule')}")
      



      Hope this helps,


      Jeroen










        • 1. Re: Seam 2.2.0 and JBoss negotiation SPNEGO without login form
          alfredw

          Hi Jeroen,


          Thanks for the great write up but I'm having a slight issue with getting the remote user and the principal from the CustomIdentity class.


          ...
          log.info( "session user:" + FacesContext.getCurrentInstance().getExternalContext().getRemoteUser() );
          log.info( "session principal:" + FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal() );
          ...
          



          In the log, these two lines return nil thus causing an error to occur. Any insight on why this will happen? I have setup the server just like JBoss Negotiation documents I should, the Toolkit that comes with JBoss Negotiation works for all three tests so I'm assuming that the framework is up and running. I'm running Seam 2.2.0, ICEFaces, with JBoss AS 5.0.1.


          Thank you,
          Alfred

          • 2. Re: Seam 2.2.0 and JBoss negotiation SPNEGO without login form

            How would this approach change if I was using IBM Websphere Application Server 7 with SPNEGO?