5 Replies Latest reply on Apr 18, 2006 11:12 AM by calin.pavel

    Dynamic authentication

    kresho

      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
          starksm64

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

          • 2. Re: Dynamic authentication
            kresho

            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
              starksm64

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

              • 4. Re: Dynamic authentication
                acxsjones

                Did this get fixed

                • 5. Re: Dynamic authentication
                  calin.pavel


                  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.