4 Replies Latest reply on Feb 12, 2003 4:48 PM by donlind

    principal=null (like so many others... sigh)

    donlind

      I'm sorry this is such a long post. But I've tried a *lot* of stuff already, and I wanted to give enough details so that someone might be able to help.

      I'm using JBoss 3.0.5 with Jetty.

      I've purchased the "real" docs (and read the JAAS stuff about 4 times). I've read the various javaworld articles on JBoss and JAAS.... I have read just about everything concerning JAAS in these forums. I'm almost embarassed to say, but I've been wrestling with this for several weeks now. OK, three weeks. Sigh.

      My main problem *seems* to be this: I can't get my EJB to see/use my JAAS Subject (and credentials).

      Many of the JAAS tutorials simply have a JSP create a LoginContext, log in, and then display the credentials on the response html page. That's easy. :-) I can do that. What I can't (so far) do is to get the credentials propagated to an EJB.

      Background:

      I have written a JCA adapter that connects to a real back-end EIS. The EIS requires a user/password pair to build a JCA connection. The JCA adapter receives a user/password (in standard a ConnectionRequestInfo parameter) and gets a good connection. This all works just fine. Essentially, my JCA adapter works just fine when I don't try to use JAAS.

      My JCA adapter, in lieu of an explicit ConnectionRequestInfo, is also coded to be able to take a JAAS Subject object when an application requests a connection. The app server's JCA Connection Manager is supposed to pass in the JAAS Subject object as part of a JCA getConnection call. I'm trying to test this now.

      For test purposes, I have a simple JSP that accepts a user/password, creates a login context, and successfully gets authenticated to our EIS using the JAAS stuff. After the login() method call, I can see (via traces and debug stuff) that, from the JSP's viewpoint, there is a good, live subject, principal, and credential, and that I've actually connected to our EIS.

      We happen to have a custom Login Module (but I don't think that's part of the problem I'm having, though). Our login method makes use of the normal callback mechanism to get a user/password pair (which works fine when called from the JSP). It then authenticates the information (logs the user onto the EIS), and stores, as the credential, an object that gives us access to the EIS.

      But, right now, the JSP can't even create the bean's home interface. This is failing with:
      15:04:13,125 ERROR [SecurityInterceptor] Authentication exception, principal=null
      15:04:13,125 ERROR [LogInterceptor] EJBException, causedBy:
      java.lang.SecurityException: Authentication exception, principal=null
      at org.jboss.ejb.plugins.SecurityInterceptor.checkSecurityAssociation(SecurityInterceptor.java:173)
      at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:94)
      at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:129)
      at org.jboss.ejb.StatelessSessionContainer.invokeHome(StatelessSessionContainer.java:300)

      As an aside, if I edit my jboss.xml file and delete the line that reads "<security-domain>java:/jaas/eProcessRealm</security-domain>" I can get past the JSP calling home.create() error. But, the EJB still never sees any Principal or credentials, and I fail downstream with a very similar security exception complaining about "principal=null" when the EJB tries to get the JCA connection.

      I suspect I have a configuration issue in one of the many deployment XML files (and, maybe an issue with my expectations of JAAS). What I *want*, logically, is that a user "logs in" once, and that his credentials then get automatically "applied" on all ejb method calls made by the user. In my mind, the app server would have to tie the JAAS Subject (including the credentials) to the web-users's "web session" or something.

      Anyway, I think my main issue is that the JSP sees the credentials, but can't get them passed over to the EJB (stateless session bean).

      This whole exercise is just a test to verify that my JCA Adapter works with JAAS. I'm not an EJB expert. And I'm trying to keep this really simple (ha ha...)

      I have tried a *lot* of different things... Like an earlier poster, I also need "roles" as much as a fish needs a bicycle. But, since things weren't working without them, I've defined a single (bogus) role and I've tried to propagate it appropriately through the various XML files.

      At first, I just had a single realm that included my own custom login module. I configured that realm in the XML files. Now, having read more of the documentation, I've got the JSP (the client) using a realm that includes the ClientLoginModule in hopes of getting the user/password information sent over to the EJB's enviornment. This hasn't helped, though. I've configured and tried realms that include various combinations of the UsersRolesLoginModule, the ClientLoginModule, and my own login module.

      As a sidelight, my own login module seems to be working because after the JSP goes through the normal JAAS login stuff, the JSP sees a good subject, credentials, and principals. And I can see a live connection to our EIS.

      I have put info into the users.properties and roles.properties for the attempts involving the UsersRolesLoginModule. Although, in our environment, it makes no sense to duplicate the login information that's already managed by our EIS into these properties files.

      So, through everything I've tried, what I'm seeing is that the JSP seems very happy. As I try various different login.config settings, I can see the JSP using the various login modules and the subject, principals, and credentials are all looking good (from the JSP's viewpoint). And, when using the ClientLoginModule, the JSP can fetch the values for org.jboss.security.SecurityAssociation.principal and .credential and they look appropriate.

      But in all cases, I end up with a "principal=null" authentication error. Oh, I've also tried doing a "Subject.doAs(...)" in the JSP when I call the EJB... that doesn't help, either.

      I must be missing something. If someone can give me a hint as to where I need to be looking, that'd be great.

      Here are some JAAS-related excerpts from the deployment XML files. Maybe someone will see a dumb mistake...:

      jboss-web.xml
      <security-domain>java:/jaas/eProcessRealm</security-domain>

      web.xml

      <security-role-ref>
      <role-name>Any</role-name>
      <role-link>Any</role-link>
      </security-role-ref>

      <security-constraint>
      <web-resource-collection>
      <web-resource-name>test stuff</web-resource-name>
      <url-pattern>/test/*</url-pattern>
      </web-resource-collection>
      <auth-constraint>
      <role-name>Any</role-name>
      </auth-constraint>
      <user-data-constraint>
      <transport-guarantee>NONE</transport-guarantee>
      </user-data-constraint>
      </security-constraint>
      <login-config>
      <auth-method>BASIC</auth-method>
      <realm-name>eProcessRealm</realm-name>
      </login-config>
      <security-role>
      <role-name>Any</role-name>
      </security-role>

      ejb-jar.xml
      <security-role-ref>
      <role-name>Any</role-name>
      <role-link>Any</role-link>
      </security-role-ref>
      <method-permission>
      <role-name>Any</role-name>

      <ejb-name>TestBean</ejb-name>
      <method-name>create</method-name>

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

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

      </method-permission>

      jboss.xml
      <security-domain>java:/jaas/eProcessRealm</security-domain>

      login-config.xml
      <application-policy name = "eProcessRealm">

      <login-module code = "filenet.vw.server.VWLoginModule" flag = "required">
      <module-option name = "routerurl">rmi://don:32771/vwrouter</module-option>
      </login-module>

      </application-policy>

      <application-policy name = "eProcessClientRealm">

      <login-module code = "org.jboss.security.auth.spi.UsersRolesLoginModule" flag = "required">
      </login-module>
      <login-module code = "filenet.vw.server.VWLoginModule" flag = "required">
      <module-option name = "routerurl">rmi://don:32771/vwrouter</module-option>
      </login-module>
      <login-module code = "org.jboss.security.ClientLoginModule" flag = "required">
      </login-module>

      </application-policy>

      Thanks!

      Don

        • 1. Re: principal=null (like so many others... sigh)
          blowagie

          I am using jBoss3.0.6 with Jetty.
          I had the same problem you had.

          I solved it like this:
          I have a securityDomain JspSecurity
          and in the login-config.xml, I have this:
          <application-policy name = "JspSecurity">

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

          </application-policy>

          I log in with in the JSP page like this:

          char[] password = {'j', 's', 'p'};
          LoginContext lc = new LoginContext("JspSecurity",new MyCallbackHandler("jsp", password));
          lc.login();

          The ClientLoginModule is used, so there is NO checking
          of username and password at this moment.

          The EJB is in another security domain:
          <application-policy name = "EjbSecurity">

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

          </application-policy>

          The credentials are passed from the JspSecurity domain
          to the EjbSecurity domain and they are checked by
          the UsersRolesLoginModule when I do this:

          InitialContext ctx = new InitialContext();
          MyHome home = (MyHome) ctx.lookup(MyHome.JNDI_NAME);
          MyRemote remote = home.create();

          So you NEED 2 different security domains:
          one for your client (the JSP page)
          and one for your server (the EJB)

          HTH,
          Bruno

          • 2. Re: principal=null (like so many others... sigh)
            blowagie

            I am using jBoss3.0.6 with Jetty.
            I had the same problem you had.

            I solved it like this:
            I have a securityDomain JspSecurity
            and in the login-config.xml, I have this:
            <application-policy name = "JspSecurity">

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

            </application-policy>

            I log in with in the JSP page like this:

            char[] password = {'j', 's', 'p'};
            LoginContext lc = new LoginContext("JspSecurity",new MyCallbackHandler("jsp", password));
            lc.login();

            The ClientLoginModule is used, so there is NO checking
            of username and password at this moment.

            The EJB is in another security domain:
            <application-policy name = "EjbSecurity">

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

            </application-policy>

            The credentials are passed from the JspSecurity domain
            to the EjbSecurity domain and they are checked by
            the UsersRolesLoginModule when I do this:

            InitialContext ctx = new InitialContext();
            MyHome home = (MyHome) ctx.lookup(MyHome.JNDI_NAME);
            MyRemote remote = home.create();

            So you NEED 2 different security domains:
            one for your client (the JSP page)
            and one for your server (the EJB)

            HTH,
            Bruno

            • 3. Re: principal=null (like so many others... sigh)
              donlind

              Thanks for the suggestion! I'm not out of the woods just yet, but it's triggered me to try some things that have helped.

              First, I've adjusted my login.config as you suggested:

              <application-policy name = "eProcessRealm">

              <login-module code = "org.jboss.security.ClientLoginModule"
              flag = "required">
              </login-module>
              <login-module code = "org.jboss.security.auth.spi.UsersRolesLoginModule"
              flag = "required">
              </login-module>
              <login-module code = "filenet.vw.server.VWLoginModule"
              flag = "required">
              <module-option name = "routerurl">rmi://don:32771/vwrouter</module-option>
              </login-module>

              </application-policy>

              <application-policy name = "eProcessClientRealm">

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

              </application-policy>

              I'd tried that before. But, by itself, it doesn't resolve my problem.

              BUT... I added some more 'debug' stuff to my JSP and I found that I was being bitten by something that I figured I could ignore 'till later.

              Within a single JSP, I was handling separate 'actions' (or states)... First, a "logon" form was presented and a button was pushed. This went to a "validate" part of the JSP which successfully created the LoginContext. Then, I would click a button that caused a particular "report/query" to be executed. The "report/query" hit/state part of the JSP would still see the same "subject" information that was set up on the previous "validate" hit (when I had the JSP logging on to a realm that included login modules in addition to the ClientLoginModule).

              But, as I just learned with some fresh debug stuff, the "report/query" page hit *doesn't* see the org.jboss.security.SecurityAssociation.credential information created on the previous hit by the ClientLogonMenu stuff.

              I knew this would probably be an issue in a "real" environment, but I thought (stupidly) that I could get away with it for a single-user test. I think I need to figure out the nuances of a Stateless bean vs. the JAAS stuff which kind of is supposed to supply me the credentials (which I kind of think of as state information). Anyway...

              So, I've combined my JSP's "validate" and "report/query" steps (states) into a single step. And now, because the org.jboss.security.SecurityAssociation.principal contains the "right" information, I get further. (I'd tried combininbg these steps a couple of weeks ago, but without the appropriate login.config realms, so it didn't help back then... sigh).

              My "principle=null" problem was due to the org.jboss.security.SecurityAssociation.principle being null rather than the Subject's principal being null. I kept fixating on the Subject, which wasn't really the problem.

              So, now, I'm getting a "SecurityException: Authentication exception, principal=SysAdmin". I still have a problem, but at least I appear to be past my original problem.

              THANKS!!!!!!! I think I'm on my way again.

              Don

              • 4. Re: principal=null (like so many others... sigh)
                donlind

                It all works for me, now.

                Just to close the loop on this one, the last problem I had was that it seems that trailing spaces in the roles.properties and users.properties files are significant. That is, if a line in my roles.properties file reads "joe=Any " (without the quotes, of course), JBoss decides my role is "Any " which is different from "Any". Interesting... and relatively easy to figure out because of the text of the exceptions that are thrown.

                Another snag was that when JBoss uses the name and password gathered by the ClientLogonModule to automatically feed the LogonModules defined in the EJB's JAAS realm, JBoss's callback handler doesn't support the TextOutputCallback (which my custom LoginModule used). This wasn't obvious (to me, anyway) until I turned on the JBoss tracing... The "TextOutputCallback not supported" exception that was thrown was trapped and a more generic "logon failure" message is all the showed up on the console. But, in the traces it was relatively easy to spot the "hidden" exception, and a quick peek at the JBoss sources confirmed that, indeed, it didn't support that callback. No biggie, I guess... I'm happy.

                Hope this info might help someone in the future. I know I've been helped by the other posts...

                Thanks!

                Don