users@javaee-security-spec.java.net

[javaee-security-spec users] [jsr375-experts] Re: Comments on Current Spec Content (take 3)

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Thu, 23 Feb 2017 13:07:37 +0100

Hi,

See replies inline ;)

On Fri, Feb 17, 2017 at 7:05 PM, Will Hopkins <will.hopkins_at_oracle.com>
wrote:

> The wording in section 13.6.5 of Servlet 3.1 says "should" and
> "recommend", not "must", WRT other authentication mechanisms and JASPIC.
>

True, although there's an open issue on the Servlet tracker to change that
to the single word "must". See https://java.net/jira/browse/SERVLET_SPEC-114

This seemed quite close to getting accepted, but is no somewhat left open
again.

Practically, all current Servlet container support JASPIC. So if "should"
and "recommend" was changed into "must", nothing really changes for them.



> Leaving that aside, though, it doesn't specify the integration; i.e.,
> there is no defined relationship between JASPIC and the authentication
> mechanisms defined by Servlet 3.1 (BASIC, FORM, etc.). Integration with the
> container is exclusively defined by the Servlet Container Profile in
> JASPIC, which makes no reference to the standard authentication mechanisms
> defined by Servlet 3.1, or to the web.xml declarations that trigger them.
>

Indeed, there's an existing issue here too that seeks to clarify this. See
https://java.net/jira/browse/JAVAEE_SECURITY_SPEC-19



> Instead, JASPIC defines its own programmatic configuration mechanism,
> distinct from, and orthogonal to, any Servlet-based authentication
> configuration.
>

Correct, and next to that it also allows for SAMs to be configured outside
the application in the "global scope" and in a container specific way.



> In my mind, the Servlet-defined mechanisms and the JASPIC mechanism exist
> separately and side-by-side, and there are some gray areas as to which
> mechanism would take precedence if both were configured.
>

I think, but have to double check how clearly this is defined, that JASPIC
has to take precedence. In practice, all containers have something like:
"If a SAM is configured for this context use it, otherwise look at the
Servlet native one"

As Greg from Jetty mentioned ~a year ago; these two should not have to
exist next to each other. The Servlet-defined ones can be implemented using
the JASPIC SPI.




> Having read your subsequent comments, I now believe that you intend
> HttpAuthenticationMechanism to be invoked as part of JASPIC processing
> (because it's wrapped in a ServerAuthModule), and not in addition to JASPIC
> processing. That makes a lot more sense.
>

Indeed, that's the idea. If you think we should clarify that, then please
go ahead.

Summarised; the container calls a SAM, the SAM activates CDI if needed, and
the SAM then calls the HAM using CDI.



> Given that, I wonder if we should define what containers must do to enable
> that -- i.e., provide a default ServerAuthModule (and associated AuthConfig
> objects, etc.), configure the SAM with the configured
> HttpAuthenticationMechanism, and register the whole thing with the
> AuthConfigFactory so that it is invoked by the container at runtime?
> Something like JASPIC's LoginModule Bridge Profile, but for
> HttpAuthenticationMechanisms.
>

Exactly. The LoginModule Bridge Profile is a profile that bridges from an
authentication mechanism to what's effectively used as an identity store
(the JAAS LoginModule), while here it's about one type of authentication
mechanism delegating to another type of authentication mechanism.

The specification of this can me much lighter and smaller than
the LoginModule Bridge Profile, as that profile has to work with any
container, any JAAS implementation and any SAM provided by the user.

In this case it's only about what the vendor should do internally. The
BridgeSam provided by Soteria does not have the standardised itself.



> On closer reading, though, the key phrase is, "as if the caller had
> attempted to access a constrained resource", which is consistent with
> Servlet 3.1, section 13.3, "The authenticate methods allow an application
> to instigate authentication of the request caller by the container from
> within an unconstrained request context."
>
> The important part there, which I think we should clarify in the Security
> Spec, is that authenticate() is only defined if the user is not already
> authenticated; i.e., in the context of an unconstrained request context. It
> should do nothing, or return an error, if called when the user is already
> authenticated.
>

This is a good point indeed, and perhaps the Servlet EG should consider
clarifying that as well.

Servlet's authenticate() has some other issues as well, evidenced by the
GlassFish/Payara and JBoss/WildFly behave differently. They all return true
when authentication succeeded, but there's some interpretation differences
about when to return false vs throwing the mandated exception. (See the
comment in the Soteria impl code for SecurityContect#authenticate).




> OK. In the case of the getCallerPrincipal() and isCallerInRole() methods,
> though, that doesn't work as well, because we might be in servlet context,
> or EJB context, or some other context. Also, the implication in the spec is
> that we're superceding/standardizing the corresponding calls in other
> containers, which would imply that the legacy container calls should
> piggy-back on the new mechanism.
>

Absolutely, so the current implementation is just a quick placeholder.

As mentioned further down in the previous email, the default solution would
be to use JACC here. It already specifies exactly this.

The JACC API is difficult to use from a user perspective, but for us that
would not matter that much. The JSR 375 implementation code would do the
JACC call, and an application server supporting JSR 375 can ship its own
JACC Provider (JACC module) internally if needed. The user would be
shielded from that.

And the JACC API would be needed for the authorization story as well. It
already does an excellent job parsing and making the constraints from
web.xml available to code. Those rules are quite complicated and even more
complicated to implement, so this is something we'd surely not want to
duplicate.



> There are ways to solve this problem -- a context stack similar to the
> Subject stack, a properly-scoped CDI context, etc. -- we just need to pick
> one.
>

A problem with that might be that it presents the question of how we sync
it with JACC, if that's used. It also duplicates what JACC already does.
Many application servers also duplicate this functionality using their own
proprietary internal code, and on top of that have a legacy implementation
of a proprietary solution as well.

So that gives 3 distinct code paths already (JACC, proprietary and
proprietary legacy). Do we really want to add a 4th one?

Many bugs I discovered in application servers throughout the years could
ultimately be attributed to these duplicated code paths and the need to
keep them in sync and to fix one bug in the other paths as well.

If we introduce a 4th one, we also have to tell all containers to use this
new source of truth. If we take advantage of JACC, then we don't have to
have any container modified, they already should go to JACC to answer this
question.

I'll look at replying to the other points in a follow-up email ;)

Kind regards,
Arjan Tijms