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

[jsr375-experts] Re: Next: Authentication Mechanism

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Thu, 15 Oct 2015 13:13:04 +0200

Hi

On Thu, Oct 15, 2015 at 3:45 AM, Alex Kosowski <alex.kosowski_at_oracle.com> wrote:
> A. Standardize a simple authenticator, by simplifying JASPIC SAM usage:

+1 on this, of course ;)


> Install a SAM programmatically using a single method call (e.g.
> Jaspic.registerServerAuthModule)

This is by itself pretty straightforward. In the simplest version this
method takes an instance of the SAM and registers that single instance
as the one and only SAM for the Servlet container.

An example of that can be seen here:
https://github.com/javaee-samples/javaee7-samples/blob/master/jaspic/common/src/main/java/org/javaee7/jaspic/common/JaspicUtils.java#L23

Many projects out there in the wild that I've seen use highly similar code.

There are two things to keep in mind for this variant:

1. The SAM here is a plain class. It can -use- the CDI API via
CDI.current(), but is itself not a CDI bean (it's not injectable or
scoped)

2. Following 1, but perhaps good to mention explicitly; there's only a
single instance of the SAM and it has to be thread-safe. Just like a
Servlet. The "handler" that it gets from the container is thead-safe
though.

An alternative (or additional) approach is that the input paramater is
a Class<T>, and we'll promise to obtain a reference to that class
using CDI.



> Install a SAM using an Annotation (e.g. @Authenticator(<SAM class>,
> <options>) )

Instead of @Authenticator it may be better to use the term
@AuthenticationMechanism here, as "authenticator" is yet another term
and even one that's unfortunately ambiguous in its existing usage
(some servers use this term for what we now call an "identity store').

Just like with the identity store, I think we have two variants here
for the annotation;

1. Making an application provided SAM directly available
2. Registering a SAM that was provided by a library (or, who knows,
the spec later on)

Example of the first variant:

@ApplicationScoped
@AuthenticationMechanism
public class BasicAuthModule extends HttpServerAuthModule {

    @Inject
    private IdentityStore identityStore;

    @Override
    public AuthStatus validateHttpRequest(HttpServletRequest request,
HttpServletResponse response, HttpMsgContext httpMsgContext) throws
AuthException {

        // get credendials, use identityStore, get authresult back

        if (httpMsgContext.isProtected()) {
            response.setHeader("WWW-Authenticate", "Basic realm=\"test
realm:\"");
            return httpMsgContext.responseUnAuthorized();
        }

        return httpMsgContext.doNothing();
    }
}

The @AuthenticationMechanism may even be omitted if we say that just
like with the IdentityStore there should only be one injectable
"HttpServerAuthModule" on the classpath.



> Simplify SAM development for servlet based authentication (e.g.
> HttpServerAuthModule, HttpMessageContext)

To sum up for those who haven't read all the issues; this is basically
what HttpServlet is to GenericServlet.

In my prototype HttpServerAuthModule is a base class that actual
authentication modules have to extend. This wasn't done because of any
architectural preference for base classes, but just because it was
easy to prototype.

One note about HttpMessageContext; this is a convenience object that
can be used within a SAM, but only within a SAM. As such it's just
like FacesContext in JSF or a ServletContext or even
HttpServletRequest in Servlet. All those objects should not be used
arbitrarily, but of course only within the context where they are
valid.

Kind regards,
Arjan Tijms