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

[jsr375-experts] Re: CDI Authentication Events

From: Werner Keil <werner.keil_at_gmail.com>
Date: Fri, 13 Mar 2015 12:44:20 +0100

Well, they like to re-assemble, refactor and rename a lot of things as we
also saw with Seam ;-D

Werner




On Fri, Mar 13, 2015 at 12:41 PM, arjan tijms <arjan.tijms_at_gmail.com> wrote:

> 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
>>>>>>> >>
>>>>>>> >
>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>
>>
>