Question

I'm trying to write my own LoginModule named CustomLoginModule for Wildfly 8.0.0.CR1 which is registered for a security-domain in the standalone.xml:

<security-domain name="other" cache-type="default">  
  <authentication>  
    <login-module code="Remoting" flag="optional">  
      <module-option name="password-stacking" value="useFirstPass"/>  
    <login-module>  
    <login-module code="com.someExample.CustomLoginModule" flag="required">  
      <module-option name="password-stacking" value="useFirstPass"/>  
    </login-module>  
  </authentication>  
</security-domain>

In my remote client I'm using the following jboss-ejb-client.properties:

endpoint.name=client-endpoint  
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false  
remote.connections=default  
remote.connection.default.host=[...]  
remote.connection.default.port=[...]  
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false  
remote.connection.default.username=myUserName  
remote.connection.default.password=abcde  

Obtaining the InitialContext in the client looks like:

Properties props = new Properties();  
props.put(Context.URL_PKG_PREFIXES,  "org.jboss.ejb.client.naming");  
InitialContext ctx = new InitialContext(props);  

Basically this works fine and my login-module is invoked when accessing an EJB via the remote-interface which is annotated with the correct @SecurityDomain.

In the login-module, I can read the username using the callback or the sharedState which is passed to the initialize method. But I was not able to get the provided password (in this example I would expect to get shomewhere the string abcde).

I have already tried several things to get the password. Via the callback (like I did on JBoss 5), via the given sharedState, ... Even if I derive from the org.jboss.security.auth.spi.UsernamePasswordLoginModule or when using code from the JBoss-Quickstart examples, I cannot see the password which has been set at the client. Instead, I always get the following string returned as password org.jboss.as.security.remoting.RemotingConnectionCredential@....

Edit: This is the code of my LoginModule (or at least one version of it):

import javax.security.auth.callback.*;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

public class CustomLoginModule implements LoginModule
{
    private CallbackHandler callbackHandler;

    public void initialize(Subject subject, CallbackHandler callbackHandler,
      Map<String, ?> sharedState, Map<String, ?> options)
    {
        this.callbackHandler = callbackHandler;
    }

    public boolean login() throws LoginException
    {
        NameCallback namecallback = new NameCallback("Username");
        PasswordCallback passwordcallback = new PasswordCallback("Password", false);
        CallbackHandler handler = this.callbackHandler;
        try {
            handler.handle(new Callback[] { namecallback, passwordcallback });
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        String username = namecallback.getName();
        char[] password2 = passwordcallback.getPassword();
        String password = new String(password2);
        System.out.println(username + " / " + password);
        if (username == null || password == null) {
            return false;
        }
        // do authentication...
        return true;
    }

    public boolean commit() throws LoginException
    { ... }

    public boolean abort() throws LoginException
    { ... }

    public boolean logout() throws LoginException
    { ... }
}

No correct solution

OTHER TIPS

I've created a small testproject now to find out how I can get this to work. And I think it is worth sharing.

We loop through the ClientLoginModule (which is provided by Wildfly) in the first stage (of the ApplicationRealm which is used to secure the remote- connection). This module stores the credentials (somewhere?) and they are available afterwards to my other login-module.

<security-realm name="ApplicationRealm">
    <authentication>
        <jaas name="AppRealmLoopThrough"/>
    </authentication>
</security-realm>

Of course, this security-domain has to be defined afterwards:

<security-domain name="AppRealmLoopThrough" cache-type="default">
    <authentication>
        <login-module code="Client" flag="required">
            <module-option name="multi-threaded" value="true"/>
        </login-module>
    </authentication>
</security-domain>
<security-domain name="other" cache-type="default">
    <authentication>
        <login-module code="com.someExample.CustomLoginModule" flag="required"/>
    </authentication>
</security-domain>

In the CustomLoginModule (which extends UsernamePasswordLoginModule) I can do the following to retrieve username and password:

final String[] usernameAndPassword = getUsernameAndPassword();
System.out.println("received username: " + usernameAndPassword[0] + " and password " + usernameAndPassword[1]);

getUsernameAndPassword() is a method provided by the base class UsernamePasswordLoginModule.

Of course, the secured EJBs have to be annoteded with @SecurityDomain("other") (or via deployment-descriptor) to get my CustomLoginModule invoked.

Btw: I know that the security-domain other has some special meaning and should not be used for the application - this was just for testing... ;)

I was not very successful when trying to find an explanation for this. For me it seems that the login-modules are invoked in two steps: first when the AppRealmLoopThrough is used for the ApplicationRealm which is the security-realm for the http-remoting-connector. In this "step" the username and password are available. The second "step" is the invocation of the CustomLoginModule when the container checks the EJB-permissions. In this phase by default there is no way to get the password (as tried initially). Does this sound reasonable?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top