How to Configure Password Expiration for Your Site

Part of managing security for your web app includes being able to set password restrictions to reduce the chances of nefarious activity.

The django-user-accounts password expiration feature forces users to create a new password on a regular basis. This feature works for existing sites as well as new sites, and can be enabled or disabled whenever desired.

Enabling password expiration requires two steps:

  1. Enabling middleware
  2. Configuring a couple of settings

Enabling Middleware

Include account.middleware.ExpiredPasswordMiddleware in MIDDLEWARE_CLASSES:

MIDDLEWARE_CLASSES = [
    ...
    "account.middleware.ExpiredPasswordMiddleware",
    ...
]

For an authenticated user whose password is expired, ExpiredPasswordMiddleware prevents retrieving or posting to any page except the password change and log out pages.

Note: If the user is “staff” (can access the Django admin site), password checking is skipped.

Configure Settings

ACCOUNT_PASSWORD_USE_HISTORY = True
ACCOUNT_PASSWORD_EXPIRY = 60*60*24*5  # number of seconds, this is five days

ACCOUNT_PASSWORD_USE_HISTORY is a boolean which enables or disables password expiration. In order to disable password expiration, simply set ACCOUNT_PASSWORD_USE_HISTORY = False . No history will be generated and password expiration WILL NOT be checked.

ACCOUNT_PASSWORD_EXPIRY indicates the duration passwords will remain valid. After that period a password must be reset in order to view any page. This is a global setting for all users. If ACCOUNT_PASSWORD_EXPIRY is zero (0) then passwords never expire.

Creating password history

For new users, nothing special is required except the settings and middleware shown above. A password history entry is automatically created as each new user is added to the system, and middleware will ensure a new password is created when the old password expires.

Existing users have no password history. In order for password expiration to work, each user must have a password history. django-user-accounts provides a management command, user_password_history, which creates an initial password history for all users who don’t already have a password history

Usage:

python manage.py user_password_history [-d <days>] [--force]

Parameters:

  • -d <days> - optional, sets the age of the current password. Password age defaults to ten days ago if not specified.
  • --force - optional, forces a new password history for all users, regardless of previous history.

User-specific password expiry

Typically password expiration duration is the same for all users, as specified by setting ACCOUNT_PASSWORD_EXPIRY. However, django-user-accounts includes a management command which sets a user-specific password expiration duration. User-specific values override the global ACCOUNT_PASSWORD_EXPIRY for these users. Technically, password expiration middleware first tries to find a user-specific password expiry value. If no user-specific password expiry exists, middleware uses the global expiration value ACCOUNT_PASSWORD_EXPIRY.

Usage:

python manage.py user_password_expiry username [username] [--expire <days>]

Parameters:

  • <username> [<username>] - required, username(s) of the user(s) who needs specific password expiry.
  • --expire <seconds> - optional, sets the number of seconds for password expiration. Default expiration value is the current global ACCOUNT_PASSWORD_EXPIRY value.

Other Uses for Password History

Password history entries are saved forever, unless deleted manually. This allows checking password history when a user chooses a new password. For instance, you may want users to never re-use an old password. Password history gives you this opportunity. Obtain old entries with standard Django object manager calls:

from account.models import PasswordHistory

user_password_history = user.password_history_set.all()