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:27:37 +0100

Hi,

On Fri, Mar 13, 2015 at 11:49 AM, Jean-Louis Monteiro <
jlmonteiro_at_tomitribe.com> wrote:

> Let's add service provider and relying party which are also common ;-)
>

And let's not forget "authenticator", which is used by Resin. See
http://caucho.com/resin-4.0/admin/security-authenticators.xtp


So for the "credential check and user/role retrieval we have:

* security provider (WebLogic)
* realm (Tomcat, some hints in Servlet spec)
* (auth) repository
* (auth) store
* login module (JAAS)
* identity manager (Undertow)
* service provider
* relying party
* authenticator (Resin, OmniSecurity)
* user service (?, used by 375 JSR)

These are rather different names, but all essentially all refer to the
exact same functionality right?

Kind regards,
Arjan Tijms




>
> --
> Jean-Louis Monteiro
> http://twitter.com/jlouismonteiro
> http://www.tomitribe.com
>
> 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;-)
>>
>> 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
>>>>> >>
>>>>> >
>>>>>
>>>>
>>>>
>>
>