2011-01-31 20:55:26 +01:00
|
|
|
<?php
|
|
|
|
|
2012-03-10 00:46:25 +01:00
|
|
|
final class PhabricatorEmailLoginController
|
|
|
|
extends PhabricatorAuthController {
|
2011-01-31 20:55:26 +01:00
|
|
|
|
|
|
|
public function shouldRequireLogin() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function processRequest() {
|
|
|
|
$request = $this->getRequest();
|
|
|
|
|
2013-06-20 20:18:48 +02:00
|
|
|
if (!PhabricatorAuthProviderPassword::getPasswordProvider()) {
|
2011-02-28 04:47:22 +01:00
|
|
|
return new Aphront400Response();
|
|
|
|
}
|
|
|
|
|
2011-01-31 20:55:26 +01:00
|
|
|
$e_email = true;
|
|
|
|
$e_captcha = true;
|
|
|
|
$errors = array();
|
|
|
|
|
Provide a configuration flag to disable silliness in the UI
Summary: See comments. A few installs have remarked that their organizations
would prefer buttons labled "Submit" to buttons labeled "Clowncopterize".
Test Plan:
- In "serious" mode, verified Differential and Maniphest have serious strings,
tasks can not be closed out of spite, and reset/welcome emails are extremely
serious.
- In unserious mode, verified Differential and Maniphest have normal strings,
tasks can be closed out of spite, and reset/welcome emails are silly.
- This does not disable the "fax these changes" message in Arcanist (no
reasonable way for it to read the config value) or the rainbow syntax
highlighter (already removable though configuration).
Reviewers: moskov, jungejason, nh, tuomaspelkonen, aran
Reviewed By: moskov
CC: aran, moskov
Differential Revision: 1081
2011-11-04 23:16:34 +01:00
|
|
|
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
|
|
|
|
|
2011-01-31 20:55:26 +01:00
|
|
|
if ($request->isFormPost()) {
|
|
|
|
$e_email = null;
|
2013-01-27 01:17:44 +01:00
|
|
|
$e_captcha = pht('Again');
|
2011-01-31 20:55:26 +01:00
|
|
|
|
|
|
|
$captcha_ok = AphrontFormRecaptchaControl::processCaptcha($request);
|
|
|
|
if (!$captcha_ok) {
|
2013-01-27 01:17:44 +01:00
|
|
|
$errors[] = pht("Captcha response is incorrect, try again.");
|
|
|
|
$e_captcha = pht('Invalid');
|
2011-01-31 20:55:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
$email = $request->getStr('email');
|
|
|
|
if (!strlen($email)) {
|
2013-01-27 01:17:44 +01:00
|
|
|
$errors[] = pht("You must provide an email address.");
|
|
|
|
$e_email = pht('Required');
|
2011-01-31 20:55:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!$errors) {
|
|
|
|
// NOTE: Don't validate the email unless the captcha is good; this makes
|
|
|
|
// it expensive to fish for valid email addresses while giving the user
|
|
|
|
// a better error if they goof their email.
|
|
|
|
|
2012-05-07 19:29:33 +02:00
|
|
|
$target_email = id(new PhabricatorUserEmail())->loadOneWhere(
|
|
|
|
'address = %s',
|
2011-01-31 20:55:26 +01:00
|
|
|
$email);
|
|
|
|
|
2012-05-07 19:29:33 +02:00
|
|
|
$target_user = null;
|
|
|
|
if ($target_email) {
|
|
|
|
$target_user = id(new PhabricatorUser())->loadOneWhere(
|
|
|
|
'phid = %s',
|
|
|
|
$target_email->getUserPHID());
|
|
|
|
}
|
|
|
|
|
2011-01-31 20:55:26 +01:00
|
|
|
if (!$target_user) {
|
2013-01-27 01:17:44 +01:00
|
|
|
$errors[] =
|
|
|
|
pht("There is no account associated with that email address.");
|
|
|
|
$e_email = pht("Invalid");
|
2011-01-31 20:55:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!$errors) {
|
Make password reset emails use one-time tokens
Summary:
Ref T4398. This code hadn't been touched in a while and had a few crufty bits.
**One Time Resets**: Currently, password reset (and similar links) are valid for about 48 hours, but we always use one token to generate them (it's bound to the account). This isn't horrible, but it could be better, and it produces a lot of false positives on HackerOne.
Instead, use TemporaryTokens to make each link one-time only and good for no more than 24 hours.
**Coupling of Email Verification and One-Time Login**: Currently, one-time login links ("password reset links") are tightly bound to an email address, and using a link verifies that email address.
This is convenient for "Welcome" emails, so the user doesn't need to go through two rounds of checking email in order to login, then very their email, then actually get access to Phabricator.
However, for other types of these links (like those generated by `bin/auth recover`) there's no need to do any email verification.
Instead, make the email verification part optional, and use it on welcome links but not other types of links.
**Message Customization**: These links can come out of several workflows: welcome, password reset, username change, or `bin/auth recover`. Add a hint to the URI so the text on the page can be customized a bit to help users through the workflow.
**Reset Emails Going to Main Account Email**: Previously, we would send password reset email to the user's primary account email. However, since we verify email coming from reset links this isn't correct and could allow a user to verify an email without actually controlling it.
Since the user needs a real account in the first place this does not seem useful on its own, but might be a component in some other attack. The user might also no longer have access to their primary account, in which case this wouldn't be wrong, but would not be very useful.
Mitigate this in two ways:
- First, send to the actual email address the user entered, not the primary account email address.
- Second, don't let these links verify emails: they're just login links. This primarily makes it more difficult for an attacker to add someone else's email to their account, send them a reset link, get them to login and implicitly verify the email by not reading very carefully, and then figure out something interesting to do (there's currently no followup attack here, but allowing this does seem undesirable).
**Password Reset Without Old Password**: After a user logs in via email, we send them to the password settings panel (if passwords are enabled) with a code that lets them set a new password without knowing the old one.
Previously, this code was static and based on the email address. Instead, issue a one-time code.
**Jump Into Hisec**: Normally, when a user who has multi-factor auth on their account logs in, we prompt them for factors but don't put them in high security. You usually don't want to go do high-security stuff immediately after login, and it would be confusing and annoying if normal logins gave you a "YOU ARE IN HIGH SECURITY" alert bubble.
However, if we're taking you to the password reset screen, we //do// want to put the user in high security, since that screen requires high security. If we don't do this, the user gets two factor prompts in a row.
To accomplish this, we set a cookie when we know we're sending the user into a high security workflow. This cookie makes login finalization upgrade all the way from "partial" to "high security", instead of stopping halfway at "normal". This is safe because the user has just passed a factor check; the only reason we don't normally do this is to reduce annoyance.
**Some UI Cleanup**: Some of this was using really old UI. Modernize it a bit.
Test Plan:
- **One Time Resets**
- Used a reset link.
- Tried to reuse a reset link, got denied.
- Verified each link is different.
- **Coupling of Email Verification and One-Time Login**
- Verified that `bin/auth`, password reset, and username change links do not have an email verifying URI component.
- Tried to tack one on, got denied.
- Used the welcome email link to login + verify.
- Tried to mutate the URI to not verify, or verify something else: got denied.
- **Message Customization**
- Viewed messages on the different workflows. They seemed OK.
- **Reset Emails Going to Main Account Email**
- Sent password reset email to non-primary email.
- Received email at specified address.
- Verified it does not verify the address.
- **Password Reset Without Old Password**
- Reset password without knowledge of old one after email reset.
- Tried to do that without a key, got denied.
- Tried to reuse a key, got denied.
- **Jump Into Hisec**
- Logged in with MFA user, got factor'd, jumped directly into hisec.
- Logged in with non-MFA user, no factors, normal password reset.
- **Some UI Cleanup**
- Viewed new UI.
- **Misc**
- Created accounts, logged in with welcome link, got verified.
- Changed a username, used link to log back in.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T4398
Differential Revision: https://secure.phabricator.com/D9252
2014-05-22 19:41:00 +02:00
|
|
|
$engine = new PhabricatorAuthSessionEngine();
|
|
|
|
$uri = $engine->getOneTimeLoginURI(
|
|
|
|
$target_user,
|
|
|
|
null,
|
|
|
|
PhabricatorAuthSessionEngine::ONETIME_RESET);
|
|
|
|
|
Provide a configuration flag to disable silliness in the UI
Summary: See comments. A few installs have remarked that their organizations
would prefer buttons labled "Submit" to buttons labeled "Clowncopterize".
Test Plan:
- In "serious" mode, verified Differential and Maniphest have serious strings,
tasks can not be closed out of spite, and reset/welcome emails are extremely
serious.
- In unserious mode, verified Differential and Maniphest have normal strings,
tasks can be closed out of spite, and reset/welcome emails are silly.
- This does not disable the "fax these changes" message in Arcanist (no
reasonable way for it to read the config value) or the rainbow syntax
highlighter (already removable though configuration).
Reviewers: moskov, jungejason, nh, tuomaspelkonen, aran
Reviewed By: moskov
CC: aran, moskov
Differential Revision: 1081
2011-11-04 23:16:34 +01:00
|
|
|
if ($is_serious) {
|
|
|
|
$body = <<<EOBODY
|
|
|
|
You can use this link to reset your Phabricator password:
|
|
|
|
|
|
|
|
{$uri}
|
|
|
|
|
|
|
|
EOBODY;
|
|
|
|
} else {
|
|
|
|
$body = <<<EOBODY
|
Revise administrative workflow for user creation
Summary:
- When an administrator creates a user, provide an option to send a welcome
email. Right now this workflow kind of dead-ends.
- Prevent administrators from changing the "System Agent" flag. If they can
change it, they can grab another user's certificate and then act as them. This
is a vaguely weaker security policy than is exhibited elsewhere in the
application. Instead, make user accounts immutably normal users or system agents
at creation time.
- Prevent administrators from changing email addresses after account creation.
Same deal as conduit certs. The 'bin/accountadmin' script can still do this if a
user has a real problem.
- Prevent administrators from resetting passwords. There's no need for this
anymore with welcome emails plus email login and it raises the same issues.
Test Plan:
- Created a new account, selected "send welcome email", got a welcome email,
logged in with the link inside it.
- Created a new system agent.
- Reset an account's password.
Reviewed By: aran
Reviewers: tuomaspelkonen, jungejason, aran
CC: anjali, aran, epriestley
Differential Revision: 379
2011-05-30 23:59:17 +02:00
|
|
|
Condolences on forgetting your password. You can use this link to reset it:
|
|
|
|
|
|
|
|
{$uri}
|
|
|
|
|
|
|
|
After you set a new password, consider writing it down on a sticky note and
|
|
|
|
attaching it to your monitor so you don't forget again! Choosing a very short,
|
|
|
|
easy-to-remember password like "cat" or "1234" might also help.
|
|
|
|
|
|
|
|
Best Wishes,
|
|
|
|
Phabricator
|
|
|
|
|
|
|
|
EOBODY;
|
Provide a configuration flag to disable silliness in the UI
Summary: See comments. A few installs have remarked that their organizations
would prefer buttons labled "Submit" to buttons labeled "Clowncopterize".
Test Plan:
- In "serious" mode, verified Differential and Maniphest have serious strings,
tasks can not be closed out of spite, and reset/welcome emails are extremely
serious.
- In unserious mode, verified Differential and Maniphest have normal strings,
tasks can be closed out of spite, and reset/welcome emails are silly.
- This does not disable the "fax these changes" message in Arcanist (no
reasonable way for it to read the config value) or the rainbow syntax
highlighter (already removable though configuration).
Reviewers: moskov, jungejason, nh, tuomaspelkonen, aran
Reviewed By: moskov
CC: aran, moskov
Differential Revision: 1081
2011-11-04 23:16:34 +01:00
|
|
|
}
|
2011-01-31 20:55:26 +01:00
|
|
|
|
Add optional "Re:" prefix to all threaded mail and allow disabling mail about
your own actions
Summary:
- Mail.app on Lion has cumbersome threading rules, see T782. Add an option to
stick "Re: " in front of all threaded mail so it behaves. This is horrible, but
apparently the least-horrible option.
- While I was in there, I added an option for T228.
Test Plan:
- Sent a bunch of threaded and unthreaded mail with varous "Re:" settings,
seemed to get "Re:" in the right places.
- Disabled email about my stuff, created a task with just me, got voided mail,
added a CC, got mail to just the CC.
Reviewers: btrahan, jungejason
Reviewed By: btrahan
CC: aran, mkjones
Maniphest Tasks: T228, T782
Differential Revision: https://secure.phabricator.com/D1448
2012-01-18 05:32:28 +01:00
|
|
|
// NOTE: Don't set the user as 'from', or they may not receive the
|
|
|
|
// mail if they have the "don't send me email about my own actions"
|
|
|
|
// preference set.
|
|
|
|
|
Make password reset emails use one-time tokens
Summary:
Ref T4398. This code hadn't been touched in a while and had a few crufty bits.
**One Time Resets**: Currently, password reset (and similar links) are valid for about 48 hours, but we always use one token to generate them (it's bound to the account). This isn't horrible, but it could be better, and it produces a lot of false positives on HackerOne.
Instead, use TemporaryTokens to make each link one-time only and good for no more than 24 hours.
**Coupling of Email Verification and One-Time Login**: Currently, one-time login links ("password reset links") are tightly bound to an email address, and using a link verifies that email address.
This is convenient for "Welcome" emails, so the user doesn't need to go through two rounds of checking email in order to login, then very their email, then actually get access to Phabricator.
However, for other types of these links (like those generated by `bin/auth recover`) there's no need to do any email verification.
Instead, make the email verification part optional, and use it on welcome links but not other types of links.
**Message Customization**: These links can come out of several workflows: welcome, password reset, username change, or `bin/auth recover`. Add a hint to the URI so the text on the page can be customized a bit to help users through the workflow.
**Reset Emails Going to Main Account Email**: Previously, we would send password reset email to the user's primary account email. However, since we verify email coming from reset links this isn't correct and could allow a user to verify an email without actually controlling it.
Since the user needs a real account in the first place this does not seem useful on its own, but might be a component in some other attack. The user might also no longer have access to their primary account, in which case this wouldn't be wrong, but would not be very useful.
Mitigate this in two ways:
- First, send to the actual email address the user entered, not the primary account email address.
- Second, don't let these links verify emails: they're just login links. This primarily makes it more difficult for an attacker to add someone else's email to their account, send them a reset link, get them to login and implicitly verify the email by not reading very carefully, and then figure out something interesting to do (there's currently no followup attack here, but allowing this does seem undesirable).
**Password Reset Without Old Password**: After a user logs in via email, we send them to the password settings panel (if passwords are enabled) with a code that lets them set a new password without knowing the old one.
Previously, this code was static and based on the email address. Instead, issue a one-time code.
**Jump Into Hisec**: Normally, when a user who has multi-factor auth on their account logs in, we prompt them for factors but don't put them in high security. You usually don't want to go do high-security stuff immediately after login, and it would be confusing and annoying if normal logins gave you a "YOU ARE IN HIGH SECURITY" alert bubble.
However, if we're taking you to the password reset screen, we //do// want to put the user in high security, since that screen requires high security. If we don't do this, the user gets two factor prompts in a row.
To accomplish this, we set a cookie when we know we're sending the user into a high security workflow. This cookie makes login finalization upgrade all the way from "partial" to "high security", instead of stopping halfway at "normal". This is safe because the user has just passed a factor check; the only reason we don't normally do this is to reduce annoyance.
**Some UI Cleanup**: Some of this was using really old UI. Modernize it a bit.
Test Plan:
- **One Time Resets**
- Used a reset link.
- Tried to reuse a reset link, got denied.
- Verified each link is different.
- **Coupling of Email Verification and One-Time Login**
- Verified that `bin/auth`, password reset, and username change links do not have an email verifying URI component.
- Tried to tack one on, got denied.
- Used the welcome email link to login + verify.
- Tried to mutate the URI to not verify, or verify something else: got denied.
- **Message Customization**
- Viewed messages on the different workflows. They seemed OK.
- **Reset Emails Going to Main Account Email**
- Sent password reset email to non-primary email.
- Received email at specified address.
- Verified it does not verify the address.
- **Password Reset Without Old Password**
- Reset password without knowledge of old one after email reset.
- Tried to do that without a key, got denied.
- Tried to reuse a key, got denied.
- **Jump Into Hisec**
- Logged in with MFA user, got factor'd, jumped directly into hisec.
- Logged in with non-MFA user, no factors, normal password reset.
- **Some UI Cleanup**
- Viewed new UI.
- **Misc**
- Created accounts, logged in with welcome link, got verified.
- Changed a username, used link to log back in.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley
Maniphest Tasks: T4398
Differential Revision: https://secure.phabricator.com/D9252
2014-05-22 19:41:00 +02:00
|
|
|
$mail = id(new PhabricatorMetaMTAMail())
|
|
|
|
->setSubject(pht('[Phabricator] Password Reset'))
|
|
|
|
->addRawTos(array($target_email->getAddress()))
|
|
|
|
->setBody($body)
|
|
|
|
->saveAndSend();
|
|
|
|
|
|
|
|
return $this->newDialog()
|
|
|
|
->setTitle(pht('Check Your Email'))
|
|
|
|
->setShortTitle(pht('Email Sent'))
|
|
|
|
->appendParagraph(
|
|
|
|
pht('An email has been sent with a link you can use to login.'))
|
|
|
|
->addCancelButton('/', pht('Done'));
|
2011-01-31 20:55:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-06-21 02:11:57 +02:00
|
|
|
$error_view = null;
|
|
|
|
if ($errors) {
|
|
|
|
$error_view = new AphrontErrorView();
|
|
|
|
$error_view->setErrors($errors);
|
|
|
|
}
|
|
|
|
|
2013-08-26 20:53:11 +02:00
|
|
|
$email_auth = new PHUIFormLayoutView();
|
2013-06-21 02:11:57 +02:00
|
|
|
$email_auth->appendChild($error_view);
|
2011-01-31 20:55:26 +01:00
|
|
|
$email_auth
|
|
|
|
->setUser($request->getUser())
|
2013-06-21 02:11:57 +02:00
|
|
|
->setFullWidth(true)
|
2011-01-31 20:55:26 +01:00
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormTextControl())
|
2013-01-27 01:17:44 +01:00
|
|
|
->setLabel(pht('Email'))
|
2011-01-31 20:55:26 +01:00
|
|
|
->setName('email')
|
|
|
|
->setValue($request->getStr('email'))
|
|
|
|
->setError($e_email))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormRecaptchaControl())
|
2013-01-27 01:17:44 +01:00
|
|
|
->setLabel(pht('Captcha'))
|
2013-06-21 02:11:57 +02:00
|
|
|
->setError($e_captcha));
|
2011-01-31 20:55:26 +01:00
|
|
|
|
2013-06-21 02:11:57 +02:00
|
|
|
$crumbs = $this->buildApplicationCrumbs();
|
2013-12-19 02:47:34 +01:00
|
|
|
$crumbs->addTextCrumb(pht('Reset Password'));
|
2011-01-31 20:55:26 +01:00
|
|
|
|
2013-06-21 02:11:57 +02:00
|
|
|
$dialog = new AphrontDialogView();
|
|
|
|
$dialog->setUser($request->getUser());
|
|
|
|
$dialog->setTitle(pht(
|
|
|
|
'Forgot Password / Email Login'));
|
|
|
|
$dialog->appendChild($email_auth);
|
|
|
|
$dialog->addSubmitButton(pht('Send Email'));
|
|
|
|
$dialog->setSubmitURI('/login/email/');
|
2011-01-31 20:55:26 +01:00
|
|
|
|
2013-01-27 01:17:44 +01:00
|
|
|
return $this->buildApplicationPage(
|
2011-01-31 20:55:26 +01:00
|
|
|
array(
|
2013-06-21 02:11:57 +02:00
|
|
|
$crumbs,
|
|
|
|
$dialog,
|
2011-01-31 20:55:26 +01:00
|
|
|
),
|
|
|
|
array(
|
2013-01-27 01:17:44 +01:00
|
|
|
'title' => pht('Forgot Password'),
|
|
|
|
'device' => true,
|
2011-01-31 20:55:26 +01:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|