7 Replies Latest reply on Jul 18, 2006 9:30 AM by Paul Kearns

    Integration of Custom Client and Server Login Modules

    Paul Kearns Newbie

      Objective: to authenticate using a custom client login module and pass the subject, containing the credentials customer ID and NHS #, to a custom server login module. This does no authentication but simple maps the customer ID to a role in order to invoke a secured EJB.

      How:

      I have listed below 4 different approaches I used.

      (1) Created the following components:

      ? Custom client login module (reference article: All that JASS):
      ConsoleCallbackHandler
      PassiveCallbackHandler
      RdbmsCredential
      RdbmsLoginModule
      RdbmsPrinciple

      ? Custom server login module (reference article: Securing EJB Applications with Custom JBoss Login Modules) :
      CustomServerLoginModule

      ? used JBoss client login module to bind subject.

      ? added RDBMS Login Module (custom client login module) to /example domain in login-conf.xml
      ? added CustomServerModule to security domain (secureBankDomain) for EJB application

      extract from login-config.xml

      <application-policy name = "Example">

      <login-module code="com.jaas.RdbmsLoginModule" flag = "required">
      <module-option name="url">jdbc:mysql://localhost/jaasdb</module-option>
      <module-option name="usr">root</module-option>
      <module-option name="pwd">steelbus581</module-option>
      <module-option name="driver">com.mysql.jdbc.Driver</module-option>
      <module-option name="debug">true</module-option>
      </login-module>
      <login-module code="org.jboss.security.ClientLoginModule"
      flag = "required">
      </login-module>


      </application-policy>

      <application-policy name = "SecureBankDomain">

      <login-module code="bank.jaas.CustomServerLoginModule" flag = "required">
      <module-option name="debug">true</module-option>
      </login-module>

      </application-policy>

      Subsequently realised that the only the username and password handled by the call back is past to the server login module. Therefore this approach would not work.

      (2) Pass the credential and principle in initial context e.g. Context.SECURITY_PRINCIPAL prior to getting a reference to the remote EJB.

      HashTable props = new HashTable();
      props.put( Context.SECURITY_PRINCIPAL,
      SecurityAssociation.getPrincipal() );
      props.put( Context.SECURITY_CREDENTIALS,
      SecurityAssociation.getCredential() );

      InitialContext initialContext = new InitialContext( props );

      On invoking the server login method it fails as no identity, i.e. Principle, can be found


      (3) Created a PrivilegedAction i.e. CallBankMgrGetCustData that would get the EJB reference and execute the method. This also fails as no identity can be found.

      (4) Pushed credential and principle onto SecurityAssociation stack. However an error occurred as on the RdbmsPrincipal class could not be found ? no class loader. Then added com.bank.RdbmsCredential and RdbmsPrincipal to server/default/lib as jar. Still the customer server login module fails as no identity, i.e. Principle, can be found.

      Question:

      What have I not understood or not configured correctly. Or is what I am trying to do not possible. Any help would be appreciated.

      References:


      All That JASS: http://www.javaworld.com/javaworld/jw-09-2002/jw-0913-jaas_p.html
      Writing Custom JAAS Login Modules. 21 Nov 2003. http://www.timfanelli.com/blog/item/custom_jaas_login_modules.html
      Securing EJB Applications with Custom JBoss Login Modules. 21 Nov 2003 http://www.timfanelli.com/item/98


        • 1. Re: Integration of Custom Client and Server Login Modules
          chris griffith Expert

          kearns,

          There are still a few details I would need to understand your situation.

          1.) It was not clear to me what data you need to be passed to your bank.jaas.CustomServerLoginModule. What is acting as the identity pricinpal and what is acting as the authentication data? What else do you need here?

          2.) Is your client a standalone application or web-enabled?

          3.) If your client is standalone, does it restrict the user from performing certain functions based on identity. For example, if user does not have right to modify another user, then a certain screen is not enabled.

          4.) if your client is standalone, is it multithreaded?

          cgriffith

          • 2. Re: Integration of Custom Client and Server Login Modules
            Paul Kearns Newbie

            hi,

            In the commit() of the client login module I add to the subject:

            subject.getPrincipals().addAll(tempPrincipals);
            subject.getPublicCredentials().addAll(tempCredentials);

            where tempCredentials contains the property name-value pairs:

            c.setProperty("nhs number", nhsNum);
            c.setProperty("customer id", custId);

            The passive callback handlers PassiveCallbackHandler has constructor that takes a username and password so its handle() method does not have to prompt the user for input. This information is supplied by a JUnit test or by a jsp which gets the information from a HTML form. There is no peripheral security restrictions.

            It is the custId that needs to be visible to the custom server login module.

            At this time the application is deployed on my desktop running a default JBoss server.

            Hope this helps. Cheers

            • 3. Re: Integration of Custom Client and Server Login Modules
              chris griffith Expert

              Hi Kearns,

              So you have a web-enabled client. I am still not clear on what is your identifing principal and what is your credential. What does the user enter in the form? My point is to determine how your authentication data can be used as a String/Principal identity and an Object credential. From there, we can talk about how to get this data to your server login module.

              In the mean time, also check out the server guide chapter 8 at http://docs.jboss.org/jbossas/jboss4guide/r4/html/ch8.chapter.html.

              cgriffith

              • 4. Re: Integration of Custom Client and Server Login Modules
                Paul Kearns Newbie

                hi,

                The jsp page where the client enters the data is shown below. You will see that I extract the credential 'customer id' from the subject to use in a call to a BankMgr Bean via a delegate (BankMgrDelegate). The BankMgr bean is in the 'securBankDomain' which uses the CustomServerLogin module to map the 'customer id' credential to a role. Specific roles have access to specific methods.

                <!--
                jaas.jsp: Simple JSP page to test custom JAAS RdbmsLoginModule.
                -->

                <%
                if (request.getParameter("user") == null) {
                %>

                <input type=text name=user>
                <input type=text name=pass>
                <input type=submit value=submit>

                <%
                } else {
                // just so you can see the debug messages
                //System.setOut(new PrintStream(response.getOutputStream()));

                try {
                // Get the form's username & password fields
                //
                String user = request.getParameter("user");
                String pass = request.getParameter("pass");

                // Use the username/password to initialize the
                // callback handler and then do the authentication.
                //
                PassiveCallbackHandler cbh = new PassiveCallbackHandler(user, pass);

                LoginContext lc = new LoginContext("Example", cbh);

                lc.login();

                // Loop through all Principals and Credentials.
                //
                Iterator it = lc.getSubject().getPrincipals().iterator();
                while (it.hasNext())
                out.println("Authenticated: " + it.next().toString() + "");

                // as the credential is not any specific class, but can be any object the type is
                // past as an augument. Here RdbmsPrinciple extends java.util.Properties.
                it = lc.getSubject().getPublicCredentials(Properties.class).iterator();

                out.println("Credentials: ");
                String id = null;
                Properties credential = null;
                while (it.hasNext())
                credential = (Properties)it.next();
                id = credential.getProperty("customer id");
                out.println(credential.toString());

                // initialise bank manager delegate
                BankMgrDelegate bankMgrDelegate = new BankMgrDelegate();
                bankMgrDelegate.init();

                // call BankMgr bean
                if (id != null) {
                int custId = Integer.parseInt(id);
                try {
                out.println(bankMgrDelegate.getCustomerData(custId).toString());
                } catch (Exception e) {
                out.println("jaas: call BankMgr bean - "+e.getMessage());
                }
                } else {
                out.println("Controller: processRequest - INVALID parameter *** userId ***");
                }


                lc.logout();

                } catch (Exception e) {
                out.println("Caught Exception: " + e);
                }
                }
                %>

                • 5. Re: Integration of Custom Client and Server Login Modules
                  Paul Kearns Newbie

                  Thanks for your continued interest.

                  I continued to research the problem and started with switching on logging for the jboss security package in log4j:

                  <appender name="SECURITY" class="org.apache.log4j.FileAppender">
                   <param name="File" value="${jboss.server.home.dir}/log/security.log"/>
                   <param name="Append" value="true"/>
                   <layout class="org.apache.log4j.PatternLayout">
                   <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
                   </layout>
                   </appender>
                  
                   <category name="org.jboss.security">
                   <priority value="DEBUG"/>
                   <appender-ref ref="SECURITY"/>
                   </category>


                  When I ran the app I expected to see a security manager log entry for both of the security domains (or realms) i.e. SecureBankDomain and Example (the custom client login module policy name). However only the SecureBankDomain was logged:

                  2006-07-18 10:46:53,125 DEBUG [org.jboss.security.plugins.JaasSecurityManager.SecureBankDomain] CallbackHandler: org.jboss.security.auth.callback.SecurityAssociationHandler@501e4e
                  2006-07-18 10:46:53,125 DEBUG [org.jboss.security.plugins.JaasSecurityManagerService] Created securityMgr=org.jboss.security.plugins.JaasSecurityManager@1f5cc7d
                  2006-07-18 10:46:53,125 DEBUG [org.jboss.security.plugins.JaasSecurityManager.SecureBankDomain] CachePolicy set to: org.jboss.util.TimedCachePolicy@4430e2
                  2006-07-18 10:46:53,125 DEBUG [org.jboss.security.plugins.JaasSecurityManagerService] setCachePolicy, c=org.jboss.util.TimedCachePolicy@4430e2
                  2006-07-18 10:46:53,125 DEBUG [org.jboss.security.plugins.JaasSecurityManagerService] Added SecureBankDomain, org.jboss.security.plugins.SecurityDomainContext@e5590e to map

                  • 6. Re: Integration of Custom Client and Server Login Modules
                    chris griffith Expert

                    kearns,

                    You need a better understanding of authentication/authorization. There is just too much stuff that is wrong here. See the resource I mentioned below. As well as the wikis at wiki.jboss.org/wiki/Wiki.jsp?page=JBossSX
                    and
                    wiki.jboss.org/wiki/Wiki.jsp?page=Tomcat.

                    However in an effort to point you in the right direction...

                    1.) you need to set up and configure container managed security for your web application (per j2ee spec.) I suggest using FORM based authentication. I suggest you combine the actions of both your com.jaas.RdbmsLoginModule and your bank.jaas.CustomServerLoginModule into one login module that is configured for the security domain covering the web app.

                    2.) Then you need to set up and configure container managed security for your EJB's (I think you have alread done this). In this case, make the security domain the same as that in step 1.

                    The result will be that your user authenticates via the new CustomServerLoginModule for both the web application as well as the EJB components. Once authenticated you can just call the bean. Note that you do not need to perform any LoginContext.login()s in your application.

                    Also, your custom login module should store the customer id and NHS# (so long as these are not restricted data) as custom Principals under the Subject. If the customerID is what you use internally to identify the user (rather than the "user" parameter entered in login form) Then follow JBoss' subject usage pattern and make this principal the "Caller Principal". Finally, you can get the customer id to use in method bankMgrDelegate.getCustomerData(custId).toString() by using EJBContext.getCallerPrincipal() method.

                    There is just too much to say, hope this provides some direction. cgriffith

                    • 7. Re: Integration of Custom Client and Server Login Modules
                      Paul Kearns Newbie

                      Thanks for your patience as I know this may seem to some as straight forward.

                      I have already succeeded in a previous project to use BASIC web authentication attached to a domain using the JBoss UsersRolesLoginModule. Only Customer and Admin roles can access specific web pages and then calls to remote EJBs are also restricted based on role.

                      Web.xml:
                      
                       <security-role>
                       <role-name>admin</role-name>
                       </security-role>
                       <security-role>
                       <role-name>customer</role-name>
                       </security-role>
                      
                       <login-config>
                       <auth-method>BASIC</auth-method>
                       <realm-name>BankDomain</realm-name>
                       </login-config>
                      
                      
                      



                      JBoss-web.xml:
                      <?xml version="1.0" encoding="UTF-8"?>
                      <jboss-web>
                       <security-domain flushOnSessionInvalidation="false">java:/jaas/BankDomain</security-domain>
                       <context-root>/bank</context-root>
                      </jboss-web>


                      JBoss.xml:
                      <jboss>
                       <security-domain>java:/jaas/BankDomain</security-domain>
                      </jboss>



                      The target bean is the same remote stateless session bean, BankMgr, which uses the Caller Principle in the way you mentioned:

                      public CustomerData getMyData() throws bank.BankException {
                       Principal p = context.getCallerPrincipal();
                       String userN = p.getName();
                       if (userN.equalsIgnoreCase("ANONYMOUS") || userN.equalsIgnoreCase("GUEST")) {
                       throw new BankException("BankMgrBean: getMyData - User not logged in");
                       }
                       int pUserId = Integer.parseInt(userN);


                      However, what I wanted to show in this Proof of Concept (PoC) project was that client authentication could be executed independently from server side resource control e.g. bean method execution. Such a scenario would occur if authentication of the client is not under your control however authorisation to use server side (remote) resources are. Thus, I can not use the same security realm for both the client and server resources.

                      Thanks again for your help.