8 Replies Latest reply on May 21, 2003 6:34 AM by cobraflow

    Principal 'Adournment'...

    cobraflow

      Hi,

      I am looking for the 'best' way to do this..

      The 'standard' login modules create SimplePrincipal and SimpleGroup instances...

      So I have (by default)

      SimplePrincipal('user')
      SimpleGroup('roles')
      ....SimplePrincipal('role1')
      ....SimplePrincipal('role2')
      SimpleGroup('callerPrincipal')
      ....SimplePrincipal('caller')

      ...Now what I would like to do is to add some attributes to these principals. I could, for example, extend the 'DatabaseServerLoginModule' creating AttributePrincipal's instead of 'SimplePrincipal's populating from extra columns in the SELECTs, or extend the 'LdapLoginModule' to add any attribues

      OR

      I could add another 'login-module' to the 'authentication' which picks up the current subject and replaces the Principals (and Groups) with my new 'AttributePrincipal's.

      AttributePrincipal('user','phone',...)
      SimpleGroup('roles')
      ....AttributePrincipal('role1','manager',...)
      ....AttributePrincipal('role2','manager',...)
      SimpleGroup('callerPrincipal')
      ....SimplePrincipal('caller')

      The disadvantage to the second method is that I would need to reconnect to the DataSource (or LDAP) and perform very similar queries to the first login module.


      I am just looking for a 'sanity' check here...


      ...just as an asside, is there a 'standard' way to get at the Subject from a HttpRequest and from inside an EJB? Other than :-

      JaasSecurityManager manager = new SecurityManager();
      Subject subject = manager.getActiveSubject();

      OR

      Subject subject = SecurityAssociation.getSubject();

      Lewis

        • 1. Re: Principal 'Adournment'...

          Please note that custom-made principals objects will not show up in the servlet container, i.e. request.getRemoteUser() will never return your AttributePrincipal, due to the authorization mechanism in jetty / jboss-jetty integration. Lately, there have been several questions about this in this forum (see for example http://www.jboss.org/modules/bb/index.html?module=bb&op=viewtopic&t= it doesn't help of course ;-) but maybe it saves you some frustration....;-)
          Peter.

          • 2. Re: Principal 'Adournment'...

            correction: that should be request.getUserPrincipal() of course....

            • 3. Re: Principal 'Adournment'...
              cobraflow

              ...I'm using Tomcat...I have not checked it yet.

              I do get the 'correct' principals in my EJB's...half way there!

              Is there no standard way of getting this 'extra' information?

              If this is of any use to anyone, I have extended the DatabaseServerLoginModule to add attributes to the Principals. This is done by extending the principalQuery with extra columns (the first is always the 'credentials' the rest are added as attributes to the Principal. I have done the same for 'roles' where the rolesQuery has two mandatory coumns (role and rolegroup), the any extra columns are added as attributes....

              I'm now moving on to do the same for LDAP!


              Lewis

              • 4. Re: Principal 'Adournment'...

                > ...I'm using Tomcat...I have not checked it yet.

                See http://www.jboss.org/modules/bb/index.html?module=bb&op=viewtopic&t= same issue. You can easily verify this by logging the type of the principal object returned by request.getUserPrincipal()

                > Is there no standard way of getting this 'extra'
                > information?

                Not that i know.

                Cheers,
                Peter.

                • 5. Re: Principal 'Adournment'...
                  cobraflow

                  Peter,

                  I have 'patched' JBossSecurityMgrRealm to this...

                  /**
                  * Return the Principal associated with the specified username and
                  * credentials, if there is one; otherwise return null.
                  *
                  * @param username Username of the Principal to look up
                  * @param credentials Password or other credentials to use in
                  * authenticating this username
                  */
                  public Principal authenticate(String username, String credentials) {
                  boolean trace = category.isEnabledFor(XPriority.TRACE);
                  if(trace)
                  category.log(XPriority.TRACE, "Begin authenticate, username=" + username);
                  Principal principal = null;
                  Context securityCtx = getSecurityContext();
                  if(securityCtx == null) {
                  return null;
                  }
                  try {
                  // Get the JBoss security manager from the ENC context
                  AuthenticationManager securityMgr = (AuthenticationManager) securityCtx.lookup("securityMgr");
                  // Default to SimplePrincipal...
                  principal = new SimplePrincipal(username);
                  char[] passwordChars = null;
                  if(credentials != null)
                  passwordChars = credentials.toCharArray();
                  if(securityMgr.isValid(principal, passwordChars)) {
                  category.log(XPriority.TRACE, "User: " + username + " is authenticated");
                  // Override with authenticated principal...
                  if(securityMgr instanceof SubjectSecurityManager) {
                  SubjectSecurityManager subjectMgr = (SubjectSecurityManager) securityMgr;
                  Subject subject = subjectMgr.getActiveSubject();
                  principal = getAuthenticatedPrincipal(subject);
                  }

                  SecurityAssociation.setPrincipal(principal);
                  SecurityAssociation.setCredential(passwordChars);
                  } else {
                  principal = null;
                  category.log(XPriority.TRACE, "User: " + username + " is NOT authenticated");
                  }
                  } catch(NamingException e) {
                  principal = null;
                  category.error("Error during authenticate", e);
                  }
                  if(trace)
                  category.log(XPriority.TRACE, "End authenticate, principal=" + principal);
                  return principal;
                  }

                  // Ripped from org.jboss.security.plugins.JaasSecurityManager::updateCache()
                  private Principal getAuthenticatedPrincipal(Subject subject) {
                  Set subjectGroups = subject.getPrincipals(Group.class);
                  Iterator iter = subjectGroups.iterator();
                  Principal principal = null;
                  while(iter.hasNext()) {
                  Group grp = (Group) iter.next();
                  String name = grp.getName();
                  if(name.equals("CallerPrincipal")) {
                  Enumeration members = grp.members();
                  if(members.hasMoreElements())
                  principal = (Principal) members.nextElement();
                  }
                  }
                  /* Handle null principals with no callerPrincipal. This is an indication
                  of a user that has not provided any authentication info, but
                  has been authenticated by the domain login module stack. Here we look
                  for the first non-Group Principal and use that.
                  */
                  if(principal == null) {
                  Set subjectPrincipals = subject.getPrincipals(Principal.class);
                  iter = subjectPrincipals.iterator();
                  while(iter.hasNext()) {
                  Principal p = (Principal) iter.next();
                  if((p instanceof Group) == false)
                  principal = p;
                  }
                  }
                  return principal;
                  }


                  Sorry about the formatting...is there any way to use tags in the forums?


                  ...is this 'legal', can we just return the principal from the security manager's active subject???

                  If it is, this does what I wanted and returns my 'AttributePrincipal' in the request!

                  There may be other configurations that need to be checked for...I don't know the internal JBoss/Tomcat security well enough to say...maybe someone can validate what I have done???

                  ...also, while doing this I came across a 'useJAAS' flag... Does anyone know how to set it and what is it's use????


                  Kind regards


                  Lewis

                  • 6. Re: Principal 'Adournment'...
                    hezekiel

                    CobraFlow,

                    I'm trying get this 'extra' info from client to server in the authentication process. All the JAAS documentation speaks nicely about these phone/address/etc.. extra Principals but in real life this seems to be almost impossible?

                    Is it so uncommon to transmit more than just username and password in the authentication?

                    Is it me or JAAS or JBoss which is flawed?

                    Brrrr...

                    • 7. Re: Principal 'Adournment'...
                      cobraflow

                      Hezekiel,

                      The 'patch' I supplied above allows you to return 'lightweight' principal information to your application via the Principal object in your request/context. This information is acquired by the SERVER login module upon successful authentication. This does not seem to be your question at all! You seem to want to pass information from the client to the server during the authentication 'challenge'. To do this you must extend both the server login module to request this information from the client and also the client login module to return the information when requested. What type of information do you want to pass to the server in this way?

                      Lewis

                      • 8. Re: Principal 'Adournment'...
                        cobraflow

                        Hezekiel,

                        The 'patch' I supplied above allows you to return 'lightweight' principal information to your application via the Principal object in your request/context. This information is acquired by the SERVER login module upon successful authentication. This does not seem to be your question at all! You seem to want to pass information from the client to the server during the authentication 'challenge'. To do this you must extend both the server login module to request this information from the client and also the client login module to return the information when requested. What type of information do you want to pass to the server in this way?

                        Lewis