3 Replies Latest reply on Jun 16, 2008 8:38 AM by j0llyr0g3r

    Simple JAAS authentication not working....

    j0llyr0g3r

      Hey folks,

      i am really becoming desperate with Jboss + JAAS.

      I have a very simple RMI client which connects to a Stateless Session Bean running within a Jboss 4.2.

      This scenario works perfectly well. Now i want to secure access to my EJB by allowing only authenticated clients to call the EJB's method.

      Based on the official documentation: http://docs.jboss.org/jbossas/jboss4guide/r1/html/ch8.chapter.html

      i started out with the most simple authentication possible using UsersRolesLoginModule as login module:

      * Create the file users.properties in the ejb-jar subproject under the directory META-INF:

      admin=secretadminpassword
      user=secretuserpassword



      * Create the file roles.properties in the ejb-jar subproject under the directory META-INF:
      admin=adminRole
      user=userRole



      * Add a ejb-jar.xml to the ejb-jar subproject under the directory META-INF:
      <ejb-jar>
       <assembly-descriptor>
       <security-role>
       <description>admin: only allowed users</description>
       <role-name>adminRole</role-name>
       </security-role>
       <security-role>
       <description>users: the rest</description>
       <role-name>userRole</role-name>
       </security-role>
       <method-permission>
       <role-name>admin</role-name>
       <method>
       <ejb-name>SendCommand</ejb-name>
       <method-name>*</method-name>
       </method>
       </method-permission>
       </assembly-descriptor>
      </ejb-jar>


      * Add the file jboss.xml under the directory /$PROJECT-ROOT/META-INF

      <jboss>
       <security-domain>java:/jaas/esf</security-domain>
       <enterprise-beans>
       <session>
       <ejb-name>SendCommand</ejb-name>
       <jndi-name>SendCommand</jndi-name>
       </session>
       </enterprise-beans>
      </jboss>


      * Adjust the file login-config.xml under the directory $JBOSS_HOME/server/$PROFILE/conf/

      <application-policy name = "esf">
       <authentication>
       <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag = "required" />
       </authentication>
      </application-policy>
      


      So far, so good....

      If i rebuild my application and inspect the EAR's content, i see all the expected files there, meaning jboss.xml, user.properties etc....

      But: I can still connect with my RMI-client to my EJB even without giving credentials at all!
      No error messages, no exceptions....

      Any ideas what went wrong here?

      Is there a way to check what Jboss sees as a security domain?


      P.S.: Jaas may be great due to its modularity, but it is horrible, unbelievably horrible to configure for a Jaas-beginner. This is an utter catastrophy, how long do i have to study Jaas to get a simple authentication working?

        • 1. Re: Simple JAAS authentication not working....
          piotr.koper

          Try add @SecurityDomain at your bean definition:

          @SecurityDomain("esf")
          @Stateless
          @Remote({IMySecuredBean.class})
          public class MySecuredBean implements IMySecuredBean
          {
          ...
          }
          


          it works for me.

          regards
          koper

          • 2. Re: Simple JAAS authentication not working....
            j0llyr0g3r

            Thx very much, that was indeed missing!

            Now i am one step further, Jboss gives me no more errors when i try to access my EJB-application, but unfortunately the (stand-alone & remote) RMI-client does:

            ERROR [SocketClientInvoker.handleException]: Got marshalling exception, exiting
            java.lang.ClassNotFoundException: javax.ejb.EJBAccessException
             at org.jboss.remoting.serialization.ClassLoaderUtility.loadClass(ClassLoaderUtility.java:82)
             at org.jboss.remoting.loading.RemotingClassLoader.loadClass(RemotingClassLoader.java:76)
             at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
             at java.lang.Class.forName0(Native Method)
             at java.lang.Class.forName(Class.java:247)
             at org.jboss.remoting.loading.ObjectInputStreamWithClassLoader.resolveClass(ObjectInputStreamWithClassLoader.java:174)
             at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
             at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
             at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
             at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
             at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
             at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
             at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
             at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
             at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
             at org.jboss.remoting.serialization.impl.java.JavaSerializationManager.receiveObjectVersion2_2(JavaSerializationManager.java:239)
            


            * Googling for this error messages i found - literally - nothing.
            * If I remove all stuff which deals with authentification from client + Jboss + EAR everything works fine again, so this error is definitely caused by something which is related to JAAS
            * I have the jar "jbossall-client.jar" in my clients classpath, i thought this should be enough, but this jar does not contain the mentioned "java.lang.ClassNotFoundException: javax.ejb.EJBAccessException" the only thing i find is "javax/ejb/AccessLocalException.class" (in the unpacked jar)

            I try to connect to the server like that:

            Hashtable<String, String> props = new Hashtable<String, String>();
            props.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
            props.put(Context.PROVIDER_URL,"jnp://" + "myhost");
            props.put(Context.SECURITY_PRINCIPAL, "myuser");
            props.put(Context.SECURITY_CREDENTIALS, "mypassword");
            Context ctx = new InitialContext(props);
            // get RMI stub
            ISendCommand sendCommand = (ISendCommand) ctx.lookup(myjndiname);
            String result = sendCommand.sendCommand(myArgs);
            



            Does anybody know what i am doing wrong / in which jar this class is located?




            #####################################



            For readers which are as unexperienced as i am in JAAS, here is a quick summary what i have done so far (hopefully it helps you):


            * Create the file users.properties under /$PROJECT-ROOT/META-INF:

            admin=secretadminpassword
            user=secretuserpassword



            * Create the file roles.properties under /$PROJECT-ROOT/META-INF:

            admin=adminRole
            user=userRole



            * Add a ejb-jar.xml to the ejb-jar subproject under the directory META-INF:

            <ejb-jar>
             <assembly-descriptor>
             <security-role>
             <description>admin: only allowed users</description>
             <role-name>adminRole</role-name>
             </security-role>
             <security-role>
             <description>users: the rest</description>
             <role-name>userRole</role-name>
             </security-role>
             <method-permission>
             <role-name>admin</role-name>
             <method>
             <ejb-name>SendCommand</ejb-name>
             <method-name>*</method-name>
             </method>
             </method-permission>
             </assembly-descriptor>
            </ejb-jar>
            


            * Add the file jboss.xml under the directory /$PROJECT-ROOT/META-INF

            <jboss>
             <security-domain>java:/jaas/esf</security-domain>
             <enterprise-beans>
             <session>
             <ejb-name>SendCommand</ejb-name>
             <jndi-name>SendCommand</jndi-name>
             </session>
             </enterprise-beans>
            </jboss>
            


            * Adjust the file login-config.xml under the directory $JBOSS_HOME/server/$PROFILE/conf/

            <application-policy name = "esf">
             <authentication>
             <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag = "required">
             <module-option
             name="usersProperties">
             META-INF/users.properties
             </module-option>
             <module-option
             name="rolesProperties">
             META-INF/roles.properties
             </module-option>
             </login-module>
             </authentication>
            </application-policy>
            


            * Add annotations to the EJB

            @SecurityDomain("esf")
            .....
            public class SendCommand....


            • 3. Re: Simple JAAS authentication not working....
              j0llyr0g3r

              Hey folks,

              one step closer to a solution.....

              I had to add the jar-file jboss-ejb3x.jar to my clients classpath.

              Unfortunately it is still not working!

              No i get the following exception (on the client side, nothing in the logs on the Jboss side):

              Exception in thread "main" javax.ejb.EJBAccessException: Authentication failure
               at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.handleGeneralSecurityException(Ejb3AuthenticationInterceptor.java:68)
               at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:70)
               at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:110)
               at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
               at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:46)
               at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
               at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
               at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
               at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:304)
               at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:106)
               at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82)
               at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:769)
               at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:573)
               at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:373)
               at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:166)
               at org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientInvoker.java:163)
               at org.jboss.remoting.Client.invoke(Client.java:1634)
               at org.jboss.remoting.Client.invoke(Client.java:548)
               at org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemoteInterceptor.java:62)
               at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
               at org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPropagationInterceptor.java:67)
               at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
               at org.jboss.aspects.security.SecurityClientInterceptor.invoke(SecurityClientInterceptor.java:53)
               at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
               at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:74)
               at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
               at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:107)
              


              Funny enough,

              i get the exact same exception if i annotate my Bean with the annotation "@PermitAll".

              Now my bean looks like this:

              @SecurityDomain("esf")
              @PermitAll
              @Stateless
              @Remote
              @RemoteBinding(jndiBinding="eSF-Server/SendCommand/remote")
              public class SendCommand implements ISendCommand {


              Any ideas?