Eventually we handled this by adding Interceptor in which the account locking mechanism is invoked. Thus JAAS Login module cares about authentication and authorization only and if credentials are correct it authenticate user, but if the account is locked then on our own Interceptor the application exception is raised. In this way all methods invocations are handled.
Anyway would be great if anybody may share Your solution for that common use case.
We are experiencing the same thing after migrating our EJB2 application from JBoss 4.2.3 to 6.1.0. The behavior in JBoss 4.2.3 used to be that the original FailedLoginException from the JAAS mechanism was propagated to the client. In JBoss 6.1.0, the client always receives the generic SecurityException thrown in the SecurityInterceptor.
I have been able to trace it back to the following change;
Appearantly, you can implement your own observer instead, it gets called on authenticationFailed. With that you might be able to rethrow the original exception (SecurityActions.getContextException()).
I have tried implementing a custom interceptor as you describe. Without the use of a ThreadLocal, but using the SecurityActions.getContextException(). That seems to do the trick just fine.
Still, I would be interested to learn about the best practice on how to implement this use case. The use of SecurityActions is package restricted, so i am not completely satisfied with my current solution.