Note on terminology:
- Authentication Mechanism (AM) herein refers to any component responsible for making authentication statements pertaining to, and registering / establishing, as a result, the identity of, authenticated caller entities with / in a Java EE runtime. Such components may be specific to the Application Server (AS) or Java EE-standard; AS implementation details or types destined for extension by the Java EE application developer; deployed as part of a Java EE application or as part of the AS. One such component is your JAAS
LoginModule
(LM). While Identity Store (IS) appears to be the (semi-)normative term used for referring to (among other things) LMs nowadays, I wanted to reserve it for your application-specific, persistence layer (e.g. JPA @Entity
) types representing your users, and thus had to establish this (ill-defined) distinction. "Why are you being vague?", you might ask, "Can't you just call an LM an LM?". Because I know nothing about JBoss LMs! In fact, I am neither a JBoss user, nor someone using JAAS in Java EE. Still, I felt like I could contribute an answer applying to the general case, hence the inevitable vagueness.
- Deactivated user refers, for lack of a better term, to your "to-be-kicked-out-user", i.e., the user whose rights (groups, roles, permissions--whatever they are called in there) have been revoked in some way at the IS level.
First of all, there is no standard Java EE API that will expose the
Subject
or
HttpSession
of an arbitrary user to your code. You could theoretically record that information yourself, e.g. during authentication, but I will assume that this is not quite what you want. Furthermore, regarding the
Subject
specifically, while no standard explicitly forbids its (
Principal
/ credential collection's) modification during servicing of a request on the
Subject
's behalf, none state that it
has to be either. It is in fact not even clear whether the
current authenticated caller's
Subject
--the one populated during authentication and retrievable via
JACC's
"javax.security.auth.Subject.container"
PolicyContextHandler
--
must coincide with the data structure the runtime queries the
Policy
with when making authorization decisions; that is, the runtime might only provide you with a copy, use an entirely different representation of the authenticated caller internally, or anything in between. Therefore, even if you were able to modify the
Subject
, doing so would not necessarily affect the security context in effect.
Moving on to what can be done. Your need can be addressed either on the authentication and/or on the authorization side, with the former approach being considerably easier to employ than the later. Since you did not answer my comment, I will briefly cover both of its possible answers.
Prohibiting caller re-authentication
Once the application has deactivated the user, it must somehow instruct the AM to cease re-authenticating them on subsequent requests they issue. In order to reduce coupling, the application will typically not communicate with the AM directly, but satisfy some condition evaluated by the later instead. For instance, the application might assign some special "locked_out" right to the user, or set an HttpSession
attribute. When asked to re-authenticate the deactivated user, the AM would acknowledge deactivation and refuse to re-authenticate them. Subsequently it would invalidate the user's session. How exactly it would accomplish that depends on its kind and implementation. Your LM would probably have to leverage the "javax.servlet.http.HttpServletRequest"
JACC PolicyContextHandler
for that purpose. A JASPIC ServerAuthModule
would have immediate access to the request instance, having received it as a validateRequest
argument. Some other component would perhaps have to resort to use of AS internals, or burden the application with the responsibility of session invalidation (some call-intercepting component, such as a Servlet Filter
, would have to query the IS a second time and act accordingly).
The aforementioned approach obviously requires the ability to modify the functionality of the AM. Additionally, a caching AM needs to evaluate said deactivation condition before reusing its previously established authentication outcome. Lastly, as mentioned in the comment, if, at the time of a user's IS access revocation, a request on that user's behalf is in the process of being serviced (having arrived / having been authenticated prior to the occurrence of the access revocation event), servicing of that request will complete normally (unless the application requests re-authentication of that user, e.g. via HttpServletRequest#
(login
|authenticate
).
Prohibiting caller re-authorization
While, as I mentioned in the begining, users' Subject
s are not readily retrievable / modifiable, the backing Policy
, against which, on JACC-compliant Java EE runtimes those get authorized, actually is. Unfortunately, the default AS-provided JACC provider (PolicyConfiguration
+ Policy
) has a serious limitation: it only allows you to operate on Java EE roles, not on the caller Principal
s mapped to, i.e., "having", those roles. For example, the default provider allows you to extend the Permission
s that Principal
s mapped to the "admin" role have; it allows you to remove the "admin" role along with all its Permission
s; but it does not allow you to decide who gets to be an "admin"--at least not in a standard way.
This limitation basically leaves you with two alternatives, as far as JACC is concerned: Either have the AM add a "dummy" group Principal
to each caller's Subject
, with the same name as that of the respective caller Principal
. Then, upon user deactivation, add (via PolicyConfiguration#addToRole
) a custon Permission
pertaining to the "dummy" group. Finally, check (e.g. via AccessController#checkPermission) from "application-space" code whether the user has the Permission
and if so kick them out. But wait, this is utterly meaningless--why even bother using the Policy
in the first place, if it is incapable of handling authorization on its own? The alternative is to author and install your own JACC provider. Doing so would give you full control over Principal
-/group-to-role mappings and enable you to act pretty much however you please, authorization-wise, with that information from that point on. Writing a new provider is nontrivial though, particularly because it would have to accommodate for the authorization needs JRE-wide, not just in the scope of a single application. I doubt that your requirement justifies an amount of work that high. If you still feel like going down that path, the JACC-related articles on Arjan Tijms' blog are a great starting point.