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

[jsr375-experts] Re: CDI Authentication Events

From: Alex Kosowski <alex.kosowski_at_oracle.com>
Date: Mon, 30 Mar 2015 18:12:11 -0400

Hi Arjan,
> Okay, does that specifically mean that we ask the Servlet spec to
> throw these events when the user has configured the Servlet container
> to use a native mechanism?
You make it quite clear that throwing events for "any" authentication
affecting the application may be too broad ;). That may be too big a
problem to solve wrt the other work we are trying to accomplish in the JSR.

Perhaps we should just start (in the spec 1.0 release) with servlet
authentication using JASPIC. The events together with the authenticator
simplifications may encourage developers toward the standard
authentication.

Regards,
Alex


On 3/30/15 3:26 AM, arjan tijms wrote:
> Hi,
>
> On Mon, Mar 30, 2015 at 3:41 AM, Alex Kosowski
> <alex.kosowski_at_oracle.com <mailto:alex.kosowski_at_oracle.com>> wrote:
>
> 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.
>
>
> Okay, does that specifically mean that we ask the Servlet spec to
> throw these events when the user has configured the Servlet container
> to use a native mechanism?
>
> I didn't bring it up earlier since the discussions were already
> complex enough as they were, but one other thing we might need to take
> into account as well is logins/security inflow from other places than
> the web/servlet.
>
> Naturally everyone (including myself) is very focussed on web, but
> it's actually still possible to login via remote EJB and the JCA
> container.
>
> Now I know EJB and remote EJB specifically is slowly being phased out,
> but this will not happen in Java EE 8 and maybe not even in Java EE 9.
> I also know that EJB remote logins have been problematic for like
> forever.
>
> JASPIC doesn't have a profile for remote EJB logins, nor for JCA. But,
> JCA does make use of JASPIC callbacks for authentication.
>
> Kind regards,
> Arjan Tijms
>
>
> 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
>>
>>
>