5 Replies Latest reply on Apr 18, 2006 11:12 AM by Calin Pavel

    Dynamic authentication

    Kresimir Tonkovic Newbie

      My application has an ejb 2.1 timer, which triggers some work. The work must be done using the same principal that requested the work. So, I start the timer with an info object that contains the principal's login and password. When the timer expires, I try to authenticate using principal data from the info object, and run the task. I understand that it is not possible to change principal during execution of a business method, so I use the same code that I use on the client to authenticate, create a new bean and run it's methods, thus making the ejbTimeout method a client to the container. Here is the code:

      public void ejbTimeout(Timer timer) {
       final OptInfo info = (OptInfo)timer.getInfo();
       try {
       Properties p = new Properties();
       p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.security.jndi.LoginInitialContextFactory");
       p.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
       p.put(Context.PROVIDER_URL, "jnp://localhost:1099");
       p.put(Context.SECURITY_PRINCIPAL, info.user.username);
       p.put(Context.SECURITY_CREDENTIALS, info.user.password);
       p.put(Context.SECURITY_PROTOCOL, "client-login");
      
       InitialContext ctx = new InitialContext(p);
       Object home = ctx.lookup(WalkOptimizerHome.JNDI_NAME);
      
       WalkOptimizerHome optimizerHome = (WalkOptimizerHome)PortableRemoteObject.narrow(home, WalkOptimizerHome.class);
       WalkOptimizer optimizer = optimizerHome.create();
      
       optimizer.runOptimization(info);
       } catch (NamingException e) {
       Category.getInstance("WalkOptimizer").error("login failed (naming): " + e.getMessage());
      (remote): " + e.getMessage());
       } catch (CreateException e) {
       Category.getInstance("WalkOptimizer").error("login failed (create): " + e.getMessage());
       } catch (SessionException e) {
       Category.getInstance("WalkOptimizer").error("login failed (session): " + e.getMessage());
       }
      }
      


      Notice that I don't use the default InitialContext with properties supplied from the container, but force properties that would make the lookup be executed over the network. I also use the WalkOptimizer bean over the remote home and interface, hoping to hide the fact that these calls come from within the container. However, every time I get this in the log:

      2005-05-09 12:55:25,803 ERROR [WalkOptimizer] login failed (remote): SecurityException; nested exception is:
       java.lang.SecurityException: Insufficient method permissions, runAsPrincipal=ejbTimeout, method=create, interface=HOME, requiredRoles=[admin], runAsRoles=[ejbTimeout]
      

      I understand this means that the create call was made over the network (interface=HOME not LOCALHOME), but JBoss still communicated the current principal (ejbTimeout) behind my back, no matter what I specify in the InitialContext properties.

      My core intention to postpone some work, but the work must still be executed by a principal that represents a logged-in user. Maybe this is a completely wrong approach - in this case please don't bother with my code, but point me in the correct direction.

      I have carefully studied posts with similar titles, and all I see is some static security configuration that will make ejbTimeout or onMessage execute as some static principal, but this is not what I need.

        • 1. Re: Dynamic authentication
          Scott Stark Master

          You need to do a JAAS login the same as any external client that needs to establish its security context.

          • 2. Re: Dynamic authentication
            Kresimir Tonkovic Newbie

            I thought I am doing a JAAS login - from what I read in section 3.2.1.2. in JBoss 4.0.1 AS guide, LoginInitialContextFactory does a JAAS login under the hood. Nevertheless, I have tried using JAAS login directly:

            public void ejbTimeout(Timer timer) {
             final OptInfo info = (OptInfo)timer.getInfo();
             try {
             Properties p = new Properties();
            
             p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); //$NON-NLS-1$
             p.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); //$NON-NLS-1$
             p.put(Context.PROVIDER_URL, "jnp://localhost:1099");
            
             try {
             LoginContext ctxLogin = new LoginContext("client-login", new CallbackHandler() {
             public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
             for (int i = 0; i < callbacks.length; i++) {
             if (callbacks[ i ] instanceof NameCallback) {
             NameCallback nc = (NameCallback)callbacks[ i ];
             nc.setName(info.user.username);
             } else if (callbacks[ i ] instanceof PasswordCallback) {
             PasswordCallback pc = (PasswordCallback)callbacks[ i ];
             pc.setPassword(info.user.password.toCharArray());
             } else {
             throw new UnsupportedCallbackException(callbacks[ i ], "Unrecognized Callback");
             }
             }
             }
             });
             ctxLogin.login();
            
             InitialContext ctx = new InitialContext(p);
             InitialContext ctx = new InitialContext(p);
             Object home = ctx.lookup(WalkOptimizerHome.JNDI_NAME);
            
             WalkOptimizerHome optimizerHome = (WalkOptimizerHome)PortableRemoteObject.narrow(home, WalkOptimizerHome.class);
             WalkOptimizer optimizer = optimizerHome.create();
            
             optimizer.runOptimization(info);
             } catch (NamingException e) {
             Category.getInstance("WalkOptimizer").error("login failed (naming): " + e.getMessage());
            (remote): " + e.getMessage());
             } catch (CreateException e) {
             Category.getInstance("WalkOptimizer").error("login failed (create): " + e.getMessage());
             } catch (SessionException e) {
             Category.getInstance("WalkOptimizer").error("login failed (session): " + e.getMessage());
             }
            }
            




            but with no effect.

            • 3. Re: Dynamic authentication
              Scott Stark Master

              Create a bug report in jira then so we can look into what the issue is:
              http://jira.jboss.com/jira/browse/JBAS

              • 5. Re: Dynamic authentication
                Calin Pavel Newbie


                Any news related to this? It seems that even if I try to uses client-login context to pass furthure user/password still not works.