2 Replies Latest reply on Dec 26, 2013 4:06 AM by s.reghuraman

    Custom JAAS login module subject association to the container

      Hi,

       

      We have a legacy financial application that works well with weblogic and websphere containers, currently we are trying to add support for Jboss 7.1. We have our own JAAS based common security framework works perfectly fine with the mentioned vendors (ofcourse with vendor specific JAAS integration API's).

       

      Since this is a legacy JAAS module that's been used across applications, I can't really start from extending Jboss SX AbstractServerLoginModule.

       

      Added our custom login module to jboss domain.xml security domain (other). The JbossCSFBaseLoginModule gets called and Subject gets created however the authenticated subject is not getting associated to the container. I need this to avoid multiple authentications. So I tried couple of way to get the authenticated Subject from the container both didn't work.

       

      Approach 1:

       

          Subject subject=null;

      SecurityContext sc = SecurityContextAssociation.getSecurityContext();


      subject=sc.getUtil().getSubject();

       

       

      Approach 2:


       


      Subject subject=null;


      try {



      subject = (Subject) PolicyContext.getContext("javax.security.auth.Subject.container");



      return subject;


      } catch (PolicyContextException e) {



      // TODO Auto-generated catch block



      e.printStackTrace();


      }

       

       

       

       

      So, I dig deeper into JBoss SubjectPolicyContextHandler code which essentially gets associated during the bootup.

       

      During the debug I noticed

       

                  SubjectInfo si = sc.getSubjectInfo();

       

                  if(si != null)

                  {

                     Subject activeSubject = si.getAuthenticatedSubject();

                     RunAsIdentity callerRunAsIdentity = (RunAsIdentity)sc.getIncomingRunAs();

       

      both activeSubject and  callerRunAsIdentity are resulting in null value's that's why I was getting the null subject.

       

      My question is, after succefull LoginModule commit, how can I update/create JbossSecurityContext subjectinfo with our authenticated subject that has custom principals?

       

      Do I need do to anything on the following lines to push the authenticated subject in the SubjectInfo.

       

      I tried couple way to do this you will find the same the following java code, both approaches didn't yield positve results.

       

      Approach 1:


            if( mboolCommitSucceeded){

      //            ctx.getSubjectInfo().setRoles(roles)

      //            ctx.getSubjectInfo().setIdentities(moSubject.getPrincipals());

      //            JBossSecurityContextUtil securityContextUtil= new JBossSecurityContextUtil(ctx);

      //            try {

      //               securityContextUtil.createSubjectInfo(identity, identity, moSubject);

      //          } catch (Exception e) {

      //               // TODO Auto-generated catch block

      //               e.printStackTrace();

      //          }

       

      Approach 2:

      //Associating authenticated subject to the JbossSecurityContext

       

                  JBossSecurityContext ctx=(JBossSecurityContext)SecurityContextAssociation.getSecurityContext();

                  ctx.getSubjectInfo().setAuthenticatedSubject(moSubject);


       

       

       

      I have the following the artifacts. Please let me know if I am missing anything.

       

      I am struck here for a while. Any help really appreciated.

       

      Thanks,

      SD

       

      JbossCSFBaseLoginModule.java

      package com.ams.core.appserver.enterprise;

       

       

      import java.security.Principal;

      import java.security.acl.Group;

      import java.util.Enumeration;

      import java.util.Iterator;

      import java.util.Map;

      import java.util.Set;

       

       

      import javax.security.auth.Subject;

      import javax.security.auth.callback.CallbackHandler;

      import javax.security.auth.login.LoginException;

       

       

      import org.jboss.security.NestableGroup;

      import org.jboss.security.SecurityConstants;

      import org.jboss.security.SecurityContextAssociation;

      import org.jboss.security.SimpleGroup;

      import org.jboss.security.SimplePrincipal;

      import org.jboss.security.plugins.JBossSecurityContext;

       

       

      import com.ams.core.security2.CorePrincipalImpl;

      import com.ams.csf.auth.CSFBaseLoginModule;

      import com.ams.csf.common.CSFUtil;

       

       

      public class JbossCSFBaseLoginModule extends CSFBaseLoginModule {

         /** The login identity */

         private Principal identity;

       

       

                @Override

                public void initialize(Subject foSubject, CallbackHandler callbackHandler, Map sharedState, Map options) {

                          super.initialize(foSubject, callbackHandler, sharedState, options);

                }

       

                @Override

                public boolean login() throws LoginException {

                          super.login();

                          if(mboolLoginSucceeded){

                                    try {

                                              identity=createIdentity(CSFUtil.getUsername(moSharedState));

                                    } catch (Exception e) {

                                              // TODO Auto-generated catch block

                                              e.printStackTrace();

                                    }

                                    return true;

                          }

                          return false;

                }

       

                @Override

                public boolean abort() throws LoginException {

                          boolean flag=super.abort();

                          if(flag){

       

                          }

                          return flag;

                }

                @Override

                public boolean commit() throws LoginException {

                          super.commit();

            if( mboolCommitSucceeded){

              Set<Principal> principals = moSubject.getPrincipals();

              Principal identity = getIdentity();

              principals.add(identity);

              // add the CallerPrincipal group

              Group callerGroup = getCallerPrincipalGroup(principals);

              if (callerGroup == null)

              {

                 callerGroup = new SimpleGroup(SecurityConstants.CALLER_PRINCIPAL_GROUP);

                 callerGroup.addMember(identity);

                 principals.add(callerGroup);

              }

              // add other role groups

              Group[] roleSets = getRoleSets();

              for(int g = 0; g < roleSets.length; g ++)

              {

                 Group group = roleSets[g];

                 String name = group.getName();

                 Group subjectGroup = createGroup(name, principals);

                 if( subjectGroup instanceof NestableGroup )

                 {

                    /* A NestableGroup only allows Groups to be added to it so we

                    need to add a SimpleGroup to subjectRoles to contain the roles

                    */

                    SimpleGroup tmp = new SimpleGroup("Roles");

                    subjectGroup.addMember(tmp);

                    subjectGroup = tmp;

                 }

                 // Copy the group members to the Subject group

                 Enumeration<? extends Principal> members = group.members();

                 while( members.hasMoreElements() )

                 {

                    Principal role = (Principal) members.nextElement();

                    subjectGroup.addMember(role);

                 }

              }

             

      //                    ctx.getSubjectInfo().setRoles(roles)

      //                    ctx.getSubjectInfo().setIdentities(moSubject.getPrincipals());

      //                    JBossSecurityContextUtil securityContextUtil= new JBossSecurityContextUtil(ctx);

      //                    try {

      //                    securityContextUtil.createSubjectInfo(identity, identity, moSubject);

      //          } catch (Exception e) {

      //                    // TODO Auto-generated catch block

      //                    e.printStackTrace();

      //          }

      //           

            //Associating authenticated subject to the JbossSecurityContext       

                            JBossSecurityContext ctx=(JBossSecurityContext)SecurityContextAssociation.getSecurityContext();

                            ctx.getSubjectInfo().setAuthenticatedSubject(moSubject);

       

                  //Not sure if we need this to make the association work    

      //                      RoleGroup roleGroup= new RoleGroup();

      //                    ctx.getSubjectInfo().setRoles(roles);

                      return true;

            }

            return false;

                }

                private Group[] getRoleSets() {

                      Group[] roleSets = {new SimpleGroup("Roles")};

                      roleSets[0].addMember(new SimplePrincipal("user"));

                      roleSets[0].addMember(new SimplePrincipal("guest"));

                      return roleSets;

                }

       

       

                private Principal getIdentity() {

                          // TODO Auto-generated method stub

                          return identity;

                }

       

       

                @Override

                public boolean logout() throws LoginException {

                          boolean flag=super.logout();

                      Principal identity = getIdentity();

                      Set<Principal> principals = moSubject.getPrincipals();

                      principals.remove(identity);

                      Group callerGroup = getCallerPrincipalGroup(principals);

                      if (callerGroup != null)

                         principals.remove(callerGroup);

                          return flag;

                }

                   protected Group createGroup(String name, Set<Principal> principals)

                   {

                      Group roles = null;

                      Iterator<Principal> iter = principals.iterator();

                      while( iter.hasNext() )

                      {

                         Object next = iter.next();

                         if( (next instanceof Group) == false )

                            continue;

                         Group grp = (Group) next;

                         if( grp.getName().equals(name) )

                         {

                            roles = grp;

                            break;

                         }

                      }

                      // If we did not find a group create one

                      if( roles == null )

                      {

                         roles = new SimpleGroup(name);

                         principals.add(roles);

                      }

                      return roles;

                   }

       

       

                   /** Utility method to create a Principal for the given username. This

                    * creates an instance of the principalClassName type if this option was

                    * specified using the class constructor matching: ctor(String). If

                    * principalClassName was not specified, a SimplePrincipal is created.

                    *

                    * @param username the name of the principal

                    * @return the principal instance

                    * @throws java.lang.Exception thrown if the custom principal type cannot be created.

                    */

                   @SuppressWarnings("unchecked")

                   protected Principal createIdentity(String username)

                      throws Exception

                   {

                             CorePrincipalImpl p= new CorePrincipalImpl();

                             p.setName(username);

                      return p;

                   }

                  

                   protected Group getCallerPrincipalGroup(Set<Principal> principals)

                   {

                      Group callerGroup = null;

                      for (Principal principal : principals)

                      {

                         if (principal instanceof Group)

                         {

                            Group group = Group.class.cast(principal);

                            if (group.getName().equals(SecurityConstants.CALLER_PRINCIPAL_GROUP))

                            {

                               callerGroup = group;

                               break;

                            }

                         }

                      }

                      return callerGroup;

                   }

      }

       

      domain.xml

      -------------------------

       

                  <subsystem xmlns="urn:jboss:domain:security:1.1">

                      <security-domains>

                          <security-domain name="other" cache-type="default">

                          <security-domain name="other" cache-type="default">

                              <authentication>

                                  <login-module code="com.ams.core.appserver.enterprise.JbossCSFBaseLoginModule" flag="sufficient"/>

                                   <login-module code="org.jboss.security.ClientLoginModule" flag="required">

                                         <module-option name="password-stacking" value="useFirstPass"/>

                                                                                                     </login-module>

                                                                                      </authentication>

                          </security-domain>

      ...........

       

      jboss-web.xml

       

      <jboss-web>

            <security-domain>java:/jaas/other</security-domain>

                <security-role id="fdx">

                          <role-name>*</role-name>

                </security-role>

      </jboss-web>

       

      web.xml has the following.. security related info..

       


      <security-role>


      <description />


      <role-name>fdx</role-name>

      </security-role>

      <security-role>


      <description />


      <role-name>fdx-admin</role-name>

      </security-role>

      <security-role>


      <description />


      <role-name>fdx-user</role-name>

      </security-role>

      <resource-ref id="ResourceRef_fdx_security">


      <res-ref-name>fdx.security</res-ref-name>


      <res-type>javax.sql.DataSource</res-type>


      <res-auth>Container</res-auth>


      <res-sharing-scope>Shareable</res-sharing-scope>

      </resource-ref>

      <security-constraint>


      <web-resource-collection>



      <web-resource-name>restricted methods</web-resource-name>



      <url-pattern>/*</url-pattern>



      <http-method>TRACE</http-method>



      <http-method>OPTIONS</http-method>



      <http-method>DELETE</http-method>


      </web-resource-collection>


      <auth-constraint>



      <role-name>fdx-admin</role-name>



      <role-name>fdx-user</role-name>



      <role-name>fdx</role-name>


      </auth-constraint>

      </security-constraint>