2013-06-16 19:15:16 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
final class PhabricatorAuthStartController
|
|
|
|
extends PhabricatorAuthController {
|
|
|
|
|
|
|
|
public function shouldRequireLogin() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-02-06 19:50:36 +01:00
|
|
|
public function handleRequest(AphrontRequest $request) {
|
2013-06-16 19:15:16 +02:00
|
|
|
$viewer = $request->getUser();
|
|
|
|
|
|
|
|
if ($viewer->isLoggedIn()) {
|
|
|
|
// Kick the user home if they are already logged in.
|
|
|
|
return id(new AphrontRedirectResponse())->setURI('/');
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($request->isAjax()) {
|
|
|
|
return $this->processAjaxRequest();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($request->isConduit()) {
|
|
|
|
return $this->processConduitRequest();
|
|
|
|
}
|
|
|
|
|
Issue "anonymous" sessions for logged-out users
Summary:
Ref T4339. Ref T4310. Currently, sessions look like `"afad85d675fda87a4fadd54"`, and are only issued for logged-in users. To support logged-out CSRF and (eventually) external user sessions, I made two small changes:
- First, sessions now have a "kind", which is indicated by a prefix, like `"A/ab987asdcas7dca"`. This mostly allows us to issue session queries more efficiently: we don't have to issue a query at all for anonymous sessions, and can join the correct table for user and external sessions and save a query. Generally, this gives us more debugging information and more opportunity to recover from issues in a user-friendly way, as with the "invalid session" error in this diff.
- Secondly, if you load a page and don't have a session, we give you an anonymous session. This is just a secret with no special significance.
This does not implement CSRF yet, but gives us a client secret we can use to implement it.
Test Plan:
- Logged in.
- Logged out.
- Browsed around.
- Logged in again.
- Went through link/register.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4310, T4339
Differential Revision: https://secure.phabricator.com/D8043
2014-01-23 23:03:22 +01:00
|
|
|
// If the user gets this far, they aren't logged in, so if they have a
|
|
|
|
// user session token we can conclude that it's invalid: if it was valid,
|
|
|
|
// they'd have been logged in above and never made it here. Try to clear
|
|
|
|
// it and warn the user they may need to nuke their cookies.
|
2013-06-16 19:15:16 +02:00
|
|
|
|
Issue "anonymous" sessions for logged-out users
Summary:
Ref T4339. Ref T4310. Currently, sessions look like `"afad85d675fda87a4fadd54"`, and are only issued for logged-in users. To support logged-out CSRF and (eventually) external user sessions, I made two small changes:
- First, sessions now have a "kind", which is indicated by a prefix, like `"A/ab987asdcas7dca"`. This mostly allows us to issue session queries more efficiently: we don't have to issue a query at all for anonymous sessions, and can join the correct table for user and external sessions and save a query. Generally, this gives us more debugging information and more opportunity to recover from issues in a user-friendly way, as with the "invalid session" error in this diff.
- Secondly, if you load a page and don't have a session, we give you an anonymous session. This is just a secret with no special significance.
This does not implement CSRF yet, but gives us a client secret we can use to implement it.
Test Plan:
- Logged in.
- Logged out.
- Browsed around.
- Logged in again.
- Went through link/register.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4310, T4339
Differential Revision: https://secure.phabricator.com/D8043
2014-01-23 23:03:22 +01:00
|
|
|
$session_token = $request->getCookie(PhabricatorCookies::COOKIE_SESSION);
|
2014-03-14 22:33:31 +01:00
|
|
|
|
Issue "anonymous" sessions for logged-out users
Summary:
Ref T4339. Ref T4310. Currently, sessions look like `"afad85d675fda87a4fadd54"`, and are only issued for logged-in users. To support logged-out CSRF and (eventually) external user sessions, I made two small changes:
- First, sessions now have a "kind", which is indicated by a prefix, like `"A/ab987asdcas7dca"`. This mostly allows us to issue session queries more efficiently: we don't have to issue a query at all for anonymous sessions, and can join the correct table for user and external sessions and save a query. Generally, this gives us more debugging information and more opportunity to recover from issues in a user-friendly way, as with the "invalid session" error in this diff.
- Secondly, if you load a page and don't have a session, we give you an anonymous session. This is just a secret with no special significance.
This does not implement CSRF yet, but gives us a client secret we can use to implement it.
Test Plan:
- Logged in.
- Logged out.
- Browsed around.
- Logged in again.
- Went through link/register.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4310, T4339
Differential Revision: https://secure.phabricator.com/D8043
2014-01-23 23:03:22 +01:00
|
|
|
if (strlen($session_token)) {
|
|
|
|
$kind = PhabricatorAuthSessionEngine::getSessionKindFromToken(
|
|
|
|
$session_token);
|
|
|
|
switch ($kind) {
|
|
|
|
case PhabricatorAuthSessionEngine::KIND_ANONYMOUS:
|
|
|
|
// If this is an anonymous session. It's expected that they won't
|
|
|
|
// be logged in, so we can just continue.
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// The session cookie is invalid, so clear it.
|
|
|
|
$request->clearCookie(PhabricatorCookies::COOKIE_USERNAME);
|
|
|
|
$request->clearCookie(PhabricatorCookies::COOKIE_SESSION);
|
2013-06-16 19:15:16 +02:00
|
|
|
|
Issue "anonymous" sessions for logged-out users
Summary:
Ref T4339. Ref T4310. Currently, sessions look like `"afad85d675fda87a4fadd54"`, and are only issued for logged-in users. To support logged-out CSRF and (eventually) external user sessions, I made two small changes:
- First, sessions now have a "kind", which is indicated by a prefix, like `"A/ab987asdcas7dca"`. This mostly allows us to issue session queries more efficiently: we don't have to issue a query at all for anonymous sessions, and can join the correct table for user and external sessions and save a query. Generally, this gives us more debugging information and more opportunity to recover from issues in a user-friendly way, as with the "invalid session" error in this diff.
- Secondly, if you load a page and don't have a session, we give you an anonymous session. This is just a secret with no special significance.
This does not implement CSRF yet, but gives us a client secret we can use to implement it.
Test Plan:
- Logged in.
- Logged out.
- Browsed around.
- Logged in again.
- Went through link/register.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4310, T4339
Differential Revision: https://secure.phabricator.com/D8043
2014-01-23 23:03:22 +01:00
|
|
|
return $this->renderError(
|
|
|
|
pht(
|
2014-06-09 20:36:49 +02:00
|
|
|
'Your login session is invalid. Try reloading the page and '.
|
|
|
|
'logging in again. If that does not work, clear your browser '.
|
|
|
|
'cookies.'));
|
Issue "anonymous" sessions for logged-out users
Summary:
Ref T4339. Ref T4310. Currently, sessions look like `"afad85d675fda87a4fadd54"`, and are only issued for logged-in users. To support logged-out CSRF and (eventually) external user sessions, I made two small changes:
- First, sessions now have a "kind", which is indicated by a prefix, like `"A/ab987asdcas7dca"`. This mostly allows us to issue session queries more efficiently: we don't have to issue a query at all for anonymous sessions, and can join the correct table for user and external sessions and save a query. Generally, this gives us more debugging information and more opportunity to recover from issues in a user-friendly way, as with the "invalid session" error in this diff.
- Secondly, if you load a page and don't have a session, we give you an anonymous session. This is just a secret with no special significance.
This does not implement CSRF yet, but gives us a client secret we can use to implement it.
Test Plan:
- Logged in.
- Logged out.
- Browsed around.
- Logged in again.
- Went through link/register.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4310, T4339
Differential Revision: https://secure.phabricator.com/D8043
2014-01-23 23:03:22 +01:00
|
|
|
}
|
|
|
|
}
|
2013-06-16 19:15:16 +02:00
|
|
|
|
|
|
|
$providers = PhabricatorAuthProvider::getAllEnabledProviders();
|
|
|
|
foreach ($providers as $key => $provider) {
|
|
|
|
if (!$provider->shouldAllowLogin()) {
|
|
|
|
unset($providers[$key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$providers) {
|
2013-06-20 01:28:48 +02:00
|
|
|
if ($this->isFirstTimeSetup()) {
|
|
|
|
// If this is a fresh install, let the user register their admin
|
|
|
|
// account.
|
|
|
|
return id(new AphrontRedirectResponse())
|
|
|
|
->setURI($this->getApplicationURI('/register/'));
|
|
|
|
}
|
|
|
|
|
2013-06-16 19:15:16 +02:00
|
|
|
return $this->renderError(
|
|
|
|
pht(
|
2014-06-09 20:36:49 +02:00
|
|
|
'This Phabricator install is not configured with any enabled '.
|
|
|
|
'authentication providers which can be used to log in. If you '.
|
|
|
|
'have accidentally locked yourself out by disabling all providers, '.
|
Fix a pht string
Summary:
This translation string is wrong and causes the following warning when running unit tests:
```
[2015-06-15 16:03:41] ERROR 2: vsprintf(): Too few arguments at [/home/joshua/workspace/github.com/phacility/libphutil/src/internationalization/PhutilTranslator.php:95]
arcanist(head=master, ref.master=956bfa701c36), phabricator(head=master, ref.master=80f11427e576), phutil(head=master, ref.master=3ff84448a916)
#0 vsprintf(string, array) called at [<phutil>/src/internationalization/PhutilTranslator.php:95]
#1 PhutilTranslator::translate(string)
#2 call_user_func_array(array, array) called at [<phutil>/src/internationalization/pht.php:17]
#3 pht(string) called at [<phabricator>/src/applications/auth/controller/PhabricatorAuthStartController.php:75]
#4 PhabricatorAuthStartController::handleRequest(AphrontRequest) called at [<phabricator>/src/aphront/AphrontController.php:69]
#5 AphrontController::delegateToController(PhabricatorAuthStartController) called at [<phabricator>/src/applications/base/controller/PhabricatorController.php:213]
#6 PhabricatorController::willBeginExecution() called at [<phabricator>/src/applications/base/controller/__tests__/PhabricatorAccessControlTestCase.php:270]
#7 PhabricatorAccessControlTestCase::checkAccess(string, PhabricatorTestController, AphrontRequest, array, array) called at [<phabricator>/src/applications/base/controller/__tests__/PhabricatorAccessControlTestCase.php:112]
#8 PhabricatorAccessControlTestCase::testControllerAccessControls()
#9 call_user_func_array(array, array) called at [<arcanist>/src/unit/engine/phutil/PhutilTestCase.php:492]
#10 PhutilTestCase::run() called at [<arcanist>/src/unit/engine/PhutilUnitTestEngine.php:65]
#11 PhutilUnitTestEngine::run() called at [<arcanist>/src/workflow/ArcanistUnitWorkflow.php:186]
#12 ArcanistUnitWorkflow::run() called at [<arcanist>/scripts/arcanist.php:382]
```
Test Plan: `arc lint`
Reviewers: epriestley, #blessed_reviewers, chad
Reviewed By: #blessed_reviewers, chad
Subscribers: epriestley, Korvin
Differential Revision: https://secure.phabricator.com/D13292
2015-06-15 10:01:09 +02:00
|
|
|
'you can use `%s` to recover access to an administrative account.',
|
2015-05-22 09:27:56 +02:00
|
|
|
'phabricator/bin/auth recover <username>'));
|
2013-06-16 19:15:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$next_uri = $request->getStr('next');
|
Make test for setting "next" cookie more general
Summary:
Ref T6870. Since it does not make sense to redirect the user to the login form after they log in, we try not to set the login form as the `next` cookie.
However, the current check is hard-coded to `/auth/start/`, and the form can also be served at `/login/`. This has no real effect on normal users, but did make debugging T6870 confusing.
Instead of using a hard-coded path check, test if the controller was delegated to. If it was, store the URI. If it's handling the request without delegation, don't.
Test Plan:
- Visited login form at `/login/` and `/auth/start/`, saw it not set a next URI.
- Visited login form at `/settings/` (while logged out), saw it set a next URI.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley, lpriestley
Maniphest Tasks: T6870
Differential Revision: https://secure.phabricator.com/D11292
2015-01-09 15:42:03 +01:00
|
|
|
if (!strlen($next_uri)) {
|
|
|
|
if ($this->getDelegatingController()) {
|
|
|
|
// Only set a next URI from the request path if this controller was
|
|
|
|
// delegated to, which happens when a user tries to view a page which
|
|
|
|
// requires them to login.
|
|
|
|
|
|
|
|
// If this controller handled the request directly, we're on the main
|
|
|
|
// login page, and never want to redirect the user back here after they
|
|
|
|
// login.
|
|
|
|
$next_uri = (string)$this->getRequest()->getRequestURI();
|
2013-06-16 19:15:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$request->isFormPost()) {
|
Make test for setting "next" cookie more general
Summary:
Ref T6870. Since it does not make sense to redirect the user to the login form after they log in, we try not to set the login form as the `next` cookie.
However, the current check is hard-coded to `/auth/start/`, and the form can also be served at `/login/`. This has no real effect on normal users, but did make debugging T6870 confusing.
Instead of using a hard-coded path check, test if the controller was delegated to. If it was, store the URI. If it's handling the request without delegation, don't.
Test Plan:
- Visited login form at `/login/` and `/auth/start/`, saw it not set a next URI.
- Visited login form at `/settings/` (while logged out), saw it set a next URI.
Reviewers: btrahan
Reviewed By: btrahan
Subscribers: epriestley, lpriestley
Maniphest Tasks: T6870
Differential Revision: https://secure.phabricator.com/D11292
2015-01-09 15:42:03 +01:00
|
|
|
if (strlen($next_uri)) {
|
|
|
|
PhabricatorCookies::setNextURICookie($request, $next_uri);
|
|
|
|
}
|
2014-03-14 22:33:31 +01:00
|
|
|
PhabricatorCookies::setClientIDCookie($request);
|
2013-06-16 19:15:16 +02:00
|
|
|
}
|
|
|
|
|
2015-02-06 19:50:36 +01:00
|
|
|
if (!$request->getURIData('loggedout') && count($providers) == 1) {
|
|
|
|
$auto_login_provider = head($providers);
|
|
|
|
$auto_login_config = $auto_login_provider->getProviderConfig();
|
|
|
|
if ($auto_login_provider instanceof PhabricatorPhabricatorAuthProvider &&
|
|
|
|
$auto_login_config->getShouldAutoLogin()) {
|
|
|
|
$auto_login_adapter = $provider->getAdapter();
|
|
|
|
$auto_login_adapter->setState($provider->getAuthCSRFCode($request));
|
|
|
|
return id(new AphrontRedirectResponse())
|
|
|
|
->setIsExternal(true)
|
|
|
|
->setURI($provider->getAdapter()->getAuthenticateURI());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-11 15:06:28 +01:00
|
|
|
$invite = $this->loadInvite();
|
|
|
|
|
2013-06-17 01:31:57 +02:00
|
|
|
$not_buttons = array();
|
|
|
|
$are_buttons = array();
|
|
|
|
$providers = msort($providers, 'getLoginOrder');
|
2013-06-16 19:15:16 +02:00
|
|
|
foreach ($providers as $provider) {
|
2015-02-11 15:06:28 +01:00
|
|
|
if ($invite) {
|
|
|
|
$form = $provider->buildInviteForm($this);
|
|
|
|
} else {
|
|
|
|
$form = $provider->buildLoginForm($this);
|
|
|
|
}
|
2013-06-17 01:31:57 +02:00
|
|
|
if ($provider->isLoginFormAButton()) {
|
2015-02-11 15:06:28 +01:00
|
|
|
$are_buttons[] = $form;
|
2013-06-17 01:31:57 +02:00
|
|
|
} else {
|
2015-02-11 15:06:28 +01:00
|
|
|
$not_buttons[] = $form;
|
2013-06-17 01:31:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$out = array();
|
|
|
|
$out[] = $not_buttons;
|
|
|
|
if ($are_buttons) {
|
|
|
|
require_celerity_resource('auth-css');
|
|
|
|
|
|
|
|
foreach ($are_buttons as $key => $button) {
|
|
|
|
$are_buttons[$key] = phutil_tag(
|
|
|
|
'div',
|
|
|
|
array(
|
|
|
|
'class' => 'phabricator-login-button mmb',
|
|
|
|
),
|
|
|
|
$button);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we only have one button, add a second pretend button so that we
|
|
|
|
// always have two columns. This makes it easier to get the alignments
|
|
|
|
// looking reasonable.
|
|
|
|
if (count($are_buttons) == 1) {
|
|
|
|
$are_buttons[] = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$button_columns = id(new AphrontMultiColumnView())
|
|
|
|
->setFluidLayout(true);
|
|
|
|
$are_buttons = array_chunk($are_buttons, ceil(count($are_buttons) / 2));
|
|
|
|
foreach ($are_buttons as $column) {
|
|
|
|
$button_columns->addColumn($column);
|
|
|
|
}
|
|
|
|
|
|
|
|
$out[] = phutil_tag(
|
|
|
|
'div',
|
|
|
|
array(
|
|
|
|
'class' => 'phabricator-login-buttons',
|
|
|
|
),
|
|
|
|
$button_columns);
|
2013-06-16 19:15:16 +02:00
|
|
|
}
|
|
|
|
|
2015-09-04 19:34:39 +02:00
|
|
|
$handlers = PhabricatorAuthLoginHandler::getAllHandlers();
|
|
|
|
|
|
|
|
$delegating_controller = $this->getDelegatingController();
|
|
|
|
|
|
|
|
$header = array();
|
|
|
|
foreach ($handlers as $handler) {
|
|
|
|
$handler = clone $handler;
|
|
|
|
|
|
|
|
$handler->setRequest($request);
|
|
|
|
|
|
|
|
if ($delegating_controller) {
|
|
|
|
$handler->setDelegatingController($delegating_controller);
|
|
|
|
}
|
|
|
|
|
|
|
|
$header[] = $handler->getAuthLoginHeaderContent();
|
|
|
|
}
|
2013-06-16 19:15:16 +02:00
|
|
|
|
2015-02-11 15:06:28 +01:00
|
|
|
$invite_message = null;
|
|
|
|
if ($invite) {
|
|
|
|
$invite_message = $this->renderInviteHeader($invite);
|
|
|
|
}
|
|
|
|
|
2013-06-16 19:15:16 +02:00
|
|
|
$crumbs = $this->buildApplicationCrumbs();
|
2013-12-19 02:47:34 +01:00
|
|
|
$crumbs->addTextCrumb(pht('Login'));
|
2015-02-02 05:12:13 +01:00
|
|
|
$crumbs->setBorder(true);
|
2013-06-16 19:15:16 +02:00
|
|
|
|
|
|
|
return $this->buildApplicationPage(
|
|
|
|
array(
|
|
|
|
$crumbs,
|
2015-09-04 19:34:39 +02:00
|
|
|
$header,
|
2015-02-11 15:06:28 +01:00
|
|
|
$invite_message,
|
2013-06-16 19:15:16 +02:00
|
|
|
$out,
|
|
|
|
),
|
|
|
|
array(
|
|
|
|
'title' => pht('Login to Phabricator'),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private function processAjaxRequest() {
|
|
|
|
$request = $this->getRequest();
|
2013-06-19 10:33:27 +02:00
|
|
|
$viewer = $request->getUser();
|
2013-06-16 19:15:16 +02:00
|
|
|
|
|
|
|
// We end up here if the user clicks a workflow link that they need to
|
|
|
|
// login to use. We give them a dialog saying "You need to login...".
|
|
|
|
|
|
|
|
if ($request->isDialogFormPost()) {
|
|
|
|
return id(new AphrontRedirectResponse())->setURI(
|
|
|
|
$request->getRequestURI());
|
|
|
|
}
|
|
|
|
|
When logged-out users hit a "Login Required" dialog, try to choose a better "next" URI
Summary:
Ref T10004. After a user logs in, we send them to the "next" URI cookie if there is one, but currently don't always do a very good job of selecting a "next" URI, especially if they tried to do something with a dialog before being asked to log in.
In particular, if a logged-out user clicks an action like "Edit Blocking Tasks" on a Maniphest task, the default behavior is to send them to the standalone page for that dialog after they log in. This can be pretty confusing.
See T2691 and D6416 for earlier efforts here. At that time, we added a mechanism to //manually// override the default behavior, and fixed the most common links. This worked, but I'd like to fix the //default// beahvior so we don't need to remember to `setObjectURI()` correctly all over the place.
ApplicationEditor has also introduced new cases which are more difficult to get right. While we could get them right by using the override and being careful about things, this also motivates fixing the default behavior.
Finally, we have better tools for fixing the default behavior now than we did in 2013.
Instead of using manual overrides, have JS include an "X-Phabricator-Via" header in Ajax requests. This is basically like a referrer header, and will contain the page the user's browser is on.
In essentially every case, this should be a very good place (and often the best place) to send them after login. For all pages currently using `setObjectURI()`, it should produce the same behavior by default.
I'll remove the `setObjectURI()` mechanism in the next diff.
Test Plan: Clicked various workflow actions while logged out, saw "next" get set to a reasonable value, was redirected to a sensible, non-confusing page after login (the page with whatever button I clicked on it).
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T10004
Differential Revision: https://secure.phabricator.com/D14804
2015-12-17 15:10:04 +01:00
|
|
|
// Often, users end up here by clicking a disabled action link in the UI
|
|
|
|
// (for example, they might click "Edit Blocking Tasks" on a Maniphest
|
|
|
|
// task page). After they log in we want to send them back to that main
|
|
|
|
// object page if we can, since it's confusing to end up on a standalone
|
|
|
|
// page with only a dialog (particularly if that dialog is another error,
|
|
|
|
// like a policy exception).
|
|
|
|
|
|
|
|
$via_header = AphrontRequest::getViaHeaderName();
|
|
|
|
$via_uri = AphrontRequest::getHTTPHeader($via_header);
|
|
|
|
if (strlen($via_uri)) {
|
|
|
|
PhabricatorCookies::setNextURICookie($request, $via_uri, $force = true);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->newDialog()
|
|
|
|
->setTitle(pht('Login Required'))
|
|
|
|
->appendParagraph(pht('You must login to continue.'))
|
|
|
|
->addSubmitButton(pht('Login'))
|
|
|
|
->addCancelButton('/');
|
2013-06-16 19:15:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private function processConduitRequest() {
|
|
|
|
$request = $this->getRequest();
|
2013-06-19 10:33:27 +02:00
|
|
|
$viewer = $request->getUser();
|
2013-06-16 19:15:16 +02:00
|
|
|
|
|
|
|
// A common source of errors in Conduit client configuration is getting
|
|
|
|
// the request path wrong. The client will end up here, so make some
|
|
|
|
// effort to give them a comprehensible error message.
|
|
|
|
|
|
|
|
$request_path = $this->getRequest()->getPath();
|
|
|
|
$conduit_path = '/api/<method>';
|
|
|
|
$example_path = '/api/conduit.ping';
|
|
|
|
|
|
|
|
$message = pht(
|
|
|
|
'ERROR: You are making a Conduit API request to "%s", but the correct '.
|
|
|
|
'HTTP request path to use in order to access a COnduit method is "%s" '.
|
|
|
|
'(for example, "%s"). Check your configuration.',
|
|
|
|
$request_path,
|
|
|
|
$conduit_path,
|
|
|
|
$example_path);
|
|
|
|
|
|
|
|
return id(new AphrontPlainTextResponse())->setContent($message);
|
|
|
|
}
|
|
|
|
|
2013-06-17 01:35:36 +02:00
|
|
|
protected function renderError($message) {
|
2013-06-16 19:15:33 +02:00
|
|
|
return $this->renderErrorPage(
|
|
|
|
pht('Authentication Failure'),
|
|
|
|
array($message));
|
2013-06-16 19:15:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|