1 Reply Latest reply on Dec 18, 2009 12:04 PM by pgib

    JBoss Programmatic Login, non-password authentication

      Hello. I am having difficulty determining how to perform programmatic login in JBoss where the credentials is more complex than a simple username + password pair.

      In our system, users are identified by UserName (String), AuthAgentId (long), and VerificationCode (String). Basically, AuthAgentId is the "domain"; each one is an independent namespace of UserNames. VerificationCode is a SHA-256 signature that we use to verify the authenticity of the user.

      Therefore we have a custom LoginModule:

      import org.jboss.security.auth.spi.AbstractServerLoginModule;
      
      public class VhmDbServerLoginModule extends AbstractServerLoginModule {
       public void initialize(...) { ... }
       public boolean login () throws LoginException { ... }
       ...
      }


      Also, we have a custom CallbackHandler to actually feed the LoginModule:
      public class UsernameAuthAgentHandler implements CallbackHandler {
       private transient final String username;
       private transient final String verificationCode;
       private transient final long authAgentId;
      
       public UsernameAuthAgentHandler (
       String username, long authAgentId, String verificationCode) {
       ...
       }
      
       public void handle (Callback[] callbacks) throws
       UnsupportedCallbackException {
       for (Callback c : callbacks) {
       if (c instanceof NameCallback) {
       NameCallback nc = (NameCallback) c;
       nc.setName(username);
       }
       else if (c instanceof TextInputCallback) {
       TextInputCallback tc = (TextInputCallback) c;
       if (tc.getPrompt().equals("VerificationCode")) {
       tc.setText(verificationCode);
       }
       }
       else if (c instanceof LongInputCallback) {
       LongInputCallback lc = (LongInputCallback) c;
       if (lc.getPrompt().equals("AuthAgent")) {
       lc.setValue(authAgentId);
       }
       }
       else {
       throw new UnsupportedCallbackException(c, "Unrecognized Callback");
       }
       }
       }
      }


      Good so far - We use LoginContext to perform the login:
      Request request = SecurityAssociationValve.activeRequest.get();
       if (request == null) {
       throw new IllegalStateException("request is null");
       }
      
       UsernameAuthAgentHandler uaah =
       new UsernameAuthAgentHandler(username, agentId, credential);
      
       String realm = request.getContext().getLoginConfig().getRealmName();
       LoginContext lc = null;
       try {
       lc = new LoginContext(realm, uaah);
       lc.login();
       }
       catch (LoginException le) {
       return false;
       }
       ...


      This works, it results in a subject that looks like:
      Subject:
       Principals:
       Principal: com.vhm.security.auth.UserPrincipal@65824b9
       Principal: Roles(members:OWNER,SUBSCRIBER,ACCESS_FULL)
       Principal: CallerPrincipal(members:com.vhm.security.auth.UserPrincipal@65824b9)
       pubCredentials: size = 0
       privCredentials: size = 0

      I can share the exact LoginModule code incase this output looks invalid, but it seems correct to me.

      I then call the WebAuthentication.register(Request request, Principal principal, String s, Object o) method. I created a subclass of WebAuthentication in order to make the method public.
      Principal p =
       lc.getSubject().getPrincipals(UserPrincipal.class).iterator().next();
       wad.register(request, p, username, credential);


      After all this, I make another request to a servlet. I call request.getUserPrincipal() and it returns my custom UserPrincipal! However, when I call request.isUserInRole("OWNER") I get false. I expect this since I never had a chance to register the roles.

      My question is - How do I actually register the roles with the request/session? Some people in #jboss tell me to "Create a SAR". I know how to do this, but I have absolutely no clue what this Service should do. I have no existing services I know to fork. So - I'm at a total loss.

      If someone could please help me register the roles with the catalina session, I would be eternally grateful!


        • 1. Re: JBoss Programmatic Login, non-password authentication

          For what it is worth:

           

          I didn't have enough time to read the whole security explaination and truly grasp JBoss-SX's innards.  Maybe someday I will be given enough time to do this.  Today I revisited the problem, and worked around it by packing multiple fields in the Username CallbackHandler.

           

          The '/' character is illegal for usernames in our system, so I simply return "authAgentId/userName" from my CallbackHandler.  In our login module, we search for '/' in the (supposed) username.  if it exists, then we split the two values out.  This works great, although it is a little bit of a hack.

           

          -Paul