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]

Reply via email to