SAF Expired Password Information

Known Issues with Updating SAF Password via the AuthSAFExpiration Directive

Users of mod_authnz_saf are only affected by these issues when the AuthSAFExpiration or AuthSAFReEnter directives are set. For those looking for an alternative way to notify users of their password expiration, please look at AuthSAFExpiredRedirect directive or using form-based authentication instead.

Chrome does not display the expired password realm message

After Chrome 49, Chrome no longer displays a basic realm message in their basic authentication prompt. This change prevents mod_authnz_saf from notifying users that their SAF password has expired since mod_authnz_saf appends the expired message to the realm message. Issue 602301 was opened to track this issue. The issue is still present in Chrome as of version 58.0.3029.110.

Firefox issues several authentication requests after user is prompted to update SAF password

When a user provides credentials for basic authentication, Firefox will cache the credentials and provide them automatically for authentication requests with the same realm. This has been found to cause issues where Firefox will repeatedly respond to 401 responses with the cached credentials until Firefox finally gives up. This can result in increased CPU usage and cause a lot of output to be written to the logs. It can also cause a user account to be revoked after too many unsuccessful authentication attempts.

A particular scenario where this is an issue is when a user attempts to access a page that requires authentication and their credentials have expired:

  1. The user makes a request that requires authentication. mod_authnz_saf responds with a 401 with the realm message "SAF Basic Authentication".

  2. The user provides their credentials that happen to be expired which are now cached by Firefox. mod_authnz_saf responds with another 401, but this time with "Expired ! oldpw/newpw/newpw" appended to the original realm.

  3. The user provides invalid credentials to which Firefox caches for the expired realm message. mod_authnz_saf fails to authenticate the user with the invalid credentials and responds with yet another 401 response with the original realm message.

  4. Firefox provides the valid but expired cached credentials for the original realm. mod_authnz_saf subsequently responds with another 401 with the expired message realm to let the user know to update their password.

  5. Firefox sees the expired message realm and responds by providing the incorrect cached credentials. This cycles repeats until Firefox eventually gives up and clears the cached credentials.

See Firefox Bug 201620 for more information.

Expired Password Loop Mitigation

To mitigate the number of authentication requests that hit the server, the session cookie saf_auth_limit was introduced. The cookie is added on the first expired password update request and is decremented for each subsequent expired password update request. Once the expired password update request limit has been reached (2 by default), a 403 Forbidden will be returned, stopping Firefox from sending any more authentication requests using cached credentials. This feature is available in fixpacks 9.0.0.5, 8.5.5.12, 8.0.0.14, 7.0.0.45 and above.

The 403 error page will display general instructions that the user can follow to successfully update their password. Furthermore, a custom message (either text or HTML) can be added to the error page to provide or link to additional information using the AuthSAFUpdateFailedMessage directive.

The environment variable SAF_AUTH_LIMIT was added to change the limit of expired password update requests that is allowed before a 403 occurs. By setting the environment variable SAF_AUTH_LIMIT to -1, this feature can be disabled entirely. A few examples are provided below.

# Increase the limit of expired password update requests allowed for Firefox user agents
BrowserMatch Firefox SAF_AUTH_LIMIT=3

# Disable this feature for all browsers except Firefox
BrowserMatch . SAF_AUTH_LIMIT=-1
BrowserMatch Firefox SAF_AUTH_LIMIT=2

# Disable this feature entirely
BrowserMatch . SAF_AUTH_LIMIT=-1

Using AuthSAFExpiredRedirect instead of AuthSAFExpiration

It is suggested that the SAF password update via AuthSAFExpiration not be used as there are usability issues with both Chrome and Firefox. AuthSAFExpiration can be disabled by commenting or removing the following directives from the httpd configuration file:

# Remove these lines from the configuration
AuthSAFExpiration custom-text
AuthSAFReEnter custom-text

Informing users that their SAF password has expired can be done by redirecting to an error page defined by the AuthSAFExpiredRedirect directive. An example of such a configuration is as follows:

<Location "/saf_protected/">
  AuthName "SAF Basic Authentication"
  AuthType Basic
  AuthBasicProvider saf
  Require valid-user
  AuthSAFExpiredRedirect /error/saf_expired.html
</Location>

