5 Replies Latest reply on Feb 27, 2006 1:03 PM by Scott Stark

    ClientLoginModule/SecurityAssociation interaction

    Scott Stark Master

      A discussion thread for the http://jira.jboss.com/jira/browse/JBAS-2820 issue.

        • 1. Re: ClientLoginModule/SecurityAssociation interaction
          Scott Stark Master

           

          "Luigi Putanesca" wrote:

          I found one more aspect to this problem. The ClientLoginModule maintains its own copy of Subject and adds/removes Principals to it. This can also get out of sync with the SecurityAssociation stack because Subject.getPrincipals is a Set. If the same user is logged in more than once, it can only appear in the set once and after the logout is removed when it should still be in there. So I made the following changes to the commit(), abort() and logout() methods. I'm not positive of what state the Subject should be in when no user is logged in so I cleared the Principals Set. Making the Subject null caused problems.

           public boolean commit() throws LoginException {
           // Set the login principal and credential and subject
           SecurityAssociation.pushSubjectContext(subject, loginPrincipal, loginCredential);
           SecurityAssociation.SubjectContext ctx = SecurityAssociation.peekSubjectContext();
           if (ctx != null) {
           subject = ctx.getSubject();
           }
          
           return true;
           }
          
           public boolean abort() throws LoginException {
           /* Changed here. Only clear if not restoring identity. */
           if (restoreLoginIdentity) {
           SecurityAssociation.popSubjectContext();
           SecurityAssociation.SubjectContext ctx = SecurityAssociation.peekSubjectContext();
           if (ctx != null) {
           subject = ctx.getSubject();
           }
           else {
           subject.getPrincipals().clear();
           }
           }
           else {
           SecurityAssociation.clear();
           subject.getPrincipals().clear();
           }
          
           return true;
           }
          
           public boolean logout() throws LoginException {
           /* Changed here. Only clear if not restoring identity. */
           if (restoreLoginIdentity) {
           SecurityAssociation.popSubjectContext();
           SecurityAssociation.SubjectContext ctx = SecurityAssociation.peekSubjectContext();
           if (ctx != null) {
           subject = ctx.getSubject();
           }
           else {
           subject.getPrincipals().clear();
           }
           }
           else {
           SecurityAssociation.clear();
           subject.getPrincipals().clear();
           }
          
           return true;
           }
          




          • 2. Re: ClientLoginModule/SecurityAssociation interaction
            Scott Stark Master

            The ClientLoginModule cannot remove more than it put into the subject. If the principals are not differentiated correctly then there is a conflict. Describe the real issue as I'm not inclined to accept these changes.

            • 3. Re: ClientLoginModule/SecurityAssociation interaction
              Scott Stark Master

               

              "Luigi Putanesca" wrote:

              Well perhaps that isn't the best way to address the issue. I'm not 100% certain of how the ClientLoginModule.subject is used. However here's a more specific situation. A servlet is invoked and logs in a user, say "admin". The servlet calls an ejb. The ejb not necessarily knowing where it is called from logs in the same user because it is needed and when done with its work logs out and we return to the servlet.

              If you look at what's in the principals set, first we have "admin" and after the second login it is still "admin". After the first logout the principals set is empty even though the "admin" user is the current principal after being restored.

              Currently I don't have an error occuring because of this however if some code is expecting that the current principal is in the subject.getPrincipals() set, it seems like an error may be lurking waiting for the right circumstance.

              Perhaps the best way to fix it is something like below. First you pop the principal info. Then you remove it from the local subject. Then re-add the current principal (if any) into the local subject. If the principal is already there, since it is a set there is no harm done as it only maintains one copy of the item. If the principal is not there then it is added and we are in sync.
               Principal p = null;
               if( restoreLoginIdentity == true )
               {
               SecurityAssociationActions.popPrincipalInfo();
               p = SecurityAssociation.getPrincipal();
               }
               else
               {
               // Clear the entire security association stack
               SecurityAssociationActions.clear();
               }
               Set principals = subject.getPrincipals();
               principals.remove(loginPrincipal);
              
               /* re-add the current principal here if applicable */
               if (p != null) {
               principals.add(p);
               }
              




              • 4. Re: ClientLoginModule/SecurityAssociation interaction
                Scott Stark Master

                 

                "Luigi Putanesca" wrote:

                One more thought on this. One problem with my solution above is say you login as "a", then as "b" and login again as "a". When "a" logs out the first time, it is removed from the set and only "b" remains. When "b" logs out, "a" is put back in this list. However after the first logout, both "a" and "b" should be in the list. Almost seems like these principals should be stored in a stack.


                • 5. Re: ClientLoginModule/SecurityAssociation interaction
                  Scott Stark Master

                  This sounds like a broken usage of the ClientLoginModule. The subject in a ClientLoginModule is simply the subject passed to its ctor. This is either the subject passed to the LoginContext or a new subject created by LoginContext. If you do:

                  Subject s = new Subject();
                  LoginContext lc = new LoginContext("config", handler("a",...), s);
                  lc.login();
                  LoginContext lc = new LoginContext("config", handler("b",...), s);
                  lc.login();
                  LoginContext lc = new LoginContext("config", handler("a",...), s);
                  lc.login();
                  


                  you have choosen to overwrite the subject contents. If you want stack behavior, each login has to use a new subject.