I've been looking into PR #890 [1] - "Make SSO re-authentication
configurable for SSLAuthenticator". The short version is that I think
some of the current code comments aren't quite right and that there
might be scope to simply SSO. Additional documentation is almost
certainly required.
There are quite a few moving parts to this. Apologies for the length of
what follows.
I'm ignoring session expiry, authentication failure etc to keep things
simple so we can focus on the bits that I think are important to this
discussion.
When I refer to full authentication I mean that the authenticator has
taken the normal credentials the authenticator requires (provided by the
user or cached by SSO) and used them to call the appropriate
Realm.authenticate() method and received a newly created, authenticated
Principal in response. Any case where a cached Principal is re-used
(e.g. based on the presence of an SSO cookie) is not full authentication.
First the (fairly) simple case.
SSO requires that all web applications under the Host/Engine where SSO
is configured use the same Realm.
The SSO Valve processes the request before the Authenticators do.
The authenticators look for an SSO Valve when they start up and, if
found, retain a reference to it.
Any full authentication by any authenticator is registered with the SSO
Valve which caches the authenticated Principal (and a few other bits and
pieces) and an SSO cookie is sent to the client.
The SSO Valve looks for the cookie and, if it is set, looks up the
associated authenticated Principal and adds it to the request.
The authenticators check to see if the request already has a Principal
and, if it does, use it rather than performing a full authentication of
the user.
Then we get bug 23881 [2]. Unfortunately, "fail to authenticate
correctly" is not defined. Reading between the lines, the underlying
issue is that the application is depending on more than just the
Principal being added to the request. Bug 23881 mentions JAAS but I'm
not sure what role that was playing - unless it was a custom JAAS realm.
It might have been since JBoss was mentioned. The solution was to
introduce the concept of re-authentication. With re-authentication, the
authenticators always complete a full authentication even with SSO. This
means one of the Realm.authenticate() methods will be called which
strongly suggests the Realm is doing something additional that the
application depends on in addition to the setting of the Principal on
the request.
To avoid repeatedly prompting users with FORM auth (if one of the web
applications uses it) the SSO Valve caches the plain text user name and
password captured from BASIC or FORM auth and then re-uses them if it
needs to re-authenticate for a web application using BASIC or FORM.
Strictly that isn't necessary for BASIC since the client will re-send
the credentials on every request.
DIGEST and CLIENT-CERT authenticators can't perform a full
authentication with a plain text username and password so the
Authenticator completes a full authentication by obtaining the
information from the request. The client typically sends the credentials
for DIGEST on every request so the user isn't repeatedly prompted for
credentials.
There is an interesting edge case here that if digested passwords are
being used with DIGEST authentication the password stored in the Realm
will need to be different for DIGEST compared to BASIC/FORM so it would
not be possible to mix DIGEST with FORM or BASIC in an SSO configuration
with digested passwords. This needs documenting.
Depending on what the Realm is doing / application is expecting, it may
be sufficient for a DIGEST authenticator to re-authenticate to the Realm
using the cached plain-text user name and password from BASIC/FORM auth.
SPNEGO will re-authenticate with a user name and password from
BASIC/FORM. That looks odd to me since if re-authentication has been
enabled, I would expect SPNEGO to complete a full SPNEGO authentication.
I think this is a bug that needs to be fixed.
PR #890 is - essentially - a request to make re-authentication
configurable for the SSLAuthenticator when the SSO Valve is configured
to require it.
The code comments suggest that re-authentication is to do with the
relative security of the authentication mechanisms. I think this is
incorrect. I think it is whether an authenticator can complete a full
(against the Realm) authentication with the cached, plain-text user name
and password. Whether it can is going to depend on exactly what the
Realm is doing that application is depending on. I intend to update the
comments to that effect.
If re-authentication is enabled for the SSO Valve it makes the SSO Valve
essentially pointless unless there is more than one Context that can
re-authenticate from the cached username and password. That is worth
documenting for the requireReauthentication attribute of the SSL Valve.
Getting back to #890, I wondered if the solution for the OP would be to
disable re-authentication on the SSO Valve. That would have the same
effect. That got me thinking there maybe cases where re-authentication
is required for some, but not all, web applications under an SSO Valve.
There are, currently, 3 authentication possibilities for a web
application using SSO.
1. Cached user Principal from SSO session is added to request
(Default)
2. User is re-authenticated against Realm using cached plain
text user name and password from SSO session
(BASIC, FORM and SPNEGO when requireReauthentication is set)
3. User is fully re-authenticated using against the Realm using
credentials from the request (as if SSO was not present)
(DIGEST and CLIENT-CERT when requireReauthentication is set)
So, finally, to potential changes.
I had considered removing the requireReauthentication attribute from the
SSO Valve but I think it still serves a purpose and is worth keeping.
Removing it would also create migration work for users. I proposed the
following:
- add an ssoReauthenticationMode to the Authenticator interface with
three possible values (all case insensitive)
- cached - add the cached Principal to the request
- userPassword - authenticate to the Realm with the cached
username and password from BASIC/FORM
- full - perform the standard authentication for the authenticator
using information provided in the request
- if requireReauthentication is not enabled, all authenticators
use the "cached" mode (no change)
- if requireReauthentication is enabled
- BASIC and FORM reauthenticate use "userPassword" mode by default
(no change).
- SPNEGO used "full" mode by default (change)
- DIGEST and CLIENT-CERT used "full" mode by default (no change)
- individual authenticators can override the default
re-authentication mode to one of cached, userPassword, full
There is an argument to switch DIGEST to "userPassword" mode by default
if requireReauthentication is enabled but I'm not sure there is enough
of a reason to change the current behaviour.
If you followed my ramblings this far - thank you. Thoughts?
Mark
[1] https://github.com/apache/tomcat/pull/890
[2] https://bz.apache.org/bugzilla/show_bug.cgi?id=23881
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]