1 Reply Latest reply on Nov 15, 2004 4:43 PM by Marco Antonio Villalobos, Jr.

    What am I doing wrong?  Please help.

    Marco Antonio Villalobos, Jr. Newbie

      Here is the scenario. I have a custom jaas login module that my web app and EJBs use. A user performs a login. The webpage calls an EJB to do something. It seems as though the web application authenticates and authorisizes properly, however, the EJB seems to fail in the same process. Am I doing something wrong with security?

      Here is my error message and login module:

      2004-11-12 12:28:36,613 ERROR [org.jboss.ejb.plugins.SecurityInterceptor] Authentication exception, principal=villalobosm
      2004-11-12 12:28:36,613 ERROR [org.jboss.ejb.plugins.LogInterceptor] EJBException in method: public abstract kineteque.myapp.ejb.session.scriptaudit.ScriptAuditSystem kineteque.myapp.ejb.session.scriptaudit.ScriptAuditSystemHome.create() throws java.rmi.RemoteException,javax.ejb.CreateException, causedBy:
      java.lang.SecurityException: Authentication exception, principal=villalobosm
      at org.jboss.ejb.plugins.SecurityInterceptor.checkSecurityAssociation(SecurityInterceptor.java:173)



      package kineteque.myapp.jaas;

      import org.jboss.security.SimpleGroup;
      import org.jboss.security.auth.spi.AbstractServerLoginModule;

      import javax.security.auth.Subject;
      import javax.security.auth.callback.CallbackHandler;
      import javax.security.auth.callback.NameCallback;
      import javax.security.auth.callback.PasswordCallback;
      import javax.security.auth.callback.Callback;
      import javax.security.auth.callback.UnsupportedCallbackException;

      import javax.security.auth.login.FailedLoginException;
      import javax.security.auth.login.LoginException;
      import java.io.IOException;
      import java.security.Principal;
      import java.security.acl.Group;
      import java.util.Map;

      import kineteque.myapp.JNDINames;

      /**
      * When subclassing the AbstractServerLoginModule implement the following:
      *
      * void initialize(Subject, CallbackHandler, Map, Map) if you have custom options to parse.
      * boolean login() to perform the authentication activity.
      * Principal getIdentity() to return the Principal object for the user authenticated by the log() step.
      * Group[] getRoleSets() to return at least a Group named Roles that contains the roles assigned to the Principal authenticated during login(). A second common group is CallerPrincipal; it provides, if necessary, the user's application identity rather than the security domain identity.
      *
      */
      public class MyAppLoginModule extends AbstractServerLoginModule
      {
      /** The roles that the principal belongs too. */
      private Group roles = null;
      /** The principal that was authenticated. */
      private Principal identity = null;
      /** Standard fail message */
      private static final String STANDARD_FAIL_AUTH_MESSAGE = "Not Authorized.";

      /**
      * Initialize the login module. This stores the subject, callbackHandler
      * and sharedState, and options for the login session. Subclasses should override
      * if they need to process their own options. A call to super.initialize(...)
      * must be made in the case of an override.
      * @param subject the Subject to update after a successful login.
      * @param callbackHandler the CallbackHandler that will be used to obtain the
      * the user identity and credentials.
      * @param sharedState a Map shared between all configured login module instances
      * @param options option password-stacking: if true, the login identity will be taken from the
      * javax.security.auth.login.name value of the sharedState map, and
      * the proof of identity from the javax.security.auth.login.password
      * value of the sharedState map.
      */
      public void initialize(Subject subject,
      CallbackHandler callbackHandler, Map sharedState, Map options)
      {
      //jboss documentation states that this should be
      //the first line of this method.
      super.initialize(subject,callbackHandler,sharedState,options);
      }

      /**
      * Looks for javax.security.auth.login.name and javax.security.auth.login.password
      * values in the sharedState map if the useFirstPass option was true and returns
      * true if they exist. If they do not or are null, this method returns false.
      * Subclasses should override to perform the required credential validation steps.
      * @return
      * @throws LoginException
      */
      public boolean login() throws LoginException
      {
      if (callbackHandler==null)
      throw new LoginException("No Callback handler available.");

      //initialize a callback for the username and password
      NameCallback ncb = new NameCallback("Username: ");
      PasswordCallback pcb = new PasswordCallback("Password: ",false);
      Callback[] cb = {ncb,pcb};

      try
      {
      //get the username and password
      callbackHandler.handle(cb);

      //get the username
      String name = ncb.getName();
      identity = createIdentity(name);

      try
      {
      //validate the username and password pair
      AuthenticateCmd authenticate = new AuthenticateCmd();
      if (!authenticate.execute(identity.getName(),pcb.getPassword()))
      throw new FailedLoginException(STANDARD_FAIL_AUTH_MESSAGE);
      }
      finally
      {
      pcb.clearPassword();
      }
      }
      catch (IOException e)
      {
      throw new LoginException("Failed to handle callback.");
      }
      catch (UnsupportedCallbackException e)
      {
      throw new LoginException("Failed to handle callback.");
      }
      catch (Exception e)
      {
      throw new FailedLoginException(STANDARD_FAIL_AUTH_MESSAGE);
      }
      loginOk = true;
      return true;
      }

      /**
      * Retrieve the users primary identity.
      * @return The users primary identiy.
      */
      protected Principal getIdentity()
      {
      return identity;
      }

      /**
      * Overridden by subclasses to return the Groups that correspond
      * to the role sets assigned to the user. Subclasses should create at
      * least a Group named "Roles" that contains the roles assigned to the user.
      * A second common group is "CallerPrincipal," which provides the application
      * identity of the user rather than the security domain identity.
      * @return Group[] containing the sets of roles
      */
      protected Group[] getRoleSets() throws LoginException
      {
      Group[] value = null;
      try
      {
      if (roles==null)
      {
      roles = new SimpleGroup("Roles");


      AuthorizeCmd authorize = null;
      try
      {
      String datasource = JNDINames.DATASOURCE;
      authorize = new AuthorizeCmd();
      }
      catch(Error e)
      {
      e.printStackTrace();
      }
      catch(RuntimeException e)
      {
      e.printStackTrace();
      }
      authorize.setUsername(identity.getName());
      authorize.execute();
      RoleDTO roleDTO = null;
      Principal p = null;
      while(authorize.hasNext())
      {
      roleDTO = (RoleDTO)authorize.next();
      p = createIdentity(roleDTO.getRole());
      roles.addMember(p);
      }
      value = new Group[]{roles};
      }
      }
      catch (Exception e)
      {
      throw new LoginException("Cannot create roles.");
      }
      return value;
      }
      }


      Here are my configuration files:

      login-config.xml:


      <application-policy name="kineteque-security" >

      <login-module code="kineteque.myapp.jaas.MyAppLoginModule" flag="required" />


      </application-policy>



      web.xml:

      <web-app
      xmlns="http://java.sun.com/xml/ns/j2ee"
      version="2.4"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

      <security-role>
      <role-name>Administrator</role-name>
      </security-role>

      <security-role>
      <role-name>IT_Operator</role-name>
      </security-role>

      <security-role>
      <role-name>Auditor</role-name>
      </security-role>

      <ejb-ref>
      <ejb-ref-name>ejb/ScriptAuditSystemEJB</ejb-ref-name>
      <ejb-ref-type>Session</ejb-ref-type>
      kineteque.myapp.ejb.session.scriptaudit.ScriptAuditSystemHome
      kineteque.myapp.ejb.session.scriptaudit.ScriptAuditSystem
      </ejb-ref>

      </web-app>

      ejb-jar.xml:

      <ejb-jar
      xmlns="http://java.sun.com/xml/ns/j2ee"
      version="2.1"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">

      <enterprise-beans>


      <ejb-name>ScriptAuditSystemEJB</ejb-name>
      kineteque.myapp.ejb.session.scriptaudit.ScriptAuditSystemHome
      kineteque.myapp.ejb.session.scriptaudit.ScriptAuditSystem
      <ejb-class>kineteque.myapp.ejb.session.scriptaudit.ScriptAuditSystemBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>
      <resource-ref>
      MyDS JDBC reference
      <res-ref-name>jdbc/MyDS</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
      </resource-ref>
      <security-identity>
      <use-caller-identity/>
      </security-identity>


      </enterprise-beans>

      <assembly-descriptor>

      <security-role>
      <role-name>Administrator</role-name>
      </security-role>
      <security-role>
      <role-name>IT_Operator</role-name>
      </security-role>
      <security-role>
      <role-name>Auditor</role-name>
      </security-role>

      <method-permission>
      <role-name>Administrator</role-name>

      <ejb-name>ScriptAuditSystemEJB</ejb-name>
      <method-name>*</method-name>

      </method-permission>
      <method-permission>
      <role-name>IT_Operator</role-name>

      <ejb-name>ScriptAuditSystemEJB</ejb-name>
      <method-name>*</method-name>

      </method-permission>
      <method-permission>
      <role-name>Auditor</role-name>

      <ejb-name>ScriptAuditSystemEJB</ejb-name>
      <method-name>*</method-name>

      </method-permission>

      <container-transaction>
      Transaction attributes for 'ScriptAuditSystemEJB' methods

      <ejb-name>ScriptAuditSystemEJB</ejb-name>
      <method-name>*</method-name>

      <trans-attribute>Required</trans-attribute>
      </container-transaction>

      </assembly-descriptor>
      </ejb-jar>

      jboss-app.xml:

      <jboss-app>
      <security-domain>java:/jaas/kineteque-security</security-domain>
      </jboss-app>

      jboss-web.xml:

      <jboss-web>
      <security-domain>java:/jaas/kineteque-security</security-domain>

      <resource-ref>
      <res-ref-name>jdbc/MyDS/res-ref-name>
      <jndi-name>java:/MyDS</jndi-name>
      </resource-ref>

      <ejb-ref-name>ejb/ScriptAuditSystemEJB</ejb-ref-name>
      <jndi-name>ScriptAuditSystemEJB</jndi-name>
      </ejb-ref>

      </jboss-web>

      application.xml:

      <application
      xmlns="http://java.sun.com/xml/ns/j2ee"
      version="1.4"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application_1_4.xsd">

      MyApp
      <display-name>MyApp</display-name>


      myapp-ejb.jar




      <web-uri>MyApp.war</web-uri>
      <context-root>myapp</context-root>



      <security-role>
      <role-name>Administrator</role-name>
      </security-role>

      <security-role>
      <role-name>IT_Operator</role-name>
      </security-role>

      <security-role>
      <role-name>Auditor</role-name>
      </security-role>



      jboss.xml:

      <!DOCTYPE jboss PUBLIC
      "-//JBoss//DTD JBOSS 4.0//EN"
      "http://www.jboss.org/j2ee/dtd/jboss_4_0.dtd">

      <security-domain>java:/jaas/infonet-security</security-domain>
      <enterprise-beans>

      <ejb-name>ScriptAuditSystemEJB</ejb-name>
      <jndi-name>ScriptAuditSystemEJB</jndi-name>
      <resource-ref>
      <res-ref-name>jdbc/AppEvents</res-ref-name>
      <jndi-name>java:/AppEvents</jndi-name>
      </resource-ref>

      </enterprise-beans>