users@servlet-spec.java.net

[servlet-spec users] Re: request#authenticate - start new vs continue

From: arjan tijms <arjan.tijms_at_gmail.com>
Date: Wed, 20 Apr 2016 13:47:15 +0200

Hi,

On Wed, Apr 20, 2016 at 12:34 PM, Greg Wilkins <gregw_at_webtide.com> wrote:

>
>
>> Did I understand that correctly?
>>
>
> More or less, except that it may not be a header, it may be a session or
> SSL certificate etc. The point is that depending on how our loginService
> is configured, authenticating can be an expensive operation (with possibly
> remote calls etc.), so just because a request offers credentials or is for
> a session with auth information or has a client certificate, it doesn't
> mean that we go to the effort of doing the authentication. Only if an Auth
> constraint is hit OR somebody subsequently calls authenticate do we
> undertake that effort.
>

I see. Deferring in this way does have to be done by the authentication
mechanism itself then, as only that one would have knowledge what the exact
credentials look like. This may be a choice though, as authenticating even
for resources that don't have an authentication constraint can still be
useful. E.g. public resources that show extra options when authenticated.



> Yes a little bit. I think you are saying you want a mechanism where the
> application can plug in some credentials to the request and then call
> authenticate() and for it to attempt to use those credential - if they are
> wrong or insufficient, then the authentication conversation will continue
> as need be.
>

Close, but not exactly. In the example above, the authentication dialog
(conversation) has already started. It started when the caller tried to
access a protected resource. At some point though the application is
consulted, since the form page to be displayed comes from the application.
not from the authentication mechanism.



> The problem I see is the opacity of this. authenticate() currently works
> because it has no idea what credential (if any) exist in the
> request/session/connection, but it assumes that if they are there they were
> set by a previous encounter with the configured authentication mechanism,
> and thus it will know what to do.
>
> So in your example, the application some how knows (or assumes) that
> authentication is using JASPIC (I'm assuming that is what
> defines IS_AUTHENTICATION and AUTH_PARAMS ??), but I think that is fragile
> and/or limiting.
>
> I think the problem is that you are trying to mix application managed
> authentication with container managed authentication, and it is going to be
> difficult to pass any partial results without assuming a mechanism.
>

Mixing itself should not be a problem IMHO. In so far as that mixing is
pretty much the main reason why JSR 375 was started. In short, an
authentication mechanism can reside at either the container or the
application archive, and the same holds for the identity store it delegates
to. The application code is largely unaware of this. You should be able to
move a particular mechanism from the container to the application and vice
versa without changing code.

Note that this already works like that today for data sources and JMS
destinations. One can define a data source in web.xml (data-source element)
or via @DataSourceDefinition, and the application will use it via JNDI. If
you subsequently remove the definition from the application and instead
define it at the container level, the app will happily continue.

With regards to security, there always has been a mix between container
managed and application managed security.

With Servlet FORM, the very fact that FORM has to be used is declared in
web.xml, and the mechanism is configured with a login and error page that
reside within the application archive. The existing, hard coded signal that
the application uses to continue the authentication dialog (conversation)
is by posting to /jsecuriy_check using the form parameters j_username and
j_password.

So here the mechanism already provides an "API" that the application uses,
namely {j_username, j_password} -> /j_security_check. The application is
thus aware that FORM authentication is used and that a username/password
has to be provided.

What I'm using here is simply the programmatic equivalent of that. I think
it's exactly as fragile or limiting as the existing " {j_username,
j_password} -> /j_security_check" way to continue the authentication dialog
is. It just gives the application an opportunity to inspect/validate the
credentials before continuing that dialog, but otherwise (conceptually)
there should not be any differences.

But, in general there are multiple issues with the authenticate() method:

1. Letting the application be very strict about wanting (or expecting) to
continue a dialog (such as when a FORM-like mechanism delegates the login
form to the application) vs the application wanting to abandon any
potentially existing dialog (such as when a user clicks on a login button)

2. Providing parameters with the authenticate() call. (for JSR 375 I want
to propose to use the generic Credential type for the SecurityContext; a
Credential is the super class of any other type of more specific
credentials)

3. The return value of HttpServletRequest#authenticate - not mentioned in
this thread yet, but it may be good to start a separate discussion about it
;)

Btw, IS_AUTHENTICATION is just for distinguishing between an invocation of
the authentication mechanism at the start of the request (prior to a
resource invocation) and one following the authenticate() call. See also
this one: https://java.net/jira/browse/JASPIC_SPEC-5

A number of servers already provide this information, but in a non-portable
way.

Kind regards,
Arjan Tijms









>
>
> or am I missing something still?
>
> cheers
>
>
> --
> Greg Wilkins <gregw@webtide.com> CTO http://webtide.com
>