13 Replies Latest reply on Dec 1, 2006 6:13 AM by marilenc

    Can't get access right from Java Client

    jmcollin92

      I'm sorry to ask this question another time but I read all documentation and FAQ and I can't get my java client access to my EJB.
      I'm on this pb for 3 days, and I had to make it works.
      Thank's for your help.

      Environnemt : Jboss4.0.1.SP1 and I try with 4.0.4.GA without success.

      Here are some piece of code :
      In the client :

      System.setProperty("java.security.auth.login.config", "file://path/to/auth.conf");
      Hashtable env = new Hashtable();
      env.put(Context.INITIAL_CONTEXT_FACTORY,"org.jboss.security.jndi.LoginInitialContextFactory");
      env.put(Context.URL_PKG_PREFIXES,"org.jboss.naming:org.jnp.interfaces");
      env.put(Context.PROVIDER_URL, "jnp://localhost:1099");
      env.put(Context.SECURITY_CREDENTIALS,"root");
      env.put(Context.SECURITY_PRINCIPAL,"root");
      env.put(Context.SECURITY_PROTOCOL,"CPIProject");
      
      javax.naming.InitialContext initialContext = new javax.naming.InitialContext(env);
      
      Object objRef = initialContext.lookup(jndiName);
      
      MyHome home = javax.rmi.PortableRemoteObject.narrow(objRef, MyHome.class);
      
      /* It's fails at the next line !! */
      MyBean bean = home.create();
      ...
      


      The auth.conf is :
      CPIProject {
       org.jboss.security.ClientLoginModule required
       password-stacking="useFirstPass"
       ;
      };
      


      The login-config.xml is :
      <application-policy name="CPIProject">
       <authentication>
       <login-module code="org.jboss.security.ClientLoginModule" flag="required"/>
       <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">
       <module-option name="unauthenticatedIdentity">guest</module-option>
       <module-option name="dsJndiName">java:/CPIDS</module-option>
       <module-option name="principalsQuery">Select PASSWORD from COLLABORATEUR where LOGIN=?</module-option>
       <module-option name="rolesQuery">Select P.ROLES_FK, 'Roles' from PROFIL P,COLLABORATEUR C where C.LOGIN=? AND C.ID=COLLABORATEURS_FK</module-option>
       </login-module>
       </authentication>
       </application-policy>
      


      The debug security trace in server.log :
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.plugins.JaasSecurityManager.CPIProject] Begin isValid, principal:, cache info: null
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.plugins.JaasSecurityManager.CPIProject] defaultLogin, principal=
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.login.XMLLoginConfigImpl] Begin getAppConfigurationEntry(CPIProject), size=9
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.login.XMLLoginConfigImpl] End getAppConfigurationEntry(CPIProject), authInfo=AppConfigurationEntry[]:
      [0]
      LoginModule Class: org.jboss.security.ClientLoginModule
      ControlFlag: LoginModuleControlFlag : required
      Options:[1]
      LoginModule Class: org.jboss.security.auth.spi.DatabaseServerLoginModule
      ControlFlag: LoginModuleControlFlag : required
      Options:name=rolesQuery, value=Select P.ROLES_FK, 'Roles' from PROFIL P,COLLABORATEUR C where C.LOGIN=? AND C.ID=COLLABORATEURS_FK
      name=principalsQuery, value=Select PASSWORD from COLLABORATEUR where LOGIN=?
      name=unauthenticatedIdentity, value=guest
      name=dsJndiName, value=java:/CPIDS
      
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.ClientLoginModule] Begin login
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.ClientLoginModule] Obtained login: , credential.class: null
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.ClientLoginModule] End login
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] initialize, instance=@4626217
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] Saw unauthenticatedIdentity=guest
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] DatabaseServerLoginModule, dsJndiName=java:/CPIDS
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] principalsQuery=Select PASSWORD from COLLABORATEUR where LOGIN=?
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] rolesQuery=Select P.ROLES_FK, 'Roles' from PROFIL P,COLLABORATEUR C where C.LOGIN=? AND C.ID=COLLABORATEURS_FK
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] suspendResume=true
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] login
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] suspendAnyTransaction
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] Excuting query: Select PASSWORD from COLLABORATEUR where LOGIN=?, with username:
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] Query returned no matches from db
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] resumeAnyTransaction
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.ClientLoginModule] abort
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.SecurityAssociation] clear, server=true
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] abort
      2006-09-23 10:45:44,671 TRACE [org.jboss.security.plugins.JaasSecurityManager.CPIProject] Login failure
      javax.security.auth.login.FailedLoginException: No matching username found in Principals
       at org.jboss.security.auth.spi.DatabaseServerLoginModule.getUsersPassword(DatabaseServerLoginModule.java:152)
      

      We can see that the Principal is empty !
      The security informations seems to be not propagating from Client to Server.
      The FAQ says "put a ClientLoginModule". I've done this without sucess.

      For information, authentication is all right from a struts web app.

      What goes wrong ?



        • 1. Re: Can't get access right from Java Client
          jaikiran
          • 2. Re: Can't get access right from Java Client
            jmcollin92

            Really, really thank's for your help.

            I've tried your piece of code (and I've already tired some similarly code) without success.
            Here is my code :

            static class AppCallbackHandler implements CallbackHandler
             {
             private String username;
             private String password;
            
             public AppCallbackHandler(String username, String password)
             {
             this.username = username;
             this.password = password;
             }
            
             public void handle(Callback[] callbacks) throws
             java.io.IOException, UnsupportedCallbackException
             {
             for (int i = 0; i < callbacks.length; i++)
             {
             if (callbacks instanceof NameCallback)
             {
             NameCallback nc = (NameCallback) callbacks;
             nc.setName(username);
             }
             else if (callbacks instanceof PasswordCallback)
             {
             PasswordCallback pc = (PasswordCallback) callbacks;
             pc.setPassword(password.toCharArray());
             }
             else
             {
             throw new UnsupportedCallbackException(callbacks, "Unrecognized Callback");
             }
             }
             }
             }
            
             @SuppressWarnings("unchecked")
             @Before
             public void setUp() throws Exception {
             log.info("Appel setUp");
             System.setProperty("java.security.auth.login.config", "E:/jmc/projets/CPI/workspace/CPITests/bin/auth.conf");
            
             try
             {
             AppCallbackHandler handler = new AppCallbackHandler("root", "root");
             LoginContext lc = new LoginContext("CPIProject", handler);
             System.out.println("Created LoginContext");
             lc.login();
             Subject s = lc.getSubject();
             for (Principal p : s.getPrincipals()) {
             log.debug("Principal dans Subjet :"+p.getName());
             }
             }
             catch (LoginException le)
             {
             System.out.println("Login failed");
             le.printStackTrace();
             }
            
             Context ctx = new InitialContext();
             Object lookupObj = ctx.lookup(ServiceCollaborateurHome.JNDI_NAME);
             log.info("Recherche de la home");
             ServiceCollaborateurHome home = (ServiceCollaborateurHome) PortableRemoteObject.narrow(lookupObj, ServiceCollaborateurHome.class);


            The error is always the same (server side) :
            java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
             java.rmi.AccessException: SecurityException; nested exception is:
             javax.security.auth.login.FailedLoginException: No matching username found in Principals
             at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:325)
             at sun.rmi.transport.Transport$1.run(Transport.java:153)
             at java.security.AccessController.doPrivileged(Native Method)
             at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
             at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466)
             at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707)
             at java.lang.Thread.run(Thread.java:595)
             at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source)
             at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
             at sun.rmi.server.UnicastRef.invoke(Unknown Source)
             at org.jboss.invocation.jrmp.server.JRMPInvoker_Stub.invoke(Unknown Source)
             at org.jboss.invocation.jrmp.interfaces.JRMPInvokerProxy.invoke(JRMPInvokerProxy.java:118)
             at org.jboss.invocation.InvokerInterceptor.invokeInvoker(InvokerInterceptor.java:163)
             at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.java:103)
             at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:46)
             at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:55)
             at org.jboss.proxy.ejb.HomeInterceptor.invoke(HomeInterceptor.java:169)
             at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:91)
             at $Proxy0.create(Unknown Source)
             at jmcnet.cpi.tests.TestGererCollaborateur.setUp(TestGererCollaborateur.java:119)
             at junit.framework.TestCase.runBare(TestCase.java:128)
             at junit.framework.TestResult$1.protect(TestResult.java:110)
             at junit.framework.TestResult.runProtected(TestResult.java:128)
             at junit.framework.TestResult.run(TestResult.java:113)
             at junit.framework.TestCase.run(TestCase.java:120)
             at junit.framework.TestSuite.runTest(TestSuite.java:228)
             at junit.framework.TestSuite.run(TestSuite.java:223)
             at org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:35)
             at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
             at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
             at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
             at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
             at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
             at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
            Caused by: java.rmi.AccessException: SecurityException; nested exception is:
             javax.security.auth.login.FailedLoginException: No matching username found in Principals
             at org.jboss.ejb.plugins.LogInterceptor.handleException(LogInterceptor.java:388)
             at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:136)
             at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invokeHome(ProxyFactoryFinderInterceptor.java:107)
             at org.jboss.ejb.SessionContainer.internalInvokeHome(SessionContainer.java:637)
             at org.jboss.ejb.Container.invoke(Container.java:975)
             at sun.reflect.GeneratedMethodAccessor123.invoke(Unknown Source)
             at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
             at java.lang.reflect.Method.invoke(Method.java:585)
             at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
             at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
             at org.jboss.mx.server.Invocation.invoke(Invocation.java:86)
             at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
             at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
             at org.jboss.invocation.jrmp.server.JRMPInvoker$MBeanServerAction.invoke(JRMPInvoker.java:819)
             at org.jboss.invocation.jrmp.server.JRMPInvoker.invoke(JRMPInvoker.java:420)
             at sun.reflect.GeneratedMethodAccessor125.invoke(Unknown Source)
             at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
             at java.lang.reflect.Method.invoke(Method.java:585)
             at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:294)
             at sun.rmi.transport.Transport$1.run(Transport.java:153)
             at java.security.AccessController.doPrivileged(Native Method)
             at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
             at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466)
             at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707)
             at java.lang.Thread.run(Thread.java:595)
            Caused by: javax.security.auth.login.FailedLoginException: No matching username found in Principals
             at org.jboss.security.auth.spi.DatabaseServerLoginModule.getUsersPassword(DatabaseServerLoginModule.java:152)
             at org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(UsernamePasswordLoginModule.java:206)
             at sun.reflect.GeneratedMethodAccessor138.invoke(Unknown Source)
             at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
             at java.lang.reflect.Method.invoke(Method.java:585)
             at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
             at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
             at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
             at java.security.AccessController.doPrivileged(Native Method)
             at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
             at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
             at org.jboss.security.plugins.JaasSecurityManager.defaultLogin(JaasSecurityManager.java:601)
             at org.jboss.security.plugins.JaasSecurityManager.authenticate(JaasSecurityManager.java:535)
             at org.jboss.security.plugins.JaasSecurityManager.isValid(JaasSecurityManager.java:344)
             at org.jboss.ejb.plugins.SecurityInterceptor.checkSecurityAssociation(SecurityInterceptor.java:211)
             at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:135)
             at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:132)
             ... 23 more


            I've tried something : giving a wrong name to the security module (given to the LoginContext constructor) makes the test pass !
            I've got a login exception but I can call my EJB and it's works !

            Have you an idea of what happens ?

            • 3. Re: Can't get access right from Java Client
              jmcollin92

              In fact, my EJB don't check if the user is logged in. So giving a wrong name make the test pass.
              But the business method check the role of the user to take decision (if (! ctx.isCallerInRole...).
              So I need to be logged before calling the business method.
              Any help would be apprecied.

              • 4. Re: Can't get access right from Java Client
                jaikiran

                As per the documentation of ClientLoginModule (http://wiki.jboss.org/wiki/Wiki.jsp?page=ClientLoginModule) :

                Note that this login module does not perform any authentication. It merely copies the login information provided to it into the JBoss server EJB invocation layer for subsequent authentication on the server. If you need to perform client-side authentication of users you would need to configure another login module in addition to the ClientLoginModule .


                So if you are using isCallerInRole in your EJB, you will require a *authenticated* user, in which case you will require a additional login module which will do the authentication(as mentioned in the quote above)



                • 5. Re: Can't get access right from Java Client
                  jmcollin92

                  Thank's for your answer. Your help is precious.
                  But I ask me some other questions.

                  If you need to perform client-side authentication of users you would need to configure another login module in addition to the ClientLoginModule .

                  I was first using LoginInitialContextFactory. Does this module perform client-side authentication ?
                  If not, can you send me a piece of code that does perform client-side authentication ?


                  So if you are using isCallerInRole in your EJB, you will require a *authenticated* user, in which case you will require a additional login module which will do the authentication(as mentioned in the quote above)

                  You mean that all code found on the internet does not authenticate ? I can'et believe thsi because all are talking about login and password.
                  Are you sure I need another module client side ?

                  • 6. Re: Can't get access right from Java Client
                    jaikiran

                     

                    I was first using LoginInitialContextFactory. Does this module perform client-side authentication ?


                    As per the javadocs of LoginInitialContextFactory:

                    /** A naming provider InitialContextFactory implementation that combines the authentication phase
                    * with the InitialContext creation. During the getInitialContext callback from the JNDI naming
                    * layer a JAAS LoginContext is created using the login configuration name passed in as
                    * the Context.SECURITY_PROTOCOL env property. The CallbackHandler used is a
                    * org.jboss.security.auth.callback.UsernamePasswordHandler that is populated
                    * with the username obtained from the Context.SECURITY_PRINCIPAL env property
                    * and the credentials from the Context.SECURITY_CREDENTIALS env property.
                    */


                    In brief, the LoginIntialContextFactory uses the login module to which you passed through env.put(Context.SECURITY_PROTOCOL,...). In your case this happens to be:

                    env.put(Context.SECURITY_PROTOCOL,"CPIProject");


                    And your "CPIProject" points to the ClientLoginModule:

                    CPIProject {
                     org.jboss.security.ClientLoginModule required
                     password-stacking="useFirstPass"
                     ;
                    };


                    As already mentioned the ClientLoginModule will just copy the login information and will not do any authentication.

                    If not, can you send me a piece of code that does perform client-side authentication ?


                    If you require authentication to be done, then the simplest one would be to use the UsersRolesLoginModule which authenticates using users.properties file and roles.properties file. So your "CPIProject" context will look like:

                    CPIProject {
                    org.jboss.security.auth.spi.UsersRolesLoginModule required;
                    };


                    Your properties file should be present in the classpath. Typically the users.properties file will contain something like:

                    #username=password
                    root=root
                    someotheruser=pass1


                    The roles.properties will contain the username and role mappings.


                    • 7. Re: Can't get access right from Java Client
                      jmcollin92

                      Thank's for your reply.
                      But is it not possible to have the authentication done by the server using its login configuration ?

                      What's the use of having a security declaration server side if a client can authenticate itself and then make any calls he wants server side ?

                      There is really something I don't understand, I guess...

                      My needs are :
                      1. a client calls a log in service server side passing a login and a password to the server,
                      2. the server authenticate the user, store the roles of the user in the context,
                      3. the authenticated client calls a secured EJB.

                      Like it is done by a webapp accessing a secured EJB.

                      Is it not possible ?

                      • 8. Re: Can't get access right from Java Client
                        jmcollin92

                        Up

                        • 9. Re: Can't get access right from Java Client
                          jmcollin92

                          Is my question stupid or is there any solution ?

                          • 10. Re: Can't get access right from Java Client
                            jaikiran

                             

                            Is my question stupid


                            Ofcourse not. I just wanted to test these things in a sample application, before answering your question, so that i am completely sure as to what i am saying. Give me just some more time and i will answer your question.

                            • 11. Re: Can't get access right from Java Client
                              jaikiran

                              Thank you for being patient.

                              StandaloneClient SecurityInterceptorOnServer SecureResource
                               | | |
                               | | |
                               |1) doJAASlogin() | |
                               | | |
                               |2) invokeSecureResource() | |
                               |---------------------------------------------->| |
                               | | |
                               | | |
                               | |3)doJAASloginOnServer() |
                               | | |
                               | |4)if valid/authorized, let access |
                               | |---------------------------------------------->|
                               | |
                              
                              


                              The diagram above is just a simplified view of the entities involved, please do not go by the names.

                              Lets assume the following:
                              -------------------------
                              1) Only user(lets talk in terms of users instead of roles, for simplicity) "abc123" is allowed to access the secure resource
                              2) You are using ClientLoginModule at the standalone client programatically and UsersRolesLoginModule at the server(specified in jboss.xml) for securing the resource.


                              Here's the flow of what happens:

                              - The StandaloneClient invokes the doJAASlogin method using username "xyz"(invalid user) which uses ClientLoginModule to *populate the security info*.
                              - The doJAASlogin internally invokes the LoginContext's login method and this call to login succeeds even though the user is invalid. This is because you are using ClientLoginModule which does no authentication.
                              - After login, the StandAloneClient tries to access a secure resource on the server. It passes the security info which was created using the ClientLoginModule. This security info includes the username "xyz"(invalid user)
                              - At this point the Security interceptor(or whatever you call this entity) on the server comes into picture, since the resource is a secure one.
                              - The SecurityInterceptorOnServer will look at the jboss.xml to check the security domain to be used for authenticating the user request. In our case we have mentioned it as UsersRolesLoginModule (in our assumption #2).
                              - The SecurityInterceptorOnServer internally kicks off the authentication of the user request passing it the security info which was passed on by the StandAloneClient(this info includes the invalid username).
                              - During this process the UsersRolesLoginModule's login method is invoked. The UsersRolesLoginModule uses the username "xyz" and tries to login. But since this is not a valid user(remember as per assumption #1, valid username is "abc123"), the login fails and a SecurityException is thrown.
                              - Hence access to secure resource fails at this point.

                              This is how the flow works while accessing a secure resource.

                              I have tried my best to explain the flow to you. However, if you still have doubts about this, do let us know. Someone, if not me, will be able to help you out.



                              • 12. Re: Can't get access right from Java Client
                                jaikiran

                                The diagram lost some of the formatting, but i guess, its still readable.

                                • 13. Re: Can't get access right from Java Client
                                  marilenc

                                  I finally managed to get this to work and put everything working here, maybe it will help someone not loosing as much time as I did:
                                  http://www.len.ro/work/articles/jboss/jmx-invocation-with-secured-console/

                                  http://www.len.ro