title: How to catch FailedLoginException in Picketbox/Undertow on Wildfly 8 to apply CORS
body: <p>With the help of a ContainerResponseFilter I am able to apply CORS headers to all outgoing Responses, and with an ExceptionMapper I can do the same on all Errors and Exceptions, <em>except</em> for any authentication related Exceptions that Picketbox/Undertow is supposed to throw in Wildfly. </p>
  
  <p>My ExceptionMapper <em>never</em> catches it no matter what I try, and as a result, the frontend can't read the 401 status since the response doesn't have the CORS headers appended (the XHR HTTP status code just becomes 0).</p>
  
  <p>I am using <a href="https://github.com/m9aertner/PBKDF2" rel="nofollow">this</a> PBKDF2 setup to authenticate against a MySQL database, and at first I thought that maybe since the authentication was run in a separate module it wasn't being caught by my application, but even after moving all the authentication code into my own application I have the same problem. </p>
  
  <p>This is the log entry I get when trying to authenticate with the wrong password (I get a very similar one when I simply don't send any credentials at all):</p>
  
  <blockquote>
    <p>2014-11-29 16:11:08,053 TRACE [org.jboss.security] (default task-4) PBOX000224: End getAppConfigurationEntry(PBKDF2DatabaseDomain), AuthInfo: AppConfigurationEntry[]:
    [0]
    LoginModule Class: com.example.myapplication.security.SaltedDatabaseServerLoginModule
    ControlFlag: LoginModuleControlFlag: required
    Options:
    name=dsJndiName, value=java:/user
    name=principalsQuery, value=SELECT <code>Hash</code> FROM <code>account</code> WHERE ID=?
    name=rolesQuery, value=SELECT <code>Role</code>, 'Roles' FROM account WHERE <code>account</code>.<code>ID</code>=?</p>
    
    <p>2014-11-29 16:11:08,053 TRACE [org.jboss.security] (default task-4) PBOX000236: Begin initialize method
    2014-11-29 16:11:08,053 TRACE [org.jboss.security] (default task-4) PBOX000262: Module options [dsJndiName: java:/user, principalsQuery: SELECT <code>Hash</code> FROM <code>account</code> WHERE ID=?, rolesQuery: SELECT <code>Role</code>, 'Roles' FROM account WHERE <code>account</code>.<code>ID</code>=?, suspendResume: true]
    2014-11-29 16:11:08,053 TRACE [org.jboss.security] (default task-4) PBOX000240: Begin login method
    2014-11-29 16:11:08,053 TRACE [org.jboss.security] (default task-4) PBOX000263: Executing query SELECT <code>Hash</code> FROM <code>account</code> WHERE ID=? with username 1@2.se
    2014-11-29 16:11:08,062 DEBUG [org.jboss.security] (default task-4) PBOX000283: Bad password for username 1@2.com
    2014-11-29 16:11:08,062 TRACE [org.jboss.security] (default task-4) PBOX000244: Begin abort method
    2014-11-29 16:11:08,062 DEBUG [org.jboss.security] (default task-4) PBOX000206: Login failure: javax.security.auth.login.FailedLoginException: PBOX000070: Password invalid/Password required
        at org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(UsernamePasswordLoginModule.java:284) [picketbox-4.0.21.Beta1.jar:4.0.21.Beta1]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.8.0_25]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) [rt.jar:1.8.0_25]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.8.0_25]
        at java.lang.reflect.Method.invoke(Method.java:483) [rt.jar:1.8.0_25]
        at javax.security.auth.login.LoginContext.invoke(LoginContext.java:755) [rt.jar:1.8.0_25]
        at javax.security.auth.login.LoginContext.access$000(LoginContext.java:195) [rt.jar:1.8.0_25]
        at javax.security.auth.login.LoginContext$4.run(LoginContext.java:682) [rt.jar:1.8.0_25]
        at javax.security.auth.login.LoginContext$4.run(LoginContext.java:680) [rt.jar:1.8.0_25]
        at java.security.AccessController.doPrivileged(Native Method) [rt.jar:1.8.0_25]
        at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680) [rt.jar:1.8.0_25]
        at javax.security.auth.login.LoginContext.login(LoginContext.java:587) [rt.jar:1.8.0_25]
        at org.jboss.security.authentication.JBossCachedAuthenticationManager.defaultLogin(JBossCachedAuthenticationManager.java:408) [picketbox-infinispan-4.0.21.Beta1.jar:4.0.21.Beta1]
        at org.jboss.security.authentication.JBossCachedAuthenticationManager.proceedWithJaasLogin(JBossCachedAuthenticationManager.java:345) [picketbox-infinispan-4.0.21.Beta1.jar:4.0.21.Beta1]
        at org.jboss.security.authentication.JBossCachedAuthenticationManager.authenticate(JBossCachedAuthenticationManager.java:333) [picketbox-infinispan-4.0.21.Beta1.jar:4.0.21.Beta1]
        at org.jboss.security.authentication.JBossCachedAuthenticationManager.isValid(JBossCachedAuthenticationManager.java:146) [picketbox-infinispan-4.0.21.Beta1.jar:4.0.21.Beta1]
        at org.wildfly.extension.undertow.security.JAASIdentityManagerImpl.verifyCredential(JAASIdentityManagerImpl.java:111)
        at org.wildfly.extension.undertow.security.JAASIdentityManagerImpl.verify(JAASIdentityManagerImpl.java:82)
        at io.undertow.security.impl.BasicAuthenticationMechanism.authenticate(BasicAuthenticationMechanism.java:110) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:281) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:298) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.access$100(SecurityContextImpl.java:268) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.security.impl.SecurityContextImpl.attemptAuthentication(SecurityContextImpl.java:131) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.security.impl.SecurityContextImpl.authTransition(SecurityContextImpl.java:106) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.security.impl.SecurityContextImpl.authenticate(SecurityContextImpl.java:99) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:54) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.server.handlers.DisableCacheHandler.handleRequest(DisableCacheHandler.java:27) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.server.Connectors.executeRootHandler(Connectors.java:177) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:727) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_25]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_25]
        at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_25]</p>
  </blockquote>
  
  <p>And this is my ExceptionMapper class (currently set to catch all Throwables in a vain attempt to make it work):</p>
  
  <pre><code>@Provider
  public class NotAuthorizedExceptionMapper implements ExceptionMapper&lt;Throwable&gt;{
  
  @Override
  public Response toResponse(Throwable exception) {
      Response response = Response.status(Response.Status.UNAUTHORIZED).build();
      response.getHeaders().putSingle("Access-Control-Allow-Origin", "*");
      response.getHeaders().putSingle("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PUT, DELETE");
      response.getHeaders().putSingle("Access-Control-Allow-Headers", "origin, content-type, accept, authorization, access-control-allow-origin, access-control-allow-methods, access-control-allow-headers, allow, content-length, date, last-modified");
      return response;
  }
  </code></pre>
  
  <p>What can I do to catch these authentication Exceptions and thus append CORS to them?</p>