@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhabricatorAuthFinishController
4 extends PhabricatorAuthController {
5
6 public function shouldRequireLogin() {
7 return false;
8 }
9
10 public function shouldAllowPartialSessions() {
11 return true;
12 }
13
14 public function shouldAllowLegallyNonCompliantUsers() {
15 return true;
16 }
17
18 public function handleRequest(AphrontRequest $request) {
19 $viewer = $this->getViewer();
20
21 // If the user already has a full session, just kick them out of here.
22 $has_partial_session = $viewer->hasSession() &&
23 $viewer->getSession()->getIsPartial();
24 if (!$has_partial_session) {
25 return id(new AphrontRedirectResponse())->setURI('/');
26 }
27
28 $engine = new PhabricatorAuthSessionEngine();
29
30 // If this cookie is set, the user is headed into a high security area
31 // after login (normally because of a password reset) so if they are
32 // able to pass the checkpoint we just want to put their account directly
33 // into high security mode, rather than prompt them again for the same
34 // set of credentials.
35 $jump_into_hisec = $request->getCookie(PhabricatorCookies::COOKIE_HISEC);
36
37 try {
38 $token = $engine->requireHighSecuritySession(
39 $viewer,
40 $request,
41 '/logout/',
42 $jump_into_hisec);
43 } catch (PhabricatorAuthHighSecurityRequiredException $ex) {
44 $form = id(new PhabricatorAuthSessionEngine())->renderHighSecurityForm(
45 $ex->getFactors(),
46 $ex->getFactorValidationResults(),
47 $viewer,
48 $request);
49
50 return $this->newDialog()
51 ->setTitle(pht('Provide Multi-Factor Credentials'))
52 ->setShortTitle(pht('Multi-Factor Login'))
53 ->setWidth(AphrontDialogView::WIDTH_FORM)
54 ->addHiddenInput(AphrontRequest::TYPE_HISEC, true)
55 ->appendParagraph(
56 pht(
57 'Welcome, %s. To complete the process of logging in, provide your '.
58 'multi-factor credentials.',
59 phutil_tag('strong', array(), $viewer->getUsername())))
60 ->appendChild($form->buildLayoutView())
61 ->setSubmitURI($request->getPath())
62 ->addCancelButton($ex->getCancelURI())
63 ->addSubmitButton(pht('Continue'));
64 }
65
66 // Upgrade the partial session to a full session.
67 $engine->upgradePartialSession($viewer);
68
69 // TODO: It might be nice to add options like "bind this session to my IP"
70 // here, even for accounts without multi-factor auth attached to them.
71
72 $next = PhabricatorCookies::getNextURICookie($request);
73 $request->clearCookie(PhabricatorCookies::COOKIE_NEXTURI);
74 $request->clearCookie(PhabricatorCookies::COOKIE_HISEC);
75
76 if (!PhabricatorEnv::isValidLocalURIForLink($next)) {
77 $next = '/';
78 }
79
80 return id(new AphrontRedirectResponse())->setURI($next);
81 }
82
83}