11 Replies Latest reply on May 14, 2004 8:13 AM by morenito9000

    Change rolesQuery in DatabaseServerLoginModule

    morenito9000

      Hi all,
      I have a question about changing rolesQuery in DatabaseServerLoginModule.

      In my application a user may have different roles but this roles
      could change depending from the company in which user works.
      For example:

      in Company1 user John has Admin/Developer Roles
      in Company2 user John has Developer Role
      in Company3 user John has Seller Role

      Is it possible to change rolesQuery in this way:
      <select usersRoles, 'Roles' from UsersRoles where username=?
      AND Company=?>

      or I need to write, Server Side, a Custom Login Module that substitutes DatabaseServerLoginModule ?

      Client Side, must I write a MyClientLoginModule, similar to
      the default ClientLoginModule, that sends username/password
      and Company to JBoss ?

      Company must be set using SecurityAssociation.setPrincipal() method ?
      (in JBoss docs I read that "you could always set the SecurityAssociation
      information directly, but this is considered an internal API that is
      subject to change without notice").

      I'm very confused :-(

      Could someone give me a suggestion ?

      Thank you very much,
      Moreno

        • 1. Re: Change rolesQuery in DatabaseServerLoginModule
          jburugupalli

          HI,
          I have an idea, better write some class similar to NestedPrincipal which holds information other than the principal and set this Pricipal in the ClientLoginModule instead of SimplePrincipal.

          SecurityAssociation.setPrincipal(new SimplePrincipal(username));

          But you should write your own databaseserverloginmodule with minimal chnages and also yous hould override one or two methods from the UserNamePasswrodLoginModule...

          i hope this helps...bur if any one has better solution

          regards
          JB

          • 2. Re: Change rolesQuery in DatabaseServerLoginModule
            morenito9000

            Thank you Jburugupalli,

            > I have an idea, better write some class similar to NestedPrincipal
            > which holds information other than the principal and set this
            > Pricipal in the ClientLoginModule instead of SimplePrincipal.

            >SecurityAssociation.setPrincipal(new SimplePrincipal(username));

            If I understood well,
            I can change SimplePrincipal (creating a ModifiedSimplePrincipal)
            adding the company attribute, with related method:

            private String company;
            public String getCompany()

            and changing equals() and hashCode() methods.

            I need to change ClientLoginModule in this instruction:

            SecurityAssociation.setPrincipal(new ModifiedSimplePrincipal(username, company));

            >But you should write your own databaseserverloginmodule
            >with minimal chnages and also yous hould override one
            >or two methods from the UserNamePasswrodLoginModule...

            Here I must change getRoleSets() method of DatabaseServerLoginModule
            retrieving company from the Principal and changing rolesQuery
            that this LoginModule execute.

            When I compile MyDatabaseServerLoginModule I have to put it
            (tha class or a jar file) in the DEPLOY directory of my server instance ?
            The only changes, in configuration, are inside login-config.xml
            file ?

            <application-policy name = "XMALF-policy">

            <login-module code="xxx.yyy.zzz.MyDatabaseServerLoginModule" flag = "required">
            <module-option name="dsJndiName">java:/PostgresDS</module-option>
            <module-option name="principalsQuery">select password from utente username where username=?</module-option>
            <module-option name="rolesQuery">select ente, 'Roles' from prod_ute_ente where username=? AND company=?</module-option>
            </login-module>

            </application-policy>

            Hi,
            Moreno

            • 3. Re: Change rolesQuery in DatabaseServerLoginModule
              jburugupalli

              Yes exactly, i tried every thing exceot writing my own Principal class , and it should not be a problem, in my case i assign a valid session after the user logs in, and this session ID is set as a credential and checked every time if it has expired,

              Please put all of your own classes in a separate jar file and put it in the server/mode(default)/lib directory

              thats it

              regards
              Jani

              • 4. Re: Change rolesQuery in DatabaseServerLoginModule
                gorano

                Using form authentcation, I recommend everyone to extend org.jboss.security.auth.spiDatabaseServerLoginModule

                This class is simple and easy to extend to whatever you want.

                I have made two extended versions:

                1. user, role and group tables with many to many between all tables.
                This gives you the posibility to asign roles to groups and roles + groups
                to users (gives you a fast and very flexible assignment of capabilities).

                2. A version of the above using RMI to a session bean on the application tier. (if the web tier with jaas does not have db connectivity).

                I can post some code as examples if anyone is interested.

                /Göran

                • 5. Re: Change rolesQuery in DatabaseServerLoginModule
                  morenito9000

                  Hi,
                  I'm trying to extend DatabaseServerLoginModule but I have problems
                  in getRoleSets() method.
                  From Client I receive a modified SimplePrincipal that contains
                  name/password/product (I added product class member).

                  In MyDatabaseServerLoginModule I changed the rolesQuery:

                  "select Role, RoleGroup from Roles where PrincipalID=?
                  and productID=?

                  In getRoleSets() method I have to prepare the SQL Statement:

                  String username = getUsername();
                  String product = getProduct(); /* METHOD I MUST WRITE !!!!! */

                  ps = conn.prepareStatement(rolesQuery);
                  try {
                  ps.setString(1, username);
                  ps.setString(2, product);
                  }

                  My class inherits getUsername() method from DatabaseServerLoginModule
                  (that inherits the method from UsernamePasswordLoginModule):
                  This method looks like:

                  protected String getUsername()
                  {
                  String username = null;
                  if( getIdentity() != null )
                  username = getIdentity().getName();
                  return username;
                  }

                  If I'm right this method uses an identity created in login() method.

                  My question is:
                  I need to write getProduct() method but in this case
                  I need to overwrite login() method in order to create an identity
                  with name and product inside of it ?
                  Login() method retrieves username and password, after
                  Callbackhandler.handle() method, calling getUsernameAndPassword()
                  method: must I change getUsernameAndPassword() method too ?

                  I'm very confused :-(

                  Thank you for any suggestion,
                  Moreno

                  • 6. Re: Change rolesQuery in DatabaseServerLoginModule
                    jburugupalli

                    HI,

                    But why dint u concentrate on the other inherited method from UserNamePasswor....

                    getIdentity() which returns a principal that is nothing but your own Principal class with product info

                    or u can even use the static method
                    SecurityAssociation.getPrincipal(); which returns the current principal...

                    i hope u got it.

                    regards
                    jani

                    • 7. Re: Change rolesQuery in DatabaseServerLoginModule
                      morenito9000

                      I wrote the getProduct() method that looks like getUsername().

                      protected String getProduct() {
                      String prodotto = null;
                      Principal p = getIdentity();

                      if( p != null ) {
                      prodotto = ((XMalfSimplePrincipal) p).getProduct();
                      /* Here I receive a ClassCastException */
                      }

                      return prodotto;
                      }

                      During login phase I see in server.log file a
                      ClassCastException when I try to cast the Principal returned by
                      getIdentity() to XMalfSimplePrincipal.

                      (XMalfSimplePrincipal is the Principal that I used in SecurityAssociation.setPrincipal() in MyClientLoginModule).



                      [org.jboss.security.plugins.JaasSecurityManager.XMALF-policy] Login failure
                      javax.security.auth.login.LoginException: java.lang.ClassCastException
                      at server.security.XMalfDatabaseServerLoginModule.getProduct
                      (XMalfDatabaseServerLoginModule.java:339)
                      at server.security.XMalfDatabaseServerLoginModule.getRoleSets(XMalfDatabaseServerLoginModule.java:176)

                      Does anybody have any idea ?

                      Many thanks
                      Moreno

                      • 8. Re: Change rolesQuery in DatabaseServerLoginModule
                        morenito9000

                        Jburugupalli wrote:

                        >But why dint u concentrate on the other inherited method
                        >from UserNamePasswor....
                        >getIdentity() which returns a principal that is
                        >nothing but your own Principal class with product info
                        >or u can even use the static method
                        >SecurityAssociation.getPrincipal(); which returns the current principal...


                        I'm proceeding step by step.
                        For the moment I have forgotten the attribute product,
                        I'm trying to send from Client to Server a XMalfSimplePrincipal that carries name and product attributes
                        even if the XMalfDatabaseServerLoginModule uses ONLY name (product will be used later, I hope :-)).

                        In XMalfDatabaseServerLoginModule I copied getUsername()
                        method from UsernamePasswordLoginModule (if I'm able to change
                        it I'll be able to write getProduct() method later).

                        This is the code:

                        protected String getUsername()
                        {
                        String username = null;
                        if( getIdentity() != null )
                        username = getIdentity().getName();
                        return username;
                        }

                        It obviously run.
                        When I change getUsername() in this way:

                        protected String getUsername() {
                        String username = null;

                        if( SecurityAssociation.getPrincipal() != null )
                        username = SecurityAssociation.getPrincipal().getName();

                        return username;
                        }

                        the method fails :-(

                        I tried to concentrate on getIdentity() method but
                        - it returns identity
                        - identity is set inside login() method (identity = createIdentity(name))
                        - createIdentity() is used after having called CallbackHandler
                        - CallbackHandler returns password and name (it should return product too, but I don't understand which
                        CallbackHandler is used by
                        UsernamePasswordLoginModule and why I had to use a CallbackHandler,
                        server side, if I already have received user, password and product
                        from the Client).

                        Sorry if I'm boring you :-(
                        Thanks
                        Moreno

                        • 9. Re: Change rolesQuery in DatabaseServerLoginModule
                          morenito9000

                          Jburugupalli wrote:

                          >But why dint u concentrate on the other inherited method
                          >from UserNamePasswor....
                          >getIdentity() which returns a principal that is
                          >nothing but your own Principal class with product info
                          >or u can even use the static method
                          >SecurityAssociation.getPrincipal(); which returns the current principal...


                          I'm proceeding step by step.
                          For the moment I have forgotten the attribute product,
                          I'm trying to send from Client to Server a XMalfSimplePrincipal that carries name and product attributes
                          even if the XMalfDatabaseServerLoginModule uses ONLY name (product will be used later, I hope :-)).

                          In XMalfDatabaseServerLoginModule I copied getUsername()
                          method from UsernamePasswordLoginModule (if I'm able to change
                          it I'll be able to write getProduct() method later).

                          This is the code:

                          protected String getUsername()
                          {
                          String username = null;
                          if( getIdentity() != null )
                          username = getIdentity().getName();
                          return username;
                          }

                          It obviously run.
                          When I change getUsername() in this way:

                          protected String getUsername() {
                          String username = null;

                          if( SecurityAssociation.getPrincipal() != null )
                          username = SecurityAssociation.getPrincipal().getName();

                          return username;
                          }

                          the method fails :-(

                          I tried to concentrate on getIdentity() method but
                          - it returns identity
                          - identity is set inside login() method (identity = createIdentity(name))
                          - createIdentity() is used after having called CallbackHandler
                          - CallbackHandler returns password and name (it should return product too, but I don't understand which
                          CallbackHandler is used by
                          UsernamePasswordLoginModule and why I had to use a CallbackHandler,
                          server side, if I already have received user, password and product
                          from the Client).

                          Sorry if I'm boring you :-(
                          Thanks
                          Moreno

                          • 10. Re: Change rolesQuery in DatabaseServerLoginModule
                            jburugupalli

                            Hi,
                            Dont depend too much on these LoginModules , there is a nice way of writing ur own by extending the AbstractServerLoginModule....then when ur implementing ur own LoginModule u will get know the important aspects of this LoginMechanism just a simple one will help u

                            But any way try the follwoing code if it helps using different callback handler

                             protected String[] getUsernameAndPassword() throws LoginException
                             {
                             String[] info = {null, null};
                             // prompt for a username and password
                             if( callbackHandler == null )
                             {
                             throw new LoginException("Error: no CallbackHandler available " +
                             "to collect authentication information");
                             }
                             String username = null;
                             String password = null;
                             SecurityAssociationCallback sac = new SecurityAssociationCallback();
                             Callback[] callbacks = { sac };
                             try
                             {
                             callbackHandler.handle(callbacks);
                             if(sac.getPrincipal() != null)username = sac.getPrincipal().getName();
                             if(sac.getCredential() != null)
                             {
                             password = new String((char[]) sac.getCredential());
                             }
                             SecurityAssociation.setPrincipal(sac.getPrincipal());
                             SecurityAssociation.setCredential(sac.getCredential());
                             SecurityAssociation.setSubject(subject);
                             }
                             catch(java.io.IOException ioe)
                             {
                             throw new LoginException(ioe.toString());
                             }
                             catch(UnsupportedCallbackException uce)
                             {
                             throw new LoginException("CallbackHandler does not support: " + uce.getCallback());
                             }
                             info[0] = username;
                             info[1] = password;
                            // or even add here ur product or any other stuff u need and dont forget //to check the instance of the Principal class u r getting above if it is the //same as u sent it from the client
                             return info;
                             }
                            

                            regards
                            jani

                            • 11. Re: Change rolesQuery in DatabaseServerLoginModule
                              morenito9000

                              Many thanks Jburugupalli for your precious help,

                              I created a XMalfDatabaseServerLoginModule that
                              extends AbstractServerLoginModule
                              (it's a "merge" between UsernamePassword... and DatabaseServer....
                              login modules)
                              and that uses, in getUsernameAndPassword() method, the SecurityAssociationCallback.

                              Now I'm able to get from the Client Username/Password/Product
                              and to select from DB roles of my user that depend
                              from product.

                              Moreno