jsr375-experts@javaee-security-spec.java.net

[jsr375-experts] Re: CDI Authentication Events

From: Alex Kosowski <alex.kosowski_at_oracle.com>
Date: Sun, 29 Mar 2015 21:41:10 -0400

If we do not currently have a JIRA for authentication events, I will add
it. I think it makes sense to produce events for authentication in
general and not JASPIC specificially.

> and require that the notifications be sent for any authentication on
> the platform, JASPIC or otherwise, which affects the application?
> Just wondering, but how would you propose "otherwise" works?
I meant that we could specify that authentication notify events are
produced for platform-specific/non-JASPIC authentication mechanisms too.
For example, this would allow an application to audit logins users even
if JASPIC is not used.

Thanks,
Alex


On 3/19/15 4:14 AM, arjan tijms wrote:
> Hi,
>
> On Thu, Mar 19, 2015 at 3:34 AM, Alex Kosowski
> <alex.kosowski_at_oracle.com <mailto:alex.kosowski_at_oracle.com>> wrote:
>
> Hi,
>
> 1. Events indicating a well known authentication step has happened
> (Logged-in, Login-Failed, Logged-out, ...)
>
> This is somewhat represented in
> https://java.net/jira/browse/JASPIC_SPEC-21, which only applies to
> JASPIC. Would it make sense to move this JIRA to JAVAEE_SECURITY_SPEC,
>
>
> Yes, that could be an option.
>
> I created the issue for JASPIC at the time since A) it concerns an
> authentication concern and JASPIC is about that in Java EE, and B)
> there wasn't really an other place.
>
> The description can be slightly adjusted, from:
>
> "For several use cases it would be quite convenient if JASPIC would
> throw events at several important moments of the authentication
> message exchange."
>
> to
>
> "For several use cases it would be quite convenient if the
> authentication system would throw events at several important moments
> of the authentication process."
>
>
> and require that the notifications be sent for any authentication
> on the platform, JASPIC or otherwise, which affects the application?
>
>
> Sure! I do like to stress that JASPIC doesn't do too much of its own.
> Instead, the Servlet Profile of JASPIC *asks the Servlet container* to
> do or do not do certain things.
>
> So in case of the JASPIC Servlet Profile it's the Servlet container
> that would thrown the events, since it's the thing that starts,
> actually applies and ends authentication. For other profiles (there's
> currently only the additional SOAP Profile) JASPIC asks the relevant
> entity for that profile (e.g. the EJB container can start, apply, stop
> authentication as well).
>
> Just wondering, but how would you propose "otherwise" works?
>
> Kind regards,
> Arjan Tijms
>
>
>
>
> Thanks,
> Alex
>
>
>
> On 3/12/15 8:03 PM, arjan tijms wrote:
>
> Hi,
>
> On Thu, Mar 12, 2015 at 7:49 AM, David
> Blevins<dblevins_at_tomitribe.com
> <mailto:dblevins_at_tomitribe.com>> wrote:
>
> If you look at JAAS in comparison, there is effectively a
> single method that counts. This is from CallbackHandler,
> effectively the thing that really logs people in.
>
> Well, in Java EE and specifically in JASPIC the JAAS login
> module (if
> used at all), does not really do the actual login. In practice
> it's
> something like the following:
>
> ServerAuthModule#validateRequest(..., Subject clientSubject, ...)
>
> LoginContext loginContext = new LoginContext(...,
> credentialsCallbackHandler);
> loginContext.login();
>
> Subject subject = loginContext.getSubject();
>
> String username = extractUsername(subject);
> String[] groups = extractGroups(subject);
>
> CallerPrincipalCallback callerPrincipalCallback = new
> CallerPrincipalCallback(clientSubject, username);
> GroupPrincipalCallback groupPrincipalCallback = new
> GroupPrincipalCallback(clientSubject, groups);
>
> handler.handle(new Callback[]{callerPrincipalCallback,
> groupPrincipalCallback});
>
> return SUCCESS;
> }
>
> Here the JAAS LoginContext calls through to a JAAS
> LoginModule, which
> then gets the credentials from the passed-in
> credentialsCallbackHandler, and after commit() is called makes a
> Subject available, which contains the username and roles of the
> logged-in user.
>
> However, despite the name login() on the LoginContext, nobody is
> logged-in for Java EE at this moment. The login only exists in the
> local LoginContext and by extension the LoginModule it
> contains, but
> nothing in the outside world is aware of this yet.
>
> The "auth mechanism" (the Servlet proprietary implementation
> of FORM
> etc, or a JASPIC custom one) then extracts the username and groups
> from the Subject. This is always a non-standardized process.
> Therefor
> you always have JAAS LoginModules that are specific for JBoss,
> GlassFish or a specific custom auth module (see also
> http://arjan-tijms.omnifaces.org/2014/02/jaas-in-java-ee-is-not-universal.html)
>
> Once these two data items are obtained, they are put into two
> structures that -are- standard, the CallerPrincipalCallback
> and the
> GroupPrincipalCallback, which are then passed to the container
> provided CallbackHandler, after which the auth module's method
> returns
> control to the container.
>
> It's only after this point that the (Servlet) container reads
> the data
> from the CallerPrincipalCallback and GroupPrincipalCallback
> and does
> whatever it internally needs to do to log the user in (which
> typically
> consists of setting some private fields in the HttpServletRequest
> implementation and/or installing a thread local security
> context of
> some kind).
>
> Up until this very last point there's still theoretically
> something
> that can go wrong, so it's only after this point that an
> authentication event indicating a successful login can be
> published.
>
>
> The calling side may as well just use reflection to find
> an "authenticate" method in the callee that will accept
> the data it is capable of passing in.
>
> The idea Jean-Louis crafted up, which I thought was quite
> genius, use CDI Events. A callback handler is basically
> an event handler.
>
> True, but correct me if I'm wrong but it looks like we're talking
> about *two* kinds of events here:
>
> 1. Events indicating a well known authentication step has happened
> (Logged-in, Login-Failed, Logged-out, ...)
> 2. Events to solve the eternal problem of how to pass
> credentials into
> a login module, when the form of those credentials are not
> fixed (can
> be username/password, token, ....)
>
> Is that correct?
>
>
> public void authenticate(@Observes
> UserPasswordAuthenticationEvent event)
>
> Okay, so this is clearly an example of item 2. above ;)
>
> It's a way by which the "auth mechanism" (which handles the user
> interaction and therefor knows the user has provided a
> username/password) can delegate the credential check and
> retrieval of
> a username (which may be different from the provided username) and
> optionally one or more groups/roles.
>
> Btw, we still don't really have established terms for these two
> things, which is why I hoped to discuss
> https://java.net/jira/browse/JAVAEE_SECURITY_SPEC-1 first on this
> list, but nobody has replied to that unfortunately. It would make
> exactly this discussion much easier.
>
> Additionally I hope that with clear terminology here also
> comes more
> awareness of the fact that there really are two main entities that
> play a role in authentication, and that both of these can be
> switched
> and/or provided by the application. When looking at the JIRA, blog
> postings etc, I get the feeling that almost everyone thinks mainly
> about the "credential check and retrieval of username/roles"
> entity
> and forgets that there's also the "mechanism" part.
>
> I do like the general idea using events though. I'm missing a
> bit how
> the observer of such event communicates the user/caller name and
> group/roles back to the container. Also, the
> BaseAuthenticationEvent
> in the example has a getPrincipal(), but what kind of
> Principal would
> that exactly contain?
>
> Here we do perhaps have another terminology issue; in general a
> Principal is almost another word for an "attribute". It can be
> anything, like a username, phonenumber, SSN, etc. The overarching
> entity (typically representing the user) is the Subject type,
> which
> contains a "bag of Principals". Often times it's mistakingly
> thought
> that a Principal represents the User, and that a Principal has
> many
> attributes like name, street address etc, but this is not entirely
> correct.
>
> An alternative CDI based approach would be to define a similar
> kind of
> hierarchy as mentioned for these kinds of authentication
> events, but
> as interfaces to be implemented by login modules. This is
> essentially
> what I used in the example I posted here earlier and which is
> further
> described at
> http://arjan-tijms.omnifaces.org/2014/11/header-based-stateless-token.html
>
> In that case the auth module uses the CDI bean manager to
> request a
> bean that implements the "TokenAuthenticator" interface, via the
> following utility method:
>
> TokenAuthenticator tokenAuthenticator =
> getReferenceOrNull(TokenAuthenticator.class);
>
> (injection would be an alternative)
>
> An implementation of the TokenAuthenticator is then defined as
> follows
> (simplified)
>
> @RequestScoped
> public class APITokenAuthModule implements TokenAuthenticator {
>
> @Override
> public boolean authenticate(String token) {
> // ...
> }
>
> @Override
> public String getUserName() {
> // ...
> }
>
> @Override
> public List<String> getApplicationRoles() {
> // ...
> }
>
> }
>
> Ultimately my gut feeling says that publishing events vs
> obtaining a
> bean, both for a specific type of credentials that are
> provided are
> not -that- different, but largely a matter of style.
>
> To sum up:
>
> 1. Actual login is done by Servlet container, not by auth
> module or login module
> 2. Two types of opposite events; 1. login is requested for given
> credentials, 2. Something auth related has happened
> 3. Two main entities play role in authentication; the interaction
> mechanism and the credential check + user/role retrieval. No clear
> terms for these yet.
> 4. Event to essentially invoke a login module, or obtain an
> implementation of login module can both be done via CDI
>
> Hope this feedback helps ;)
>
> Kind regards,
> Arjan Tijms
>
>