How to implement Password expiration
Prerequisite: You must be familiar with the Syntax used in Tutorials and have already created an extension.
This tutorial is no more needed as the feature is included in iTop Community since version 3.1.0 with this module Password Expiration Management
In this tutorial, we will describe a mean to force existing users to change their password to comply to a newly added complexity policy.
The administrator would set the expiration
flag of
all users to expired
, then when a user will login,
once the user is ok, we will ask him to change his password.
In order to do that, we need to plug a check on the Login Finite
State Machine, in the state user ok
. And if the
password is expired, display a form to request a new password, then
store it, before going on with the state machine.
Plug the check
class MyClass extend AbstractLoginFSMExtension { public function ListSupportedLoginModes() { return array('form'); } protected function OnUsersOK(&$iErrorCode) { /* Enter the specific code here */ return LoginWebPage::LOGIN_FSM_CONTINUE; } }
Check if password is expired
$oUser = UserRights::GetUserObject(); if ($oUser->Get('expiration') == 'expired') { /* add more code here */ }
Request a new password
This iTop code can be a source, to display a form to request a new password
public function DisplayChangePwdForm($bFailedLogin = false, $sIssue = null) { $oTwigContext = new LoginTwigRenderer(); $aVars = $oTwigContext->GetDefaultVars(); $aVars['bFailedLogin'] = $bFailedLogin; $aVars['sIssue'] = $sIssue; $oTwigContext->Render($this, 'changepwdform.html.twig', $aVars); }
This template can be reused, after removing the
old_pwd
part as at this state of the login, the user
has already provided it and it has already been checked as valid,
so no need to ask it again.
iTop/templates/login/password/changepwdform.html.twig
There is also a changepwdform.js.twig file which control the fact that the two entries are equal and that the password matches the policies. That one can be reuse as is.
Save the new password
Get and save the new password
$sNewPwd = utils::ReadPostedParam('new_pwd', '', 'raw_data'); $oUser->Set('password', $sNewPwd); $oUser->Set('expiration', 'limited'); $oUser->DB_Update();
Be ready for error
Because the password may not be provided correctly or not compliant to policy, we must protect the code with try and catch
try { if (!UserRights::ChangePassword($sOldPwd, $sNewPwd)) { $oPage = self::NewLoginWebPage(); $oPage->DisplayChangePwdForm(true); // new pwd was not compliant ??? $oPage->output(); exit; } } catch (CoreCannotSaveObjectException $e) { $oPage = self::NewLoginWebPage(); $oPage->DisplayChangePwdForm(true, $e->getIssue()); // password policy was not met. $oPage->output(); exit; }
Notes
When an extension automate the expiration behavior, it should
alter the translation UserLocal:password:expiration
displayed within the edit“ page of the UserLocal in order to
reflect this.
We have not implemented any password expiration by default, but
the fields exists on the UserLocal
class to handle it
if an extension brings the behavior using the new login
API.