Feature Proposal: Add way to disable and expire passwords, and expire accounts.

Motivation

The inability to disable passwords, and block reset, or reuse of WikiName and Email address has been a long-desired feature. In addition, forcing a user to change their password either after certain events, or on a time interval is considered a good security practice.

The TWiki project added some of this. recently. We can use some of the design, but the API and UI both need a bit of work.

Description and Documentation

.htpasswd file changes

htdigest format: [#]UserName:AuthRealm:password:email1,email2:passwordExpires:pwdChgTime:accountExpires
htpasswd format: [#]UserName:password:email1,email2:passwordExpires:pwdChgTime:accountExpires

Disabled entries prefixed with #
  • On load, # is removed and the {Enable} flag is set to 0.
  • On save, any {Enable}=0 entries are written with prepended #
passwordExpires values
  • 0 or empy: Never expires
  • Any date "today" or earlier, change required before access permitted.

Users API

  • Add a "disabled account" indication to .htpasswd entries.
  • Add expires info to .htpaswd
  • Extend the Users API
Field Status getter* / *setter Default behavior
Enabled
 
userEnabled($login, $enabled) -> boolean
Returns true if the PasswordManager or Mapper don't support the feature.
PasswordExpires
isPasswordExpired($login)
passwordExpires($login, $date) -> date
Returns false if not supported.
PasswordLastChange
passwordLastChange($login) -> date
 
Returns 0 if not supported.
AccountExpires
isAccountExpired($login)
accountExpires($login, $date) -> date
Returns false and year 9999 if not supported.

For HtPasswdUser.pm, the set methods do an immediate save of the password file. For multiple-field updates in management forms also add:
getUserData(uid) -> {field hash}
setUserData( { field hash } )

Configuration

  • Configure needs to set default password lifetime. $Foswiki::cfg{PasswordControl}{PasswordValidFor} = 0; Configure lifetime in days. Default 0 means passwords will not expire.
  • Configure should set optional minimum password lifetime. $Foswiki::cfg{PasswordContro}{BlockChangeFor} = 0; Configure minimum time between password change. Default 0 means no restriction.
  • $Foswiki::cfg{MinPasswordLength} should be renamed to $Foswiki::cfg{PasswordControl}{MinPasswordLength}

Macros

USERINFO

Extend the USERINFO macro format string with the following tokens:
  • $enabled: Returns true/false account enable status. (all users)
  • $passwordExpires: Returns expiration date. (admin only)
  • $lastChange: Returns date/time of last password change. (admin only)
  • $accountExpires: Returns expiration date. (admin only)
  • $status: Returns "Active", "Password expired" and/or "Account expired"
Also add template parameter, to allow templated / skinned results instead of requiring complex format strings. Expands the named template with token substitution.

USERLIST (new)

Currently the only way to list users is a search of the Main, for topics with a UserForm. This fails for external mappers like LDAP, and is also going to be less reliable for Topic mapping, now that Foswiki 2.1 supports multiple form names for User forms.
%USERLIST{"filter-spec" format="$wikiname," limit=20 }%

Default is to list "limit" users, including the Base mapper and the configured Mapper. I think it would be more useful to exclude the Base mapper. That would require change to the Foswiki::Func::eachUser() and the Foswiki::Users->eachUser() to select the desired mapper.

Change dialogs that currently search for UserForm, to use USERLIST.

User Management Application

Implement as a Plugin rather than core changes to UI::Manage.
  • Topic to search and list users for edit
  • Edit topic displays single user's data from Password system for change.
  • Either form-based rest verb to change the user's data or
  • javascript with jsonrpc backend for user changes.

Also under consideration, an optional preRenderingHandler to render expired user wikiNames as Wikiname

General behaviour

  • Users with expired passwords should be immediately redirected to ChangePassword on next access.
  • Users with expired accounts should be presented with an Oops screen with an explanation.
  • Disabled Users should receive an Oops screen with explanation.
  • Disabled or Expired Accounts should not receive any MailNotify messages.

Other topics:
  • BulkRegistration should support the password expiration.
  • Password reset should set expiration to "1" - to trigger required password change on next use.

Examples

Impact

%WHATDOESITAFFECT%
edit

Implementation

-- Contributors: GeorgeClark - 26 Feb 2016

Discussion

"known" users are displayed as a normal wiki link. This is good. It would be great if these disabled users were visually identifiable when the link shows up on a topic page, perhaps as a normal blue link but with an overstrike.

-- HarlanStenn - 26 Feb 2016

Amending proposal to include some additional integration:
  • BulkUserRegistration needs to support the Account and Password expiration fields
  • Configure needs to set default password lifetime.
  • Configure should set optional minimum password lifetime.
  • Password change should block changing a password to itself.

-- GeorgeClark - 28 Feb 2016

This is fine, just remember that not all password systems will have the capability to process all the requests you describe. As always, the password storage detail must be hidden behind the Password Manager interface.

-- Main.CrawfordCurrie - 22 Mar 2016 - 10:28

I have a question about the proposed USERLIST macro. With TopicUserMappingContrib, its possible to somewhat "hide" users by restricting VIEW access from their USERSWEB topic. A USERLIST macro which access the mapper's forEachUser would see all users regardless of whether they have an accessible USERSWEB topic or not. This could potentially expose more users when used in place of the topic %SEARCH macro implementation.
  • Should USERLIST macro have any access restrictions? Checking view authority for each returned user would have a considerable performance penalty, especially in an LDAP environment where there are possibly a large number of users, and many without a user topic existing.

Foswiki::Func::eachUser can currently only return a WikiName. It does not support cUID, login name, etc. My plan for USERLIST is to only return WikiName. (ie format="$wikiname". If a user desired more information, they can use format="$percntUSERINFO{"$wikiname"... }$percnt" As the USERINFO macro does have access restrictions, it would apply further controls to the returned information rather than duplicating the controls in the USERLIST macro.

-- GeorgeClark - 06 Jun 2017

Since we don't really have a user object, the API was not correct. Changed to pass $login as a parameter to the API calls.

For best compatibility, the API extensions implemented in the base classes will return defaults when a mapper / password manager do not support the call.

-- GeorgeClark - 16 Jun 2017

Removing this from the 2.2 release plan.

-- GeorgeClark - 14 Dec 2017
 
Topic revision: r9 - 14 Dec 2017, GeorgeClark
The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License    Legal Imprint    Privacy Policy