6 Replies Latest reply on Mar 22, 2006 9:04 AM by j2ee_junkie

    Standalone Tomcat to JBoss - SecurityAssociation mixup

    jaco.joubert

      Hi,

      Could someone please clarify this for me?
      I've got the following situation:

      Standalone standard Tomcat 4.1.29 with a couple of secured pages and FORM based login.
      I'm using the JAASRealm in Tomcat to perform authentication through JAAS. As part of this authentication, I'm using my own Login module, as well as the JBoss ClientLoginModule.

      In the separate JBoss (4.0.2), I'm running a couple of secured EJBs.
      The EJBs are configured to use only my custom Login module for authentication (the same login module I'm using in the separate Tomcat).

      Authentication works fine and I'm able to login in Tomcat and call the secured EJB methods. JBoss also picks up the user principal coming from Tomcat correctly.

      The problem occurs when a couple of users are using the web interface simultaneously. I would then get weird behaviour. As an example:
      1. User1 logs in via web and execute EJB method as User1 successfully.
      2. User2 logs in via another browser and execute EJB method as User2 successfully.
      3. User1 (still logged in) would execute the EJB method again, but this time it executes as User2 (last logged-in user)!

      All I can see is that the JBoss ClientLoginModule populates the SecurityAssociation which is propagated to JBoss on EJB calls, but the security contexts are stored inside the SecurityAssociation on a per-thread basis. This would obviously be a problem in my scenario, as the threads inside Tomcat are shared between all the clients.
      I basically need a SecurityAssociation per user session (and not client thread), as I'm never guaranteed which Tomcat thread would service my request?

      My ClientLoginModule is configured with multi-threaded=true

      Do I understand the problem correctly, or am I just missing a configuration option somewhere?
      Let me know if I should post more of my current configuration as well.

        • 1. Re: Standalone Tomcat to JBoss - SecurityAssociation mixup
          j2ee_junkie

          jaco,

          From you post below, I would say you understand the problem really well. JBoss's SecurityAssociation is set with principal and credential info (note that the use of SecurityAssocation is just what currently happens, but is non-public and should not be counted on.) But this is a ThreadLocal variable that is only good for that thread, and for the login thread. When user makes subsequent request, you need to associate the principal and credentails to that new thread. In the embedded version of Tomcat, there is the org.jboss.web.tomcat.security.SecurityAssocationValve that automatically gets added to your request pipeline. This class sets SecurityAssocation's principal and credential from that stored in the user's session. Since I have never used Tomcat separately, I can not say for sure what you will have to make this all jive. But I would start by using org.jboss.web.tomcat.security.JBossSecurityMgrRealm as your realm (if you want to share security domains between your war and ejbs) and then the add org.jboss.web.tomcat.security.SecurityAssocaitionValve to your pipeline. Again, I am not 100% on this. If anyone else has a comment that would be good. Hope this works!

          Let us know, cgriffith

          • 2. Re: Standalone Tomcat to JBoss - SecurityAssociation mixup
            jaco.joubert

            I appreciate the quick response.

            You've put me on the right track now. I'll play around with the above-mentioned concepts and post my findings again.

            • 3. Re: Standalone Tomcat to JBoss - SecurityAssociation mixup
              jaco.joubert

              Hi,

              Although there are a couple of things still unclear to me in the Tomcat environment, I got this working.

              I don't really need this, but I battled to get it working by implementing a Tomcat Valve. I guess it has to do with the order in which Tomcat invokes the configured valves, but in my Valve, when I look at the request.getUserPrincipal, it's always null. Looks like it's only assigned after my Valve has been invoked. What is strange is that the standard Tomcat SingleSignOn Valve is able to extract this information if I add that to the configuration, but I can't?

              Anyway, I got this working by doing the following:
              1. Use normal FORM-based login in Tomcat.
              2. Create my own cache of logged-in users. This is a static HashMap on some class, storing the full subject, user principal and credentials of each logged-in user.
              3. Create my own Tomcat Realm. This Realm extends the Tomcat Realm I used before. It only adds functionality to cache the logged-in user in the already-mentioned cache after each successful login.
              4. Add a normal Filter which extracts the request.getUserPrincipal from each request. If there is a principal (user is logged in), extract the user's information from the cache and populate the JBoss SecurityAssociation:

              SecurityAssociation.setServer();
              SecurityAssociation.setPrincipal(cachedUser.principal);
              SecurityAssociation.setCredential(cachedUser.credential);
              


              The filter then forwards the request where these associations could possible be used by remote invocations. After the call, the associations for the thread is cleared again with SecurityAssociation.clear();

              As a safeguard to ensure that my cached users store does not grow forever, I also add an attribute in the user's session which indicates his logged-in username. I then add an AttributeListener in Tomcat which would remove the user from the cache as soon as this attribute is cleared (session invalidated or expired).

              I know this might not be the most robust solution and is very dependant on how JBoss handles security propagation at the moment, but it seems to be working fine.

              I'm sure it has to do with classloaders, but I also had to make sure that I only have one instance of the security classes (like SecurityAssociation) in Tomcat. Don't bundle with your webapp for example. Rather leave only one instance in common/lib.


              • 4. Re: Standalone Tomcat to JBoss - SecurityAssociation mixup
                cssmith4

                 

                "j2ee_junkie" wrote:
                jaco,

                From you post below, I would say you understand the problem really well. JBoss's SecurityAssociation is set with principal and credential info (note that the use of SecurityAssocation is just what currently happens, but is non-public and should not be counted on.) But this is a ThreadLocal variable that is only good for that thread, and for the login thread. When user makes subsequent request, you need to associate the principal and credentails to that new thread.

                In the embedded version of Tomcat, there is the org.jboss.web.tomcat.security.SecurityAssocationValve that automatically gets added to your request pipeline (Are you sure? Where and how is this done? Which desriptor defines this valve?. This class sets SecurityAssocation's principal and credential from that stored in the user's session Stored under what keys?. Since I have never used Tomcat separately, I can not say for sure what you will have to make this all jive how to make this work if they are running in same jboss server w/ webapp in separate war and ejb in ejb3 archive?. But I would start by using org.jboss.web.tomcat.security.JBossSecurityMgrRealm as your realm (if you want to share security domains between your war and ejbs) and then the add org.jboss.web.tomcat.security.SecurityAssocaitionValve to your pipeline You mentioned above this is done automatically? Is this a contradiction?. Again, I am not 100% on this. If anyone else has a comment that would be good. Hope this works!

                Let us know, cgriffith

                I've been working on this forever. Thanks for all help.

                Much thanks, Shane





                • 5. Re: Standalone Tomcat to JBoss - SecurityAssociation mixup
                  anil.saldhana

                  You are not forced to use the direct contract on SecurityAssociation, in your client programs. You can specify the ClientLoginModule in your jaas config on the client side.

                  http://wiki.jboss.org/wiki/Wiki.jsp?page=ClientLoginModule

                  • 6. Re: Standalone Tomcat to JBoss - SecurityAssociation mixup
                    j2ee_junkie

                    cssmith4,

                    Sorry, I though I responded to your questions. Must of got sidetracked.


                    1: SecurityAssociationValve gets added to pipeline by TomcatDeployer

                    2: The Principal is not necessarily stored under any key. The Tomcat Session implementation has a Principal object that gets set to the authenticated Principal.

                    3: RTFM

                    4: No, it is not a contradiction if jaco is using a separated Tomcat instance, and my comments are describing the embedded instance.


                    If you are having problems, and you have read documentation, start a thread. cgriffith