8 Replies Latest reply: Mar 22, 2012 6:03 AM by Daniel Jipa RSS

Remote client access with database login module: user name and password are UUIDs

f.ulbricht Newbie

Hello there,

 

I have a simple application with a secured session bean. I want to invoke this bean from a remote client.

 

This is my configuration:

 

standalone.xml:

 

...

            <security-realm name="TutorialRealm">

                <authentication>

                    <jaas name="tutorial"/>

                </authentication>

            </security-realm>

...

        <subsystem xmlns="urn:jboss:domain:remoting:1.1">

            <connector name="remoting-connector" socket-binding="remoting" security-realm="TutorialRealm"/>

        </subsystem>

...

              <security-domain name="tutorial" cache-type="default">

                    <authentication>

                        <login-module code="Remoting" flag="optional">

                            <module-option name="password-stacking" value="useFirstPass"/>

                        </login-module>

                        <login-module code="Database" flag="required">

                            <module-option name="dsJndiName" value="java:/TutorialDS"/>

                            <module-option name="principalsQuery" value="SELECT PASSWORD FROM SYSTEM_USER WHERE USER_NAME = ?"/>

                            <module-option name="rolesQuery" value="SELECT USER_ROLE, 'Roles' FROM SYSTEM_USER_ROLE WHERE USER_NAME = ?"/>

                            <module-option name="password-stacking" value="useFirstPass"/>

                        </login-module>

                    </authentication>

                </security-domain>

...

 

My bean looks like this (it just returns the current user, but this method was never called):

 

@Stateless(name = "Secured")
@Remote(SecuredRemote.class)
@SecurityDomain("tutorial")
public class SecuredBean implements SecuredRemote {

 

@Resource
private SessionContext sessionContext;

 

@Override
@RolesAllowed("role1")
public String getCurrentUserName() {
  Principal principal = this.sessionContext.getCallerPrincipal();

  return principal.getName();
}
}

 

In my ear I have a jboss-app.xml like this:

 

<jboss-app xmlns="http://www.jboss.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="7.0">

<security-domain>tutorial</security-domain>

</jboss-app>

 

My client code is this:

 

@SuppressWarnings("nls")
public class Client {

private static String applicationName = "test.ear";
private static String remoteModuleName = "remote.jar";

private static String userName = "admin";
private static String password = "test";

 

public static void main(final String[] args) {

  final Client client = new Client();
  try {
   client.run();
  } catch (final Exception ex) {
   ex.printStackTrace();
  }
}

 

public Client() {
  // create client configuration
  final EJBClientConfiguration clientConfiguration = new PropertiesBasedEJBClientConfiguration(
    createClientConfigurationProperties());

  // create a context selector
  final ContextSelector<EJBClientContext> contextSelector = new ConfigBasedEJBClientContextSelector(
    clientConfiguration);

  // set the selector for use
  EJBClientContext.setSelector(contextSelector);
}

 

public void run() throws Exception { 

  // lookup and use secured bean
  final SecuredRemote secured = lookupBean("Secured", SecuredRemote.class, false);
  System.out.println(secured.getCurrentUserName());
}

 

private static <T> T lookupBean(final String beanName, final Class<T> viewClass, final boolean stateful)
   throws NamingException {
  final String lookupName = String.format("ejb:%1$s/%2$s/%3$s!%4$s?%5$s", applicationName, remoteModuleName,
    beanName, viewClass.getName(), stateful ? "stateful" : "stateless");

  return (T) getInitialContext().lookup(lookupName);
}

 

private static Context context;

private static Context getInitialContext() throws NamingException {
  if (context == null) {
   final Hashtable<Object, Object> contextProperties = new Hashtable<>();
   contextProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
   contextProperties.put(Context.SECURITY_PRINCIPAL, userName);
   contextProperties.put(Context.SECURITY_CREDENTIALS, password);

   contextProperties.put("jboss.naming.client.ejb.context", true);
   contextProperties.put(Context.PROVIDER_URL, "remote://localhost:4447");

   //contextProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");

   context = new InitialContext(contextProperties);
  }
  return context;
}

 

private static Properties createClientConfigurationProperties() {
  final Properties properties = new Properties();
  properties.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
  properties.put("remote.connections", "default");

  properties.put("remote.connection.default.host", "localhost");
  properties.put("remote.connection.default.port", "4447");

  properties.put("remote.connection.default.username", userName);
  properties.put("remote.connection.default.password", password);

  properties.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "true");
  // properties.put("remote.connection.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS","JBOSS-LOCAL-USER");
  properties.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");