It is also important to verify that the redirect target is not protected! If the error page is protected, it can be unprotected using one of the following stanzas:

# IHS 9.0 and above
<IfModule authn_core_module>
  <Location "/error">
    Require all granted
  </Location>
</IfModule>

# IHS 8.0 and 8.5.5
<IfModule authz_default_module>
  <Location "/error">
    Order allow,deny
    Allow from all
    Satisfy any
  </Location>
</IfModule>

Form-Based SAF Password Update Utility

A feature has been added with PI81602 to allow users to update their passwords using a form. It also allows users to use a custom form instead of the default form that mod_authnz_saf provides. PI81602 is targeted for IBM HTTP Server fixpacks: 9.0.0.5, 8.5.5.12, 8.0.0.14, and 7.0.0.45.

The feature can be enabled by adding the mod_authnz_saf handler saf-change-pw and redirecting to the handler when a user's password has expired using the AuthSAFExpiredForm directive. A basic configuration will look similar to the following stanza:

# Enable and configure the mod_authnz_saf module
LoadModule authnz_saf_module modules/mod_authnz_saf.so

<Location "/saf_protected/">
  AuthName "SAF Basic Authentication"
  AuthType Basic
  AuthBasicProvider saf
  Require valid-user

  # Redirect to the saf-change-pw handler to handle expired passwords.
  AuthSAFExpiredForm /change-saf-password
</Location>


# Enable the saf-change-pw handler. It is important to make sure this location
# is not protected! An example of un-protecting a certain location is given
# in the previous section.
<Location "/change-saf-password">
  SetHandler saf-change-pw

  # The IBM-1047 character set encoding is required if using the default form provided
  # by the handler. This is to make sure the correct encoding is set in case the user
  # switches CharsetSourceEnc to a value other than IBM-1047.
  CharsetSourceEnc IBM-1047

  # This option is required so that the handler is able to read the request body. This
  # needs to be set in case the translation of request bodies was disabled in a more
  # generic context (e.g. virtual host, server, etc).
  CharsetOptions TranslateRequestBodies
</Location>

Using a Custom SAF Password Update Form

Using a custom form page [example] is also an option instead of using the default one. There are certain requirements that must be followed, however, so that mod_authnz_saf can process the form's data:

  • The form content type must be application/x-www-form-urlencoded.

  • The form must post to the saf-change-pw handler defined in the httpd configuration.

  • There must be a user name field named user.

  • There must be a password field named old_password.

  • There must be a password field named new_password.

  • There must be a password field named confirm_new_password.

  • There must be a hidden input field named original_uri whose value should be set to the the value uri passed in via the query string. See the link to the example HTML form above.

Errors are passed back as an ID to the client using the query string variable error. The list of error IDs and their meanings can be found in the linked example form above.

The custom form page can be enabled by telling mod_authnz_saf to redirect to it when an expired password is found using the AuthSAFExpiredForm directive:

# Enable and configure the mod_authnz_saf module
LoadModule authnz_saf_module modules/mod_authnz_saf.so

<Location "/saf_protected/">
  AuthName "SAF Basic Authentication"
  AuthType Basic
  AuthBasicProvider saf
  Require valid-user

  # Redirect to the custom form page to handle expired passwords.
  AuthSAFExpiredForm /my-custom-form.html
</Location>

# Make sure the expired form is not protected.
<Location "/my-custom-form.html">
  Require all granted
</Location>

# Enable the saf-change-pw handler. It is important to make sure this location
# also is not protected.
<Location "/change-saf-password">
  SetHandler saf-change-pw
  Require all granted
</Location>

Avoid Trouble when using a Custom Expired Form

  • The location you select to set the saf-change-pw handler on (i.e., change-saf-password from example above) should not represent any path on disk.

  • The custom form must NOT have the same prefix as the password change handler, e.g., /change-saf-password/my-custom-form.html.

  • After PH35356, users will no longer receive a reason for why the password update failed by default. This behavior now requires AuthSAFErrorReason ON to be set in the global server configuration to be enabled.

  • If you use the example saf-password-change.txt provided above, you will need to make the following changes:

    • Update the extension from .txt to .html

    • If you used a different location for your SAF change password handler, then you will also need to update the form's action attribute to point to the correct location.