title: Wildfly and JAAS login module
body: <p>I'm playing with <code>Wildfly-9.0.1.Final</code> and <code>JAAS</code> but I'm not having so much fun.. I implemented my custom login module:</p>
  
  <pre><code>public class MongoLoginModule implements LoginModule {
  
  @Inject
  protected MongoDB mongoDb;
  protected Subject subject;
  protected Principal identity;
  protected boolean loginOk;
  
  private CallbackHandler callbackHandler;
  private Map sharedState;
  private Map options;
  
  private Logger log = LoggerFactory.getLogger(MongoLoginModule.class);
  
  public boolean abort() throws LoginException {
      log.info("abort!");
      subject = null;
      return true;
  }
  
  public boolean commit() throws LoginException {
      // TODO Auto-generated method stub
      log.info("commit!");
      if(loginOk) {
          UserGroup userGroup = new UserGroup("Roles");
          userGroup.addMember(new RolePrincipal("userA"));
          subject.getPrincipals().add(userGroup);
          subject.getPublicCredentials().add(userGroup);
          return true;
      }
      return false;
  }
  
  public void initialize(Subject subject, CallbackHandler callbackHandler,
          Map&lt;String, ?&gt; sharedState, Map&lt;String, ?&gt; options) {
      log.info("Initializing MongoLoginModule.");
      this.subject = subject;
      this.callbackHandler = callbackHandler;
      this.sharedState = sharedState;
      this.options = options; 
  }
  
  public boolean login() throws LoginException {
      log.info("login requested.");
      NameCallback nameCallback = new NameCallback("username:");
      PasswordCallback passwordCallback = new PasswordCallback("password:", false);
      try {
          callbackHandler.handle(new Callback[]{nameCallback, passwordCallback});
          String username = nameCallback.getName();
          String password = new String(passwordCallback.getPassword());
          log.info("check credentials for: "+username);
          if(username.equals("jim") &amp;&amp; password.equals("jim")) {
              loginOk = true;
              identity = new UserPrincipal(username);
              subject.getPrincipals().add(identity);
              subject.getPublicCredentials().add(identity);
              return true;
          }
      } catch (IOException e) {
          e.printStackTrace();
      } catch (UnsupportedCallbackException e) {
          e.printStackTrace();
      }
  
      return false;
  }
  
  public boolean logout() throws LoginException {
      if(subject != null &amp;&amp; identity != null) {
          subject.getPrincipals().remove(identity);
          return true;
      }
      return false;
  }
  
  public Document getUserByName(String userName) {
      FindIterable&lt;Document&gt; results = mongoDb.getCollection().find(new Document("username", userName));
      return results.iterator().next();
  }
  
  public void getRoles() {
  //      FindIterable&lt;Document&gt; results = mongoDb.getCollection().find(new Document("username", userName));
  //      results.iterator().next().get
  }
  </code></pre>
  
  <p>It's not perfect but it's enought for now. This pure JAAS login module is a module in my Wildfly. I configure the security domain this way:</p>
  
  <pre><code>&lt;security-domain name="MongoLoginRealm" cache-type="default"&gt;
      &lt;authentication&gt;
          &lt;login-module code="it.bytebear.jaas.mongo.module.MongoLoginModule" flag="required" module="login.mongodb"&gt;
              &lt;module-option name="mongodb.uri" value="mongodb://localhost:21017/test?collection"/&gt;
          &lt;/login-module&gt;
      &lt;/authentication&gt;
  &lt;/security-domain&gt;
  </code></pre>
  
  <p>I implemented some RESTful web service to do some test. I'm only posting the relevant code:</p>
  
  <pre><code>...
  
  @POST
  @Path("/login")
  @PermitAll
  @Consumes(MediaType.APPLICATION_JSON)
  // @Consumes("application/x-authc-username-password+json")
  public Response login(User userCredentials) {
      log.info("logging in.");
      try {
          MongoModuleCallbackHandler handler = new MongoModuleCallbackHandler();
          handler.setUsername(userCredentials.getUserName());
          handler.setPassword(userCredentials.getPassword().toCharArray());
          LoginContext loginContext = new LoginContext("MongoLoginRealm", handler);
          loginContext.login();
          Subject subject = loginContext.getSubject();
          List&lt;String&gt; roles = new ArrayList&lt;String&gt;();
          for (Principal p : subject.getPrincipals()) {
              roles.add(p.getName());
          }
          userCredentials.setRoles((String[]) roles.toArray());
          return Response.ok().entity(userCredentials)
                  .type(MediaType.APPLICATION_JSON_TYPE).build();
      } catch (Exception e) {
          log.error("login fails.", e);
          return Response.status(Status.FORBIDDEN).entity("Not logged")
                  .type(MediaType.APPLICATION_JSON_TYPE).build();
      }
  }
  ...
  </code></pre>
  
  <p>In <code>web.xml</code> <code>auth-method</code> is <code>BASIC</code> and <code>realm-name</code> is <code>MongoLoginRealm</code>, the same used in <code>jboss-web.xml</code> and when instantiating <code>LoginContext</code>. When I invoke the <code>login</code> method I got this exception:</p>
  
  <pre><code>22:39:49,421 ERROR [it.bytebear.web.mongo.UserServices] (default task-1) login fails.: javax.security.auth.login.LoginException: impossibile trovare la classe Login
  Module: it.bytebear.jaas.mongo.module.MongoLoginModule from [Module "deployment.MongoWebTest.war:main" from Service Module Loader]
      at javax.security.auth.login.LoginContext.invoke(LoginContext.java:822)
      at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203)
      at javax.security.auth.login.LoginContext$4.run(LoginContext.java:698)
      at javax.security.auth.login.LoginContext$4.run(LoginContext.java:696)
      at java.security.AccessController.doPrivileged(Native Method)
      at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:695)
      at javax.security.auth.login.LoginContext.login(LoginContext.java:594)
      at it.bytebear.web.mongo.UserServices.login(UserServices.java:66)
  </code></pre>
  
  <p>My login module is never been executed. What am I missing?</p>
  
  <p><strong>UPDATE:</strong>
  Moving the login module .jar into the web application it works. Maybe there is something wrong in my Wildfly. Here is my module structure:</p>
  
  <pre><code>%wildfly_home%/modules/system/layers/base/login/mongodb/main/module.xml             
  %wildfly_home%/modules/system/layers/base/login/mongodb/main/mongo-java-driver-3.0.3.jar
  %wildfly_home%/modules/system/layers/base/login/mongodb/main/MongoLoginModule.jar
  </code></pre>
  
  <p>and this is the <code>module.xml</code>:</p>
  
  <pre><code>&lt;module xmlns="urn:jboss:module:1.1" name="login.mongodb"&gt;
      &lt;resources&gt;
          &lt;resource-root path="MongoLoginModule.jar"/&gt;
          &lt;resource-root path="mongo-java-driver-3.0.3.jar"/&gt;
      &lt;/resources&gt;
      &lt;dependencies&gt;
          &lt;module name="org.apache.log4j"/&gt;
          &lt;module name="javax.api"/&gt;
          &lt;module name="org.slf4j"/&gt;
      &lt;/dependencies&gt;
  &lt;/module&gt;
  </code></pre>
  
  <p>I have to figure out why the login module isn't reachable as Wildfly module.</p>