3
final class PhabricatorPasswordSettingsPanel extends PhabricatorSettingsPanel {
5
public function getPanelKey() {
9
public function getPanelName() {
10
return pht('Password');
13
public function getPanelGroup() {
14
return pht('Authentication');
17
public function isEnabled() {
18
// There's no sense in showing a change password panel if this install
19
// doesn't support password authentication.
20
if (!PhabricatorPasswordAuthProvider::getPasswordProvider()) {
27
public function processRequest(AphrontRequest $request) {
28
$user = $request->getUser();
30
$token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
35
$min_len = PhabricatorEnv::getEnvConfig('account.minimum-password-length');
36
$min_len = (int)$min_len;
38
// NOTE: To change your password, you need to prove you own the account,
39
// either by providing the old password or by carrying a token to
40
// the workflow from a password reset email.
42
$key = $request->getStr('key');
45
$token = id(new PhabricatorAuthTemporaryTokenQuery())
47
->withObjectPHIDs(array($user->getPHID()))
49
array(PhabricatorAuthSessionEngine::PASSWORD_TEMPORARY_TOKEN_TYPE))
50
->withTokenCodes(array(PhabricatorHash::digest($key)))
60
if ($request->isFormPost()) {
62
$envelope = new PhutilOpaqueEnvelope($request->getStr('old_pw'));
63
if (!$user->comparePassword($envelope)) {
64
$errors[] = pht('The old password you entered is incorrect.');
65
$e_old = pht('Invalid');
69
$pass = $request->getStr('new_pw');
70
$conf = $request->getStr('conf_pw');
72
if (strlen($pass) < $min_len) {
73
$errors[] = pht('Your new password is too short.');
74
$e_new = pht('Too Short');
75
} else if ($pass !== $conf) {
76
$errors[] = pht('New password and confirmation do not match.');
77
$e_conf = pht('Invalid');
78
} else if (PhabricatorCommonPasswords::isCommonPassword($pass)) {
79
$e_new = pht('Very Weak');
80
$e_conf = pht('Very Weak');
82
'Your new password is very weak: it is one of the most common '.
83
'passwords in use. Choose a stronger password.');
87
// This write is unguarded because the CSRF token has already
88
// been checked in the call to $request->isFormPost() and
89
// the CSRF token depends on the password hash, so when it
90
// is changed here the CSRF token check will fail.
91
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
93
$envelope = new PhutilOpaqueEnvelope($pass);
94
id(new PhabricatorUserEditor())
96
->changePassword($user, $envelope);
101
// Destroy the token.
104
// If this is a password set/reset, kick the user to the home page
105
// after we update their account.
108
$next = $this->getPanelURI('?saved=true');
111
id(new PhabricatorAuthSessionEngine())->terminateLoginSessions(
113
$request->getCookie(PhabricatorCookies::COOKIE_SESSION));
115
return id(new AphrontRedirectResponse())->setURI($next);
119
$hash_envelope = new PhutilOpaqueEnvelope($user->getPasswordHash());
120
if (strlen($hash_envelope->openEnvelope())) {
122
$can_upgrade = PhabricatorPasswordHasher::canUpgradeHash(
124
} catch (PhabricatorPasswordHasherUnavailableException $ex) {
125
$can_upgrade = false;
127
// Only show this stuff if we aren't on the reset workflow. We can
128
// do resets regardless of the old hasher's availability.
131
'Your password is currently hashed using an algorithm which is '.
132
'no longer available on this install.');
134
'Because the algorithm implementation is missing, your password '.
135
'can not be used or updated.');
137
'To set a new password, request a password reset link from the '.
138
'login screen and then follow the instructions.');
144
'The strength of your stored password hash can be upgraded. '.
145
'To upgrade, either: log out and log in using your password; or '.
146
'change your password.');
152
$len_caption = pht('Minimum password length: %d characters.', $min_len);
155
$form = new AphrontFormView();
158
->addHiddenInput('key', $key);
162
id(new AphrontFormPasswordControl())
163
->setLabel(pht('Old Password'))
165
->setName('old_pw'));
170
id(new AphrontFormPasswordControl())
171
->setDisableAutocomplete(true)
172
->setLabel(pht('New Password'))
174
->setName('new_pw'));
177
id(new AphrontFormPasswordControl())
178
->setDisableAutocomplete(true)
179
->setLabel(pht('Confirm Password'))
180
->setCaption($len_caption)
182
->setName('conf_pw'));
185
id(new AphrontFormSubmitControl())
186
->setValue(pht('Change Password')));
189
id(new AphrontFormStaticControl())
190
->setLabel(pht('Current Algorithm'))
191
->setValue(PhabricatorPasswordHasher::getCurrentAlgorithmName(
192
new PhutilOpaqueEnvelope($user->getPasswordHash()))));
195
id(new AphrontFormStaticControl())
196
->setLabel(pht('Best Available Algorithm'))
197
->setValue(PhabricatorPasswordHasher::getBestAlgorithmName()));
199
$form->appendRemarkupInstructions(
201
'NOTE: Changing your password will terminate any other outstanding '.
204
$form_box = id(new PHUIObjectBoxView())
205
->setHeaderText(pht('Change Password'))
206
->setFormSaved($request->getStr('saved'))
207
->setFormErrors($errors)