users@javaee-security-spec.java.net

[javaee-security-spec users] [jsr375-experts] Re: CDI Authentication Events

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Fri, 13 Mar 2015 12:41:08 +0100

Hi,

On Fri, Mar 13, 2015 at 12:29 PM, Werner Keil <werner.keil_at_gmail.com> wrote:

> Looks like Agorava isn't the only Open Source effort endorsed or supported
> by Red Hat;-)
>
> Strangely Undertow so far reinvented the "wheel" by using its own security
> subsystem and IDM, while PicketLink already got one:
> https://github.com/picketlink/picketlink/tree/master/modules/idm/api/src/main/java/org/picketlink/idm
>

And PicketLink itself is being replaced by the new security project
Elytron. See
http://lists.jboss.org/pipermail/wildfly-dev/2014-June/002244.html

I asked the guys back then if any of their work could be used for feedback
into the Java EE Security API:
http://lists.jboss.org/pipermail/wildfly-dev/2014-June/002278.html

Do note that while Undertow defined its own security subsystem with its own
(partially JASPIC like) interfaces, for a lot of the actual implementation
of things it does use PicketLink.

Kind regards,
Arjan Tijms





> Of course, Agorava also started using Scribe for Oauth, before gradually
> replacing it with existing APIs like PicketLink.
>
> Werner
>
>
>
> On Fri, Mar 13, 2015 at 12:15 PM, arjan tijms <arjan.tijms_at_gmail.com>
> wrote:
>
>> Hi,
>>
>> On Fri, Mar 13, 2015 at 11:36 AM, Werner Keil <werner.keil_at_gmail.com>
>> wrote:
>>
>>> SecurityProvider, IdentityProvider or AuthenticationProvider are common
>>> terms at least inside WebLogic Server and Portal.
>>> I happened to back-port relevant providers for SAML from WLP 9/10 to 8
>>> once in a client project, so at least I am quite familiar with those terms.
>>> And of course everyone inside Oracle or partners will be as well;-)
>>>
>>
>> True, which is likely why both
>> https://java.net/jira/browse/JAVAEE_SECURITY_SPEC-9 and
>> https://java.net/jira/browse/JAVAEE_SPEC-25 use this specific term.
>>
>> Other frequently used terms are "realm", "repository", "store", "login
>> module" and "identity manager".
>>
>> JBoss/Undertow for instance uses the latter, for the "credential check
>> and user retrieval".
>>
>> See
>> https://github.com/undertow-io/undertow/blob/master/core/src/main/java/io/undertow/security/idm/IdentityManager.java
>>
>> - - -
>>
>> The part that handles the user interaction is called "auth-method" in the
>> Servlet spec, and "authentication mechanism" by Undertow. See e.g.
>> https://github.com/undertow-io/undertow/blob/master/core/src/main/java/io/undertow/security/api/AuthenticationMechanism.java
>>
>> A concrete implementation of such mechanism gives some insight into how
>> the two concepts relate:
>>
>>
>> https://github.com/undertow-io/undertow/blob/master/core/src/main/java/io/undertow/security/impl/FormAuthenticationMechanism.java#L108
>>
>> You can see there how the mechanism obtains the data from the http
>> request in a specific way, then delegates the "credential check and user
>> retrieval" to an identity manager (security provider in WebLogic terms).
>>
>> Interesting here is that Undertow uses a Credential marker interfaces,
>> with concrete implementations such as PasswordCredential, DigestCredential,
>> GSSContextCredential, etc.
>>
>> I haven't looked too much into it yet, but I think there are no native
>> implementations of IdentityManager in Undertow yet. Just one that delegates
>> to (JBoss specific) JAAS login modules, and one that delegates to (Tomcat?)
>> Realms.
>>
>> Kind regards,
>> Arjan Tijms
>>
>>
>>
>>
>>
>>
>>>
>>> Cheers,
>>> Werner
>>>
>>>
>>>
>>> On Fri, Mar 13, 2015 at 11:14 AM, arjan tijms <arjan.tijms_at_gmail.com>
>>> wrote:
>>>
>>>>
>>>> Hi,
>>>>
>>>> On Friday, March 13, 2015, Jean-Louis Monteiro <
>>>> jlmonteiro_at_tomitribe.com> wrote:
>>>> >but it's really painful when you need to deal with MFA, tokens, etc
>>>> which is very common nowadays.
>>>>
>>>> True, and it's for this reason that many of the existing security types
>>>> and interfaces are so generic; they have to be able to handle anything.
>>>>
>>>> I think btw that the particular discussion we now find ourselves in is
>>>> most closely related with the following existing issue;
>>>> https://java.net/jira/browse/JAVAEE_SPEC-25
>>>>
>>>> Here Reza asks to essentially modernise/CDI-ify JAAS login modules
>>>> (calling them "security providers, yet another term)
>>>>
>>>> David seems to be asking the same thing, but using an event per
>>>> credential type, where Reza proposed an annotation and a different method
>>>> signature per credential type. My own suggestion in the comments used a
>>>> bean type per credential type.
>>>>
>>>> David, can you confirm that this is indeed what you wanted to discuss
>>>> here?
>>>>
>>>> Kind regards,
>>>> Arjan Tijms
>>>>
>>>>
>>>>
>>>>
>>>>> --
>>>>> Jean-Louis Monteiro
>>>>> http://twitter.com/jlouismonteiro
>>>>> http://www.tomitribe.com
>>>>>
>>>>> On Fri, Mar 13, 2015 at 9:24 AM, arjan tijms <arjan.tijms_at_gmail.com>
>>>>> wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> On Fri, Mar 13, 2015 at 9:12 AM, Rudy De Busscher <
>>>>>> rdebusscher_at_gmail.com> wrote:
>>>>>> > Can we use generics here in some way so that the casting isn't in
>>>>>> the code
>>>>>> > the developer write?
>>>>>>
>>>>>> Probably not. The issue is that there are many different kinds of
>>>>>> credentials that the user can provide. username/password is one
>>>>>> example and here it's most often String/String or String/char[], but
>>>>>> there are many other possibilities. Both the number of data items as
>>>>>> well as the type can differ.
>>>>>>
>>>>>> This is a bit why HttpServletRequest#login
>>>>>> (
>>>>>> http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequest.html#login(java.lang.String
>>>>>> ,
>>>>>> java.lang.String)) is not that useful, since it assumes one particular
>>>>>> set of credentials (username/password again). It's therefor not
>>>>>> compatible when the user provides a token as credential.
>>>>>>
>>>>>> Kind regards,
>>>>>> Arjan Tijms
>>>>>>
>>>>>>
>>>>>> >
>>>>>> > Rudy
>>>>>> >
>>>>>> >
>>>>>> > On 12 March 2015 at 07:49, David Blevins <dblevins_at_tomitribe.com>
>>>>>> wrote:
>>>>>> >>
>>>>>> >> [ markdown version
>>>>>> https://gist.github.com/dblevins/211a45b893999748c7c4 ]
>>>>>> >>
>>>>>> >> Looking to crack the ice. Hopefully inspire some brainstorming.
>>>>>> >>
>>>>>> >> The following is a set of events Jean-Louis Monteiro created in
>>>>>> our impl
>>>>>> >> for using CDI to extend login events to the application.
>>>>>> >>
>>>>>> >> The impetus of this one came from our attempt to kill a
>>>>>> particularly
>>>>>> >> inflexible interface in Tomcat called `Realm`. It started out
>>>>>> hard-coded to
>>>>>> >> a specific login approach (basic auth) and has grown awkwardly
>>>>>> since.
>>>>>> >>
>>>>>> >>
>>>>>> >> java.security.Principal authenticate(java.lang.String username,
>>>>>> >> java.lang.String password);
>>>>>> >> java.security.Principal authenticate(String username, String
>>>>>> digest,
>>>>>> >> String nonce, String nc, String
>>>>>> cnonce,
>>>>>> >> String qop, String realm,
>>>>>> >> String md5a2);
>>>>>> >> java.security.Principal authenticate(org.ietf.jgss.GSSContext
>>>>>> >> gssContext, boolean storeCreds);
>>>>>> >> java.security.Principal
>>>>>> >> authenticate(java.security.cert.X509Certificate[]
>>>>>> x509Certificates);
>>>>>> >>
>>>>>> >> As you can see, this has obvious downsides.
>>>>>> >>
>>>>>> >> Cons:
>>>>>> >>
>>>>>> >> - not extendable. each new auth scheme requires the interface to
>>>>>> be
>>>>>> >> updated.
>>>>>> >> - each existing implementation has to implement the new auth
>>>>>> scheme. (at
>>>>>> >> least pre-java8)
>>>>>> >> - caller and callee are still ultimately tied together
>>>>>> >>
>>>>>> >> Clearly this is a false interface and separates very little. The
>>>>>> calling
>>>>>> >> side and the implementing side are doing a specific dance -- they
>>>>>> are tied
>>>>>> >> together. This is perhaps unavoidable. More on that.
>>>>>> >>
>>>>>> >> Possible Pros:
>>>>>> >>
>>>>>> >> - strongly typed
>>>>>> >> - self documenting
>>>>>> >> - extremely simple to implement a scheme supported by the
>>>>>> interface.
>>>>>> >>
>>>>>> >> 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.
>>>>>> >>
>>>>>> >> void handle(Callback[] callbacks)
>>>>>> >> throws java.io.IOException, UnsupportedCallbackException;
>>>>>> >>
>>>>>> >> The observation on this one is it is effectively the same in
>>>>>> function to
>>>>>> >> the hard-coded Tomcat Realm API if it looked like this:
>>>>>> >>
>>>>>> >> java.security.Principal[] authenticate(Object[] arguments);
>>>>>> >>
>>>>>> >> Very little is actually being specified. If it is, then perhaps
>>>>>> one could
>>>>>> >> argue that `public static void main(String[])` is also a security
>>>>>> API :)
>>>>>> >>
>>>>>> >> The Principal objects come in a slightly round-a-bout way, but you
>>>>>> get the
>>>>>> >> idea. It is the polar opposite of the Tomcat Realm API.
>>>>>> >>
>>>>>> >> Pros:
>>>>>> >>
>>>>>> >> - extendable
>>>>>> >>
>>>>>> >> Cons:
>>>>>> >>
>>>>>> >> - too loosely typed
>>>>>> >> - not self-descriptive
>>>>>> >> - very hard to implement an auth scheme
>>>>>> >> - caller and callee are still ultimately tied together
>>>>>> >>
>>>>>> >> I'll note both approaches have the same downside; the caller and
>>>>>> callee
>>>>>> >> are still ultimately tied together.
>>>>>> >>
>>>>>> >> When the data you pass back and forth is essentially `Object[]`
>>>>>> there is
>>>>>> >> an incredible amount of casting involved. You aren't relying on
>>>>>> the
>>>>>> >> interface, but your foreknowledge of the code calling you. You
>>>>>> haven't
>>>>>> >> separated anything ultimately and only accomplish obfuscating that
>>>>>> simple
>>>>>> >> fact. It makes a good show of looking like it accomplishes
>>>>>> something by
>>>>>> >> having the arguments be a specific interface, but as mentioned that
>>>>>> >> interface may as well be Object.
>>>>>> >>
>>>>>> >> 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. Sounds
>>>>>> like we
>>>>>> >> have several genius' on the list and this is at the forefront of
>>>>>> everyone's
>>>>>> >> minds. That's more than exciting. :)
>>>>>> >>
>>>>>> >> Here's an idea of what those look like. Putting them here not
>>>>>> because I
>>>>>> >> think their already perfect, but so we have something to start
>>>>>> tearing up.
>>>>>> >> Let's get creative. Some comments from me inline.
>>>>>> >>
>>>>>> >> public abstract class BaseAuthenticationEvent {
>>>>>> >> private Principal principal;
>>>>>> >>
>>>>>> >> public Principal getPrincipal() {
>>>>>> >> return principal;
>>>>>> >> }
>>>>>> >>
>>>>>> >> public void setPrincipal(final Principal principal) {
>>>>>> >> this.principal = principal;
>>>>>> >> }
>>>>>> >> }
>>>>>> >>
>>>>>> >> Other options might include making principle a collection or this
>>>>>> to a
>>>>>> >> "Context" class of some sort and avoiding inheritance.
>>>>>> >>
>>>>>> >> public class DigestAuthenticationEvent extends
>>>>>> BaseAuthenticationEvent
>>>>>> >> {
>>>>>> >>
>>>>>> >> private final String username;
>>>>>> >> private final String digest;
>>>>>> >> private final String nonce;
>>>>>> >> private final String nc;
>>>>>> >> private final String cnonce;
>>>>>> >> private final String qop;
>>>>>> >> private final String realm;
>>>>>> >> private final String md5a2;
>>>>>> >>
>>>>>> >> // getters, setters and constructor stripped
>>>>>> >> }
>>>>>> >>
>>>>>> >> Clearly for Digest auth. I'd expect any required scheme to have a
>>>>>> >> standard event type. New ones can be provided, but there should
>>>>>> be concrete
>>>>>> >> classes for the minimum. The event object need only simple and
>>>>>> dumb
>>>>>> >> approach to passing arguments.
>>>>>> >>
>>>>>> >> public class GssAuthenticationEvent extends
>>>>>> BaseAuthenticationEvent {
>>>>>> >>
>>>>>> >> private final org.ietf.jgss.GSSContext gssContext;
>>>>>> >> private final boolean storeCreds;
>>>>>> >>
>>>>>> >> // getters, setters and constructor stripped
>>>>>> >> }
>>>>>> >>
>>>>>> >> public class SslAuthenticationEvent extends
>>>>>> BaseAuthenticationEvent {
>>>>>> >>
>>>>>> >> private final java.security.cert.X509Certificate[] certs;
>>>>>> >>
>>>>>> >> // getters, setters and constructor stripped
>>>>>> >> }
>>>>>> >>
>>>>>> >> public class UserPasswordAuthenticationEvent extends
>>>>>> >> BaseAuthenticationEvent {
>>>>>> >>
>>>>>> >> private final String username;
>>>>>> >> private final String credential;
>>>>>> >>
>>>>>> >> // getters, setters and constructor stripped
>>>>>> >> }
>>>>>> >>
>>>>>> >> I'm not a fan of the inheritance, but I love the basic idea.
>>>>>> >>
>>>>>> >> The obvious use is that authentication could be implemented with a
>>>>>> simple
>>>>>> >> observer such as:
>>>>>> >>
>>>>>> >> public void authenticate(@Observes
>>>>>> UserPasswordAuthenticationEvent
>>>>>> >> event)
>>>>>> >>
>>>>>> >> The inheritance clearly has CDI benefit in that one could observe
>>>>>> >> `BaseAuthenticationEvent` such as:
>>>>>> >>
>>>>>> >> public void authenticate(@Observes BaseAuthenticationEvent
>>>>>> event)
>>>>>> >>
>>>>>> >>
>>>>>> >> This of course raises tons of question, and that of course is the
>>>>>> idea :)
>>>>>> >>
>>>>>> >> - Who is allowed to implement this?
>>>>>> >> - How should one reject login?
>>>>>> >> - Do we let both the app and the container @Observes the event?
>>>>>> >> - Do we require @Observes to use a qualifier that explicitly
>>>>>> states the
>>>>>> >> scheme? @Scheme("BASIC")
>>>>>> >>
>>>>>> >> There is another event for adding roles (more Principle
>>>>>> instances), but
>>>>>> >> let's see what kind of ideas this fosters.
>>>>>> >>
>>>>>> >> I'm sort of curious if there isn't a producing side to this as
>>>>>> well:
>>>>>> >>
>>>>>> >> @Produces
>>>>>> >> public UserPasswordAuthenticationEvent
>>>>>> filter(@Authorization("Basic")
>>>>>> >> String headerValue)
>>>>>> >>
>>>>>> >> Maybe a bit too low level, but interesting idea to treat the HTTP
>>>>>> >> `Authorization` header itself as some kind of event or parameter
>>>>>> to a
>>>>>> >> producer.
>>>>>> >>
>>>>>> >> Theoretically the container could sign up to handle 100% of the
>>>>>> parts in
>>>>>> >> the common case where the app does not want to handle anything,
>>>>>> but we might
>>>>>> >> theoretically have the container NOT add built in producers and
>>>>>> observers
>>>>>> >> when it is determined the app has them.
>>>>>> >>
>>>>>> >> Again, all brainstorming.
>>>>>> >>
>>>>>> >>
>>>>>> >> -David
>>>>>> >>
>>>>>> >
>>>>>>
>>>>>
>>>>>
>>>
>>
>