users@javaee-security-spec.java.net

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

From: Will Hopkins <will.hopkins_at_oracle.com>
Date: Fri, 24 Feb 2017 18:50:49 -0500

On 02/23/2017 07:07 AM, arjan tijms wrote:
> Hi,
>
> See replies inline ;)
>
> On Fri, Feb 17, 2017 at 7:05 PM, Will Hopkins <will.hopkins_at_oracle.com
> <mailto: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.

I agree it's not a practical problem, just pointing out that the spec
(as currently written, anyway), doesn't require it.
>
> 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.

Well, yes, but it's all handled by registering an AuthConfigProvider
with the AuthConfigFactory, which is controlling for any given context.
The container can register an AuthConfigProvider for a context, or for
global scope, but it can't legally prevent an application from
overriding that choice -- at least, that's how I understand the spec.

What I'm suggesting is that we explicitly allow containers to override
what may be packaged in an app. That allows apps to provide what they
want, and to have it take effect in environments where that's
appropriate, but also allows containers to protect themselves, or
provide integration with their environment, while still allowing
deployment of apps that may happen to package HAMs.

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

The real issue is configuration. Even if the servlet-defined mechanisms
can be implemented using JASPIC, that still doesn't help the container
figure out what to do if, e.g., web.xml specifies FORM. Doing so would
imply that the container should automatically register an
AuthConfigProvider that supplies the container-native implementation of
FORM -- but what if the application (or container) registers a different
AuthConfigProvider for the context, based on some other bit of config?
What does the container do? Either it insists on it's own FORM
implementation -- breaking the JASPIC contract for the other registered
provider -- or it honors the other registration, potentially breaking
the web.xml FORM contract.

As you point out, most containers have made some choice about how to
handle that situation (I haven't yet checked WebLogic). Fortunately,
it's a JASPIC issue, and essentially orthogonal to this specification,
so we don't have to solve it here. I'm simply suggesting that this spec
should be more precise about specifying what the container should do
with these kind of corner cases.

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

Makes sense to me.

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

Yup. We just want to make sure we make the model clear and fully specify
the containers obligations.

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

Not sure what's involved in getting servlet updated -- is there work on
servlet going on for EE 8? -- but we have an opportunity to be more
precise in this spec. ;)

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

I'm reluctant to create an explicit dependency on JACC. While it's a
required part of EE, it's not often used, and in some containers it can
be disabled. In particular, a JACC dependency would be very difficult
for WebLogic to implement; our containers today delegate to existing
APIs that perform role mapping in a JACC-agnostic way (i.e., using JACC
when enabled, and proprietary APIs otherwise).
>
> 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?

See above comments. I'd rather allow containers to decide how to
implement the required behavior, leveraging their own existing internal
abstractions if desired. It's not necessary for us to define the
implementation, only the contract -- as long as we're sure that
reasonable implementations are possible.

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

At the risk of beating a dead horse, I'm not suggesting we define a new
API or mechanism; rather, that we allow containers to continue using
whatever mechanisms they already have to provide that functionality
today. The meaning and behavior of role mapping is already well defined,
and implemented in containers.

The thought behind my original question was really more about how
SecurityContext is connected to application context (e.g.,
HttpServletRequest or HttpServletContext or EJBContext), since the
delegation model implies one can find the current request context in
order to delegate to it. Alternatively, if a container chooses to
delegate to SecurityContext, then SecurityContext may needs some way to
understand the request context in order to directly determine the
current user and evaluate roles.

There are ways that containers can achieve this, so probably all we have
to specify is the required behavior. But we should satisfy ourselves
that there are reasonable implementations.

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

Sounds good. :)

>
> Kind regards,
> Arjan Tijms
>
>
>

-- 
Will Hopkins | WebLogic Security Architect | +1.781.442.0310
Oracle Application Development
35 Network Drive, Burlington, MA 01803