1 2 Previous Next 25 Replies Latest reply on Feb 24, 2006 3:52 PM by starksm64

    classic "principal=null".

    jkuhn

      Hello,

      I'm getting the classic "principal=null" exception. By doing a
      search for "principal=null" in this forum, I've found 90 hits,
      and have read them all. I feel like I know everything about JAAS,
      except for the reason why my servlet will not create a bean.
      I'm missing something, but I can't figure out what it is.

      I'm attempting to use DatabaseServerLoginModule to log my users
      into an application that is deployed in JBoss 3.2.1 (using Jetty)


      1) Here is the code from my servlet:


      ************** servlet code -- START

      String name = "jkuhn";
      String passwordStr = "jkuhn";
      char[] password = passwordStr.toCharArray();

      LoginContext lc = null;
      try{
      AppCallbackHandler handler = new AppCallbackHandler(name, password);
      lc = new LoginContext("toolkit", handler);
      System.out.println("Created LoginContext");
      lc.login();
      System.out.println("Logged in.");
      Iterator it = lc.getSubject().getPrincipals().iterator();
      while(it.hasNext()) {
      Object o = it.next();
      System.out.println("principle: "+o.getClass().getName()+ " "+o);
      }
      }catch (LoginException le){
      System.out.println("Login failed");
      le.printStackTrace();
      }

      System.out.println("About to create CatalogManagementLocal"); // this line executes.
      CatalogManagementLocal catalogManagement
      = CatalogManagementUtil.getLocalHome().create();
      System.out.println("Created CatalogManagementLocal"); // this line is never reached.

      if (lc != null){
      try{
      lc.logout();
      }catch(LoginException e){
      System.out.println("Logout failed"+e);
      }
      }

      ************** servlet code -- END


      2) The CallbackHandler is implemented as a static class inside the servlet
      as follows:


      ************** callbackHandler (also in the servlet) -- START

      static class AppCallbackHandler implements CallbackHandler {
      private String username;
      private char[] password;

      public AppCallbackHandler(String username, char[] 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);
      } else {
      throw new UnsupportedCallbackException(callbacks, "Unrecognized Callback");
      }
      }
      }
      }

      ************** callbackHandler (also in the servlet) -- END

      3) My login-config.xml is located in <JBOSS_HOME>/server/toolkit/conf/login-config.xml
      It looks like this:

      ************** login-config.xml -- START

      <application-policy name="toolkit">

      <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule"
      flag="sufficient">
      <module-option name="dsJndiName">java:/toolkitDS</module-option>
      <module-option name="principalsQuery">select Password from Principals where PrincipalID=?</module-option>
      <module-option name="rolesQuery">select Role, RoleGroup from Roles where PrincipalID=?</module-option>
      </login-module>
      <login-module code="org.jboss.security.auth.spi.AnonLoginModule" flag="required">
      <module-option name="unauthenticatedIdentity">guest</module-option>
      </login-module>

      </application-policy>

      <!-- The security domain for the Postgres DB -->
      <application-policy name = "PgDbRealm">

      <login-module code = "org.jboss.resource.security.ConfiguredIdentityLoginModule"
      flag = "required">
      <module-option name = "principal">user1</module-option>
      <module-option name = "userName">user1</module-option>
      <module-option name = "password">user1</module-option>
      <module-option name = "managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=toolkitDS</module-option>
      </login-module>

      </application-policy>

      ************** login-config.xml -- END

      NOTE: I have a fully functional schema in my postgres database
      that allows logins under "user1" with password = "user1". And,
      by accessing the database manually, I can verify that I have
      populated tables called "principals" and "roles". In these tables,
      there is user called "jkuhn" with a password of "jkuhn" and a role
      of "Echo".


      4) I have a descriptor for my session bean in the ejb-jar.xml file.
      Plus, I've got what I believe are the neccessary assembly-descriptors
      at the end of the file. Here are what they look like:

      ******** ejb-jar.xml (bean descriptor & assembly-descriptor) -- START


      Stateless Session bean.
      <ejb-name>CatalogManagement</ejb-name>
      toolkit.admin.services.catalog.interfaces.CatalogManagementRemoteHome
      toolkit.admin.services.catalog.interfaces.CatalogManagementRemote
      <local-home>toolkit.admin.services.catalog.interfaces.CatalogManagementLocalHome</local-home>
      toolkit.admin.services.catalog.interfaces.CatalogManagementLocal
      <ejb-class>toolkit.admin.services.catalog.ejb.CatalogManagementSession</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Container</transaction-type>
      <resource-ref >
      <res-ref-name>jdbc/toolkit</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
      </resource-ref>
      <security-role-ref>
      <role-name>EchoUser</role-name>
      <role-link>Echo</role-link>
      </security-role-ref>


      <assembly-descriptor>
      <security-role>
      <role-name>Echo</role-name>
      </security-role>
      <method-permission>
      <role-name>Echo</role-name>

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

      </method-permission>
      </assembly-descriptor>

      ******** ejb-jar.xml (bean descriptor & assembly-descriptor) -- END

      5) I have added the following security-domain to the top
      of my jboss.xml and jboss-web.xml file:

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


      6) Here is the output when the servlet code is accessed:

      ************* JBoss Output snippet -- START
      ...
      15:34:52,932 INFO [RequestProcessor] Processing a 'GET' for path '/admin/listCatalogItems'
      15:34:53,025 INFO [ListCatalogItemsAction] execute()
      15:34:53,025 INFO [STDOUT] Created LoginContext
      15:34:53,057 INFO [STDOUT] Logged in.
      15:34:53,072 INFO [STDOUT] principle: org.jboss.security.SimplePrincipal jkuhn
      15:34:53,072 INFO [STDOUT] principle: org.jboss.security.NestableGroup Roles(members:Echo)
      15:34:53,072 INFO [STDOUT] About to create CatalogManagementLocal
      15:34:53,088 ERROR [SecurityInterceptor] Insufficient method permissions, principal=null, method=create, interface=LOCALHOME, requiredRoles=[Echo], principalRoles=[]
      15:34:53,088 ERROR [LogInterceptor] EJBException, causedBy:
      java.lang.SecurityException: Insufficient method permissions, principal=null, method=create, interface=LOCALHOME, requiredRoles=[Echo], principalRoles=[]
      at org.jboss.ejb.plugins.SecurityInterceptor.checkSecurityAssociation(SecurityInterceptor.java:214)
      at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:81)
      .......

      ************* JBoss Output snippet -- END



      Notice that the login is successful. If you look at the JBoss output,
      you can see that it says "Logged in." (as per the debug output).

      Another reason that I know the login is successful, is that if I
      remove the "jkuhn" user from the "principals" table in the database,
      then the login fails.

      So, I'm comfident that I've logged in. However, when execution is
      attempted on the line of code that is a trying to "create()" an EJB,
      I get the exception.

      Can anybody tell me what I'm missing?


      Thanks.


        • 1. Re: classic "principal=null".
          tthiele

          hmmm... I think there is this missing in your application-policy as the last login-module:

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

          • 2. Re: classic "principal=null".
            jkuhn

            I'll try adding it, but ...

            Isn't the ClientLoginModule used for authentication using
            .properities file? I mean, doesn't my DatabaseServerLoginModule
            replace the ClientLoginModule?... because my user info
            is being persisted in the DB, not in the .properties files.


            • 3. Re: classic "principal=null".
              jkuhn

              Wow. That did it. Thanks a bunch.

              Can somebody explain to me why I need both the DatabaseServerLoginModule and
              the ClientLoginModule?

              Thansk again.


              • 4. Re: classic "principal=null".
                tthiele

                The ClientLoginModule places the principals and credentials which are aquired by the previous login module(s) in a magic way to a magic place where bean invocation mechanism passes them to the container resp. beans. I suppose the security information is associated with the Thread object. But I don't know the details. Can someone give a pointer to the documentation (not the java sources)?

                • 5. Re: classic "principal=null".

                  > The ClientLoginModule places the principals and
                  > credentials which are aquired by the previous login
                  > module(s) in a magic way to a magic place where bean
                  > invocation mechanism passes them to the container
                  > resp. beans. I suppose the security information is
                  > associated with the Thread object. But I don't know
                  > the details. Can someone give a pointer to the
                  > documentation (not the java sources)?

                  I can't, but i can confirm that your assumptions are correct. Please note JKuhn that this can lead to suprising effects in your web application, because most servlet containers use thread-pooling ;-). So the next request might behave as not logged in, whereas requests that you are supposing are not logged in, seem to do....

                  Hth
                  Peter

                  • 6. Re: classic "principal=null".
                    deanwampler

                    Shouldn't
                    ' <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule"
                    flag="sufficient">'

                    have "requisite" or maybe "required" in this tag?

                    • 7. Re: classic
                      leondavis

                      I have been having this exact problem, and this has been the post to solve it for me. I do have one further problem though.
                      I currently have code that uses the ClientLoginModule and also the DatabaseServerLoginModule. having taken the advice to put:

                      <login-module code = "org.jboss.security.ClientLoginModule" flag = "required"> </login-module> in my aplication-policy, it does indeed make the db authentication works properly.

                      However when I use the the other policy that uses the ClientLoginModule exclusively:

                      <application-policy name = "client-login">

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

                      </application-policy>

                      I recieve "Authentication exception, principal=null" for opperation that login with this and then perform some EJB operation.
                      If I remove the application policy that uses the DatabaseServerLoginModule then the code using "client-login works, and putting back in breaks it again.

                      This is the policy that I have hashed together to enable the database login:

                      <application-policy name="bank">

                      <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">
                      <module-option name="dsJndiName">java:/DefaultDS</module-option>
                      <module-option name="principalsQuery">select PASSWORD from USEREJB where USERNAME=?</module-option>
                      <module-option name="rolesQuery">select ROLESEJB,'Roles' from USEREJB_ROLES_ROLESEJB_USER where USEREJB=?</module-option>
                      </login-module>
                      <login-module code = "org.jboss.security.ClientLoginModule" flag = "required"> </login-module>

                      </application-policy>


                      The reason that I use both methods is because I have code the populates a HyperSonic database with initial Role and User account, I do this with the client-login policy. From then onwards I use the DatabaseServerLoginModule policy.

                      I am pretty new to all of this so be gentle, I am sure that there is something blindingly obvious for why it is not working, I just can't see it. Therfore I look to anyone that can give me the answer :)

                      If I need to post any more information then just say.

                      Many thanks,
                      Leon

                      • 8. Re: classic
                        phantom

                        thank you for this topic. It's quite interesting, becaus I found the answer to the quiestion which I tryid to resolve very long time.
                        JBOSS developers can you highlight this quiestion in JBOSS JAAS documentation?

                        Thank you!

                        • 9. Re: classic
                          leondavis

                          Sorry to seem like a pain, but has anyone had a chance to consider the problem that I have raised two messages above this one? I still have not solved my problem and would really apreciate some help.

                          Many thanks,
                          Leon

                          • 10. Re: classic
                            montia

                            Hi,

                            I think I understand what you're trying to achieve but I don't understand why you'd invoke the ClientLoginModule twice. I would use only one application policy, your "bank" one with a slight modification: invoke the ClientLoginModule first, and then the DatabaseServerLoginModule.

                            <application-policy name="bank">

                            <login-module code = "org.jboss.security.ClientLoginModule" flag = "required"> </login-module>
                            <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">
                            <module-option name="dsJndiName">java:/DefaultDS</module-option>
                            <module-option name="principalsQuery">select PASSWORD from USEREJB where USERNAME=?</module-option>
                            <module-option name="rolesQuery">select ROLESEJB,'Roles' from USEREJB_ROLES_ROLESEJB_USER where USEREJB=?</module-option>
                            </login-module>

                            </application-policy>

                            At least that's what I'm doing for my form-based DatabaseServerLoginModule authentication.

                            If this doesn't work, why not try to put the code that populates a HyperSonic database with initial Role and User account after you detect that the Database login failed? I don't know if this is what you want since I don't know if you're checking against files that hold valid initial Role and User account information with your client-login policy. In case you do, then why not have that information in the DB to start with?

                            Just a couple of ideas. :) I'm no expert either.

                            Oh, this link proved quite helpful when I got started configuring JAAS security on my application: http://forum.java.sun.com/thread.jsp?forum=60&thread=452691&tstart=null&trange=null

                            Good luck!

                            • 11. Re: classic
                              leondavis

                              Thanks for your reply, I have done what you said. However I am still having problems.

                              The user that I have in my users.properties file are able to login and perform operations using beans. So I therefore created another user that is only in the hypersonic database, that user has roles setup for it too. When trying to login with that user I get:


                              org.apache.cactus.client.ServletExceptionWrapper: checkSecurityAssociation; CausedByException is:
                              Authentication exception, principal=leon
                              javax.ejb.EJBException: checkSecurityAssociation; CausedByException is:
                              Authentication exception, principal=leon
                              at org.jboss.ejb.plugins.SecurityInterceptor.checkSecurityAssociation(SecurityInterceptor.java:165)

                              Its like the DatabaseServerLoginModule is not authenticating the user, why would this be?

                              • 12. Re: classic
                                starksm64

                                Turn on debug level logging on the org.jboss.security category and see what is going on in the server.log. Add the following

                                 <!-- Limit JBoss categories to INFO -->
                                 <category name="org.jboss">
                                 <priority value="INFO"/>
                                 </category>
                                
                                 <category name="org.jboss.security">
                                 <priority value="DEBUG"/>
                                 </category>
                                
                                



                                • 13. Re: classic
                                  mthoma

                                  Hi

                                  Using the DatabaseServerLoginModule, I'm facing the following strange behaviour: The login works fine, the user is authenticated against the values from the database, and he is assigned to the correct role. But when the user tries to call an EJB method, the DatabaseServerLoginModule receives a logout information immediately before this EJB call:


                                  2004-09-14 21:29:15,156 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] initialize
                                  2004-09-14 21:29:15,156 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] Saw unauthenticatedIdentity=ExternalUser
                                  2004-09-14 21:29:15,156 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] DatabaseServerLoginModule, dsJndiName=java:/RRSDataSource
                                  2004-09-14 21:29:15,156 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] principalsQuery=select password from rrsUser where name=?
                                  2004-09-14 21:29:15,156 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] rolesQuery=select role, 'Roles' from rrsUser where name=?
                                  2004-09-14 21:29:15,156 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] login
                                  2004-09-14 21:29:15,156 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] User 'admin' authenticated, loginOk=true
                                  2004-09-14 21:29:15,156 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] commit, loginOk=true
                                  2004-09-14 21:29:15,156 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] Assign user to role Administrator
                                  2004-09-14 21:29:15,156 TRACE [org.jboss.security.plugins.JaasSecurityManager.rrs-security] updateCache, subject=Betreff: Principal: admin
                                  Principal: Roles(members:Administrator)
                                  2004-09-14 21:29:15,156 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] logout
                                  2004-09-14 21:29:15,171 ERROR [org.jboss.ejb.plugins.SecurityInterceptor] Insufficient method permissions, principal=admin, method=create, interface=HOME, requiredRoles=[Administrator, InternalUser], principalRoles=null


                                  Because of this logout, the user seems not to 'have' his role any more (in this case Administrator, which would be one of the allowed role to call the EJB method).


                                  My login-config looks like that:


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

                                  <login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule"
                                  flag = "required">
                                  <module-option name = "dsJndiName">java:/RRSDataSource</module-option>
                                  <module-option name = "principalsQuery">select password from rrsUser where name=?</module-option>
                                  <module-option name = "rolesQuery">select role, 'Roles' from rrsUser where name=?</module-option>
                                  <module-option name = "unauthenticatedIdentity">ExternalUser</module-option>
                                  </login-module>
                                  <login-module code = "org.jboss.security.ClientLoginModule"
                                  flag = "required">
                                  </login-module>

                                  </application-policy>


                                  Does anybody encounter the same problem with this logout? I'm using JBoss 4.0 RC2.

                                  • 14. Re: classic
                                    mthoma

                                    I managed to eliminate the logout problem; it was a misconfiguration within my web.xml file. The web page calling the EJB method was not within the restricted area any more, that's why a logout was performed.

                                    Now the first EJB method call is successful, but as soon as I want to start a second call, the login page (declared in web.xml) is presented again. The user has to authenticate himself for every call, the principal/subject-information seems to get lost after every EJB call.
                                    I'm using JavaServer Faces, with lots of backing beans, and most of them have to perform some EJB calls --> how do I manage to pass the security information along to keep the authentication?

                                    Any help would be really appreciated.

                                    1 2 Previous Next