Hi Mark,
Thanks for the helpful analysis - see inline:-
On 11/14/12 2:27 AM, Mark Thomas wrote:
> On 13/11/2012 22:56, Danny Coward wrote:
>> Hi Mark,
>>
>> <snipping earlier conversation in the interests of bevity>
>>> There are multiple factors here:
>>> - is an HttpSession present (Yes/No)
>>> - is the WebSocket endpoint protected by a security constraint (Yes/No)
>>> - what authentication mechanism is in use (BASIC/DIGEST/FORM/
>>> CLIENT-CERT/CONTAINER-SPECIFIC)
>>> - logout / session expiration
>>>
>>> That gives us at least 32 (actually a few won't work but ignoring that
>>> for now) combinations plus an additional 8 for each container specific
>>> authentication mechanism.
>>>
>>> We either need to be clear about what happens in each of the above cases
>>> or provide the hooks to enable the developer to make the choice (with
>>> some sensible defaults). I prefer the latter option.
>> OK so I think having the developer make that association is reasonable.
>> (see below)
>>
>> I am still concerned about containers that use the HttpSession for
>> authenticated state running web sockets after the authenticated state
>> has been reset. As you say, this may only be in the FORM login case, but
>> I'm not sure that there aren't other containers and other schemes where
>> the HttpSession is used for more than that one case.
> There are certainly cases where if a session is present then it is used
> to simplify per request authentication.
>
>> It feels like we need to require containers to close web sockets opened
>> on the understanding of a particular authenticated state in those cases
>> where the authenticated state has changed for whatever reason.
>>
>> If this makes sense, can you think of a requirement we can put in the
>> spec to capture this succinctly ?
> It does make sense but I'm not sure we can in all cases currently.
>
> For BASIC/DIGEST/CLIENT-CERT auth the browser essentially caches the
> credentials so the user is authenticated for all practical purposes
> until they close the browser regardless of what happens with the
> session. That will also close any WebSocket connection. In these cases
> there is nothing for us to do.
Yes...although there is nothing to prevent a browser (add-on) from
clearing the credential cache (without clearing the cookies) at the whim
of the user. Then if the user logs in as someone else, they get the same
session, new user identity, and websockets still running that were
created with the old user identity. So I guess it's only a happy
coincidence that browsers generally clear both the credential cache and
close web sockets at the same time.
> For FORM the user is authenticated until the session expires. This is a
> tricky one as there is no easy way for the WebSocket implementation to do:
> if (url.isProtected() && auth == AuthMethod.FORM) {
> // Associate WebSocket connection with Session
> ...
> }
> Being able to do that would require placing some additional requirements
> on the Servlet Spec.
It looks like we could determine the auth method from the
HttpServletRequest, and check the user principal is non-null. Then I
think we would know definitively that we are working within an
HttpSession on which a FORM authentication hangs ?
> For TBD container specific authentication scheme we have no idea what is
> going on. We essentially need to know:
> a) Is the endpoint protected by a security constraint?
> b) Is the life-cycle of the authenticated user aligned with the session?
>
> If the answer is yes, then we need to link the WebSocket connection with
> the session (e.g. with a Listener) and close the connection if still
> open when the session ends.
>
> Neither a) nor b) is possible with the current Servlet API. We either
> need to place requirements on the Servlet API so we can determine this
> for ourselves and act accordingly or we make it a developer
> responsibility. Given the security implications, I'd rather this wasn't
> a 100% developer responsibility. I'm fine with giving developers a
> mechanism to disable this but it should really happen automatically by
> default.
>
> Note if we solve the general container specific authentication case then
> that automatically solves the FORM auth case.
I think we are struggling with the basic problem that the web socket
frames do not (natively) carry either user identity or session
information. Perhaps we can address the FORM login case (with or without
new API from Servlet).
>> In terms of supporting developers making their own association between
>> httpsessions and web sockets, currently we have
>>
>> Object HandshakeRequest.getSession()
>>
>> and we can recommend developers use an HttpSessionListener to track the
>> session to establish whatever relationship they want with it over its
>> lifetime.
> +1. I suggest we provide a implementation of that listener that they can
> start from.
what are you thinking the WebSocketHttpSessionListener would do ?
In my mind, the main question they'd need to ask would be 'what is the
HttpSession that was in place when this WebSocket session was started ?'
which is answered by the existing Session.getHttpSession()
>> We didn't want an explicit dependency on the Servlet API which explains
>> (perhaps not excuses) the typeless API. This seems a step better that
>> asking developers to pull the SessionID out of the Cookie or JSession ID
>> parameter on the request URI, but perhaps a step worse than allowing the
>> HttpSession to be injected explicitly ?
> What is the harm in using HttpSession here?
I think the complaint was its a rough edge for websocket-only servers.
- Danny
> Mark
--
<http://www.oracle.com> *Danny Coward *
Java EE
Oracle Corporation