  return properties;
}
}

 

The database query from the login module is executed but using the "jdbc.spy" is see the user name is a random UUID. So I never see the entered user name on the server side. In the end there is of course this exception on server side:

JBAS014134: EJB Invocation failed on component Secured for method public abstract java.lang.String com.qualitype.tutorial.remote.SecuredRemote.getCurrentUserName(): javax.ejb.EJBAccessException: JBAS013323: Invalid User

 

If I enable the "SASL_DISALLOWED_MECHANISMS" property the  is: java.lang.IllegalStateException: No EJB receiver available for handling [...] combination

If I enable the "INITIAL_CONTEXT_FACTORY" property the exception is: javax.security.sasl.SaslException: Authentication failed: all available authentication mechanisms failed

 

As you can see, I use a lot of different properties. This is a collection copied from various samples from the forum. I think I tested nearly all combination of them but it always leads me to one of the exceptions above.

 

In my opinion the configuration on server side should be alright. But I have a lot of doubts concerning the client configuration...

  • 1. Re: Remote client access with database login module: user name and password are UUIDs
    f.ulbricht Newbie

    After checking the logfile again, it shows the user name is now "$local" for the sample above.

     

     

    15:09:38,292 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] (EJB default - 2) initialize

    15:09:38,292 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] (EJB default - 2) Security domain: tutorial

    15:09:38,292 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] (EJB default - 2) DatabaseServerLoginModule, dsJndiName=java:/TutorialDS

    15:09:38,292 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] (EJB default - 2) principalsQuery=SELECT ENCODED_PASSWORD FROM SYSTEM_USER WHERE USER_NAME = ?

    15:09:38,292 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] (EJB default - 2) rolesQuery=SELECT ROLE_NAME, 'Roles' FROM SYSTEM_USER_ROLE WHERE USER_NAME = ?

    15:09:38,292 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] (EJB default - 2) suspendResume=true

    15:09:38,292 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] (EJB default - 2) login

    15:09:38,292 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] (EJB default - 2) commit, loginOk=true

    15:09:38,292 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] (EJB default - 2) getRoleSets using rolesQuery: SELECT ROLE_NAME, 'Roles' FROM SYSTEM_USER_ROLE WHERE USER_NAME = ?, username: $local

    15:09:38,292 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] (EJB default - 2) suspendAnyTransaction

    15:09:38,292 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] (EJB default - 2) Excuting query: SELECT ROLE_NAME, 'Roles' FROM SYSTEM_USER_ROLE WHERE USER_NAME = ?, with username: $local

    15:09:38,307 DEBUG [jboss.jdbc.spy] (EJB default - 2) java:/TutorialDS [Connection] prepareStatement(SELECT ROLE_NAME, 'Roles' FROM SYSTEM_USER_ROLE WHERE USER_NAME = ?)

    15:09:38,307 DEBUG [jboss.jdbc.spy] (EJB default - 2) java:/TutorialDS [PreparedStatement] setString(1, $local)

    15:09:38,307 DEBUG [jboss.jdbc.spy] (EJB default - 2) java:/TutorialDS [PreparedStatement] executeQuery()

    15:09:38,307 DEBUG [jboss.jdbc.spy] (EJB default - 2) java:/TutorialDS [ResultSet] next()

    15:09:38,307 TRACE [org.jboss.security.auth.spi.DatabaseServerLoginModule] (EJB default - 2) No roles found

    15:09:38,307 DEBUG [jboss.jdbc.spy] (EJB default - 2) java:/TutorialDS [ResultSet] close()

    15:09:38,307 DEBUG [jboss.jdbc.spy] (EJB default - 2) java:/TutorialDS [Statement] close()

    15:09:38,307 DEBUG [jboss.jdbc.spy] (EJB default - 2) java:/TutorialDS [Connection] close()

  • 2. Re: Remote client access with database login module: user name and password are UUIDs
    Darran Lofthouse Master

    If you are seeing the user as $local you need to disable the JBOSS-LOCAL-USER SASL mechanisms on the client side.

     

    The XNIO option for this is : -

     

    org.xnio.Options.SASL_DISALLOWED_MECHANISMS JBOSS-LOCAL-USER

     

    You will need to disable this both for the JNDI connection and for the EJB connection, there are example of this on the other posts discussing the same issue.

  • 3. Re: Remote client access with database login module: user name and password are UUIDs
    f.ulbricht Newbie

    That's it - it works!

     

    Here my final (minimized) configuration:

     

    remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
    remote.connections=default

    remote.connection.default.host=localhost
    remote.connection.default.port=4447

    remote.connection.default.username=userName

    remote.connection.default.password=password

    remote.connection.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=JBOSS-LOCAL-USER
    remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT=false

     

    And for JNDI:

     

    Context.URL_PKG_PREFIXES=org.jboss.ejb.client.naming

     

    This seems to be all that is required to have it work.

     

    Thank you very much!

  • 4. Re: Remote client access with database login module: user name and password are UUIDs
    Sebastian Bayerlein Newbie

    Hello,

    I'm facing the same problem. In the client I use a LoginContext to pass the username/password to the context:

     

    final Properties jndiProperties = new Properties();

     

    jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

    jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");

    jndiProperties.put(Context.PROVIDER_URL, "remote://localhost:4447");

     

    jndiProperties.put("jboss.naming.client.ejb.context", true);

    jndiProperties.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");      

     

    InitialContext context = null;

     

    try

    {

              Configuration.setConfiguration ( new LoginConfiguration ());

              Class<?> cb = Class.forName ( "org.jboss.security.auth.callback.UsernamePasswordHandler" );

              Constructor<?> c = cb.getConstructor ( new Class[] { String.class, char[].class });

              LoginContext lc = new LoginContext ( "other", ( CallbackHandler ) c.newInstance ( new Object[] { "fapiuser", "guest".toCharArray() }));

              lc.login();

     

              context = new InitialContext(jndiProperties);

     

              EJBObject ejbObject = (EJBObject) context.lookup("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);

              System.out.println("remote: " + ejbObject);

     

              ...

     

    On server-side I use a custom login module:

     

    public class CustomLoginModule extends UsernamePasswordLoginModule {

     

      protected String getUsersPassword() throws LoginException

      {

        final String username = super.getUsername();

        log.info( ">>> username: '" + username + "'" );

                        ...

      }

    }

     

    In JBoss logfile I also see the user name as a random UUID. Can somebody help me to solve this problem?

     

     

    Regards,

    Sebastian

  • 5. Re: Remote client access with database login module: user name and password are UUIDs
    andrei povodyrev Newbie

    Seems like all remote calls have to be authenticated by remoting-connector.

    This is the key  <connector name="remoting-connector" socket-binding="remoting" security-realm="TutorialRealm"/> where whole jboss ejb remote access is tied to a single app realm. Seems like a mess. If you have multiple apps on the same server with own security, maintaining acces to them with remote client is going to be nightmare.


    Application login module must have <module-option name="password-stacking" value="useFirstPass"/> to piggy back on cached Principal/Credentials

     

    If security realm (ApplicationRealm by default) is removed from remoting-connector, there is no way to authenticate ejb remote call.

     

    Tried multiple approaches

    1)

    jndiProperties.put(InitialContext.SECURITY_PRINCIPAL, "user");

    jndiProperties.put(InitialContext.SECURITY_CREDENTIALS, "pass");

    2)

    org.jboss.security.client.SecurityClient

    3)

    org.jboss.security.auth.callback.AppCallbackHandler

     

    User credential set by above means do not get to java ee security context and random UUID values are used on server, or $local if 

    setting  SASL_DISALLOWED_MECHANISMS=JBOSS-LOCAL-USER  not used

     

    A frequently refernced link from jboss7 docs  https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI is not sufficient to make your remote clients work because it leaves the server configuration part out of discussion.

     

    Frustrated after fighting this for the thrid day in the row.

  • 6. Re: Remote client access with database login module: user name and password are UUIDs
    Daniel Jipa Newbie
    Seems like all remote calls have to be authenticated by remoting-connector.
    This is the key  <connector name="remoting-connector" socket-binding="remoting" security-realm="TutorialRealm"/> where whole jboss ejb remote access is tied to a single app realm. Seems like a mess. If you have multiple apps on the same server with own security, maintaining acces to them with remote client is going to be nightmare.
    
    

     

    My workaround for this was to put a jar file with a dummy login module that just let authentication requests pass, considering that other security-domains are enabled in EJBs.

     

     

     

    Application login module must have <module-option name="password-stacking" value="useFirstPass"/> to piggy back on cached Principal/Credentials
    

     

    That didn't work for me in JBoss 7.1.1. Do I miss other configurations for making cache to work ?

  • 7. Re: Remote client access with database login module: user name and password are UUIDs
    andrei povodyrev Newbie

    Daniel,

    I use Jboss 7.1.0. password-stacking will work if you have more than one LoginModule. Say, you leave security realm for remoting unchanged (ApplicationRealm configured by application-users.properties),  Then org.jboss.as.security.remoting.RemotingLoginModule will place principal in the sharedState map maintained by javax.security.auth.login.LoginContext. Then your DatabseServerLoginModule gets its turn it will pick the pricipal cached by RemotingLoginModule. If <module-option name="password-stacking" value="useFirstPass"/> is enabled.

     

    Your suggestion for dummy LoginModule is good. There you can place principal/credential supplied by remote client(remote.connection.default.username/password) into sharedState which in turn will be picked up by any other LoginModule in the array of applications deployed on this jboss instance.

     

    I see configuration could be like this

                <security-realm name="ApplicationRealm">
                    <authentication>
                        <jaas name="my-dummy-domain"/>
                    </authentication>
                </security-realm>

     

                <security-domain name="my-dummy-domain" cache-type="default">
                    <authentication>
                        <login-module code="MyDummyLoginModule" flag="required">
                            <module-option name="password-stacking" value="useFirstPass"/>
                        </login-module>
                    </authentication>
                </security-domain>

     

                <security-domain name="myRealDomain" cache-type="default">
                    <login-module code="Database" flag="required">
                        <module-option name="password-stacking" value="useFirstPass"/>
                        <module-option name="dsJndiName" value=""/>
                        <module-option name="principalsQuery" value="select password ..?"/>
                        <module-option name="rolesQuery" value="select ur.role, 'Roles' from ..."/>
                    </login-module>
                </security-domain>

     

    Pls, let me know if you use your dummy loginmodule in a similar way

    Andrei

  • 8. Re: Remote client access with database login module: user name and password are UUIDs
    Daniel Jipa Newbie

    Hello Andrei,

     

    I didn't had the time to handle this upgrade to JBoss 7 this last few days. Indeed I use my dummy login module in this way, without this option:

     

    <module-option name="password-stacking" value="useFirstPass"/>

         

    for it.

     

    But this option is enabled in my real login module and the multiple call to EJB problem persists even when calling methods remotely or locally from a war.

    The problem with multiple calls to the EJB as I understood it will be solved in 7.1.2 version.