Passed
Push — dependabot/github_actions/shiv... ( d77982 )
by
unknown
24:09 queued 18:55
created
includes/Pages/UserAuth/PageForgotPassword.php 1 patch
Indentation   +209 added lines, -209 removed lines patch added patch discarded remove patch
@@ -23,213 +23,213 @@
 block discarded – undo
23 23
 
24 24
 class PageForgotPassword extends InternalPageBase
25 25
 {
26
-    /**
27
-     * Main function for this page, when no specific actions are called.
28
-     *
29
-     * This is the forgotten password reset form
30
-     * @category Security-Critical
31
-     */
32
-    protected function main()
33
-    {
34
-        if (WebRequest::wasPosted()) {
35
-            $this->validateCSRFToken();
36
-            $username = WebRequest::postString('username');
37
-            $email = WebRequest::postEmail('email');
38
-            $database = $this->getDatabase();
39
-
40
-            if ($username === null || trim($username) === "" || $email === null || trim($email) === "") {
41
-                throw new ApplicationLogicException("Both username and email address must be specified!");
42
-            }
43
-
44
-            $user = User::getByUsername($username, $database);
45
-            $this->sendResetMail($user, $email);
46
-
47
-            SessionAlert::success('<strong>Your password reset request has been completed.</strong> If the details you have provided match our records, you should receive an email shortly.');
48
-
49
-            $this->redirect('login');
50
-        }
51
-        else {
52
-            $this->assignCSRFToken();
53
-            $this->setTemplate('forgot-password/forgotpw.tpl');
54
-        }
55
-    }
56
-
57
-    /**
58
-     * Sends a reset email if the user is authenticated
59
-     *
60
-     * @param User|boolean $user  The user located from the database, or false. Doesn't really matter, since we do the
61
-     *                            check anyway within this method and silently skip if we don't have a user.
62
-     * @param string       $email The provided email address
63
-     */
64
-    private function sendResetMail($user, $email)
65
-    {
66
-        // If the user isn't found, or the email address is wrong, skip sending the details silently.
67
-        if (!$user instanceof User) {
68
-            return;
69
-        }
70
-
71
-        if (strtolower($user->getEmail()) === strtolower($email)) {
72
-            $clientIp = $this->getXffTrustProvider()
73
-                ->getTrustedClientIp(WebRequest::remoteAddress(), WebRequest::forwardedAddress());
74
-
75
-            $this->cleanExistingTokens($user);
76
-
77
-            $hash = Base32::encodeUpper(openssl_random_pseudo_bytes(30));
78
-
79
-            $encryptionHelper = new EncryptionHelper($this->getSiteConfiguration());
80
-
81
-            $cred = new Credential();
82
-            $cred->setDatabase($this->getDatabase());
83
-            $cred->setFactor(-1);
84
-            $cred->setUserId($user->getId());
85
-            $cred->setType('reset');
86
-            $cred->setData($encryptionHelper->encryptData($hash));
87
-            $cred->setVersion(0);
88
-            $cred->setDisabled(0);
89
-            $cred->setTimeout(new DateTimeImmutable('+ 1 hour'));
90
-            $cred->setPriority(9);
91
-            $cred->save();
92
-
93
-            $this->assign("user", $user);
94
-            $this->assign("hash", $hash);
95
-            $this->assign("remoteAddress", $clientIp);
96
-
97
-            $emailContent = $this->fetchTemplate('forgot-password/reset-mail.tpl');
98
-
99
-            // FIXME: domains!
100
-            /** @var Domain $domain */
101
-            $domain = Domain::getById(1, $this->getDatabase());
102
-            $this->getEmailHelper()->sendMail(
103
-                null, $user->getEmail(), "WP:ACC password reset", $emailContent);
104
-        }
105
-    }
106
-
107
-    /**
108
-     * Entry point for the reset action
109
-     *
110
-     * This is the reset password part of the form.
111
-     * @category Security-Critical
112
-     */
113
-    protected function reset()
114
-    {
115
-        $si = WebRequest::getString('si');
116
-        $id = WebRequest::getString('id');
117
-
118
-        if ($si === null || trim($si) === "" || $id === null || trim($id) === "") {
119
-            throw new ApplicationLogicException("Link not valid, please ensure it has copied correctly");
120
-        }
121
-
122
-        $database = $this->getDatabase();
123
-        $user = $this->getResettingUser($id, $database, $si);
124
-
125
-        // Dual mode
126
-        if (WebRequest::wasPosted()) {
127
-            $this->validateCSRFToken();
128
-            try {
129
-                $this->doReset($user);
130
-                $this->cleanExistingTokens($user);
131
-            }
132
-            catch (ApplicationLogicException $ex) {
133
-                SessionAlert::error($ex->getMessage());
134
-                $this->redirect('forgotPassword', 'reset', array('si' => $si, 'id' => $id));
135
-
136
-                return;
137
-            }
138
-        }
139
-        else {
140
-            $this->assignCSRFToken();
141
-            $this->assign('user', $user);
142
-            $this->setTemplate('forgot-password/forgotpwreset.tpl');
143
-            $this->addJs("/vendor/dropbox/zxcvbn/dist/zxcvbn.js");
144
-        }
145
-    }
146
-
147
-    /**
148
-     * Gets the user resetting their password from the database, or throwing an exception if that is not possible.
149
-     *
150
-     * @param integer     $id       The ID of the user to retrieve
151
-     * @param PdoDatabase $database The database object to use
152
-     * @param string      $si       The reset hash provided
153
-     *
154
-     * @return User
155
-     * @throws ApplicationLogicException
156
-     */
157
-    private function getResettingUser($id, $database, $si)
158
-    {
159
-        $user = User::getById($id, $database);
160
-
161
-        if ($user === false || $user->isCommunityUser()) {
162
-            throw new ApplicationLogicException("Password reset failed. Please try again.");
163
-        }
164
-
165
-        $statement = $database->prepare("SELECT * FROM credential WHERE type = 'reset' AND user = :user;");
166
-        $statement->execute([':user' => $user->getId()]);
167
-
168
-        /** @var Credential $credential */
169
-        $credential = $statement->fetchObject(Credential::class);
170
-
171
-        $statement->closeCursor();
172
-
173
-        if ($credential === false) {
174
-            throw new ApplicationLogicException("Password reset failed. Please try again.");
175
-        }
176
-
177
-        $credential->setDatabase($database);
178
-
179
-        $encryptionHelper = new EncryptionHelper($this->getSiteConfiguration());
180
-        if ($encryptionHelper->decryptData($credential->getData()) != $si) {
181
-            throw new ApplicationLogicException("Password reset failed. Please try again.");
182
-        }
183
-
184
-        if ($credential->getTimeout() < new DateTimeImmutable()) {
185
-            $credential->delete();
186
-            throw new ApplicationLogicException("Password reset token expired. Please try again.");
187
-        }
188
-
189
-        return $user;
190
-    }
191
-
192
-    /**
193
-     * Performs the setting of the new password
194
-     *
195
-     * @param User $user The user to set the password for
196
-     *
197
-     * @throws ApplicationLogicException
198
-     */
199
-    private function doReset(User $user)
200
-    {
201
-        $pw = WebRequest::postString('newpassword');
202
-        $pw2 = WebRequest::postString('newpasswordconfirm');
203
-
204
-        if ($pw !== $pw2) {
205
-            throw new ApplicationLogicException('Passwords do not match!');
206
-        }
207
-
208
-        $passwordCredentialProvider = new PasswordCredentialProvider($user->getDatabase(), $this->getSiteConfiguration());
209
-        $passwordCredentialProvider->setCredential($user, 1, $pw);
210
-
211
-        SessionAlert::success('You may now log in!');
212
-        $this->redirect('login');
213
-    }
214
-
215
-    protected function isProtectedPage()
216
-    {
217
-        return false;
218
-    }
219
-
220
-    /**
221
-     * @param $user
222
-     */
223
-    private function cleanExistingTokens($user): void
224
-    {
225
-        // clean out existing reset tokens
226
-        $statement = $this->getDatabase()->prepare("SELECT * FROM credential WHERE type = 'reset' AND user = :user;");
227
-        $statement->execute([':user' => $user->getId()]);
228
-        $existing = $statement->fetchAll(PdoDatabase::FETCH_CLASS, Credential::class);
229
-
230
-        foreach ($existing as $c) {
231
-            $c->setDatabase($this->getDatabase());
232
-            $c->delete();
233
-        }
234
-    }
26
+	/**
27
+	 * Main function for this page, when no specific actions are called.
28
+	 *
29
+	 * This is the forgotten password reset form
30
+	 * @category Security-Critical
31
+	 */
32
+	protected function main()
33
+	{
34
+		if (WebRequest::wasPosted()) {
35
+			$this->validateCSRFToken();
36
+			$username = WebRequest::postString('username');
37
+			$email = WebRequest::postEmail('email');
38
+			$database = $this->getDatabase();
39
+
40
+			if ($username === null || trim($username) === "" || $email === null || trim($email) === "") {
41
+				throw new ApplicationLogicException("Both username and email address must be specified!");
42
+			}
43
+
44
+			$user = User::getByUsername($username, $database);
45
+			$this->sendResetMail($user, $email);
46
+
47
+			SessionAlert::success('<strong>Your password reset request has been completed.</strong> If the details you have provided match our records, you should receive an email shortly.');
48
+
49
+			$this->redirect('login');
50
+		}
51
+		else {
52
+			$this->assignCSRFToken();
53
+			$this->setTemplate('forgot-password/forgotpw.tpl');
54
+		}
55
+	}
56
+
57
+	/**
58
+	 * Sends a reset email if the user is authenticated
59
+	 *
60
+	 * @param User|boolean $user  The user located from the database, or false. Doesn't really matter, since we do the
61
+	 *                            check anyway within this method and silently skip if we don't have a user.
62
+	 * @param string       $email The provided email address
63
+	 */
64
+	private function sendResetMail($user, $email)
65
+	{
66
+		// If the user isn't found, or the email address is wrong, skip sending the details silently.
67
+		if (!$user instanceof User) {
68
+			return;
69
+		}
70
+
71
+		if (strtolower($user->getEmail()) === strtolower($email)) {
72
+			$clientIp = $this->getXffTrustProvider()
73
+				->getTrustedClientIp(WebRequest::remoteAddress(), WebRequest::forwardedAddress());
74
+
75
+			$this->cleanExistingTokens($user);
76
+
77
+			$hash = Base32::encodeUpper(openssl_random_pseudo_bytes(30));
78
+
79
+			$encryptionHelper = new EncryptionHelper($this->getSiteConfiguration());
80
+
81
+			$cred = new Credential();
82
+			$cred->setDatabase($this->getDatabase());
83
+			$cred->setFactor(-1);
84
+			$cred->setUserId($user->getId());
85
+			$cred->setType('reset');
86
+			$cred->setData($encryptionHelper->encryptData($hash));
87
+			$cred->setVersion(0);
88
+			$cred->setDisabled(0);
89
+			$cred->setTimeout(new DateTimeImmutable('+ 1 hour'));
90
+			$cred->setPriority(9);
91
+			$cred->save();
92
+
93
+			$this->assign("user", $user);
94
+			$this->assign("hash", $hash);
95
+			$this->assign("remoteAddress", $clientIp);
96
+
97
+			$emailContent = $this->fetchTemplate('forgot-password/reset-mail.tpl');
98
+
99
+			// FIXME: domains!
100
+			/** @var Domain $domain */
101
+			$domain = Domain::getById(1, $this->getDatabase());
102
+			$this->getEmailHelper()->sendMail(
103
+				null, $user->getEmail(), "WP:ACC password reset", $emailContent);
104
+		}
105
+	}
106
+
107
+	/**
108
+	 * Entry point for the reset action
109
+	 *
110
+	 * This is the reset password part of the form.
111
+	 * @category Security-Critical
112
+	 */
113
+	protected function reset()
114
+	{
115
+		$si = WebRequest::getString('si');
116
+		$id = WebRequest::getString('id');
117
+
118
+		if ($si === null || trim($si) === "" || $id === null || trim($id) === "") {
119
+			throw new ApplicationLogicException("Link not valid, please ensure it has copied correctly");
120
+		}
121
+
122
+		$database = $this->getDatabase();
123
+		$user = $this->getResettingUser($id, $database, $si);
124
+
125
+		// Dual mode
126
+		if (WebRequest::wasPosted()) {
127
+			$this->validateCSRFToken();
128
+			try {
129
+				$this->doReset($user);
130
+				$this->cleanExistingTokens($user);
131
+			}
132
+			catch (ApplicationLogicException $ex) {
133
+				SessionAlert::error($ex->getMessage());
134
+				$this->redirect('forgotPassword', 'reset', array('si' => $si, 'id' => $id));
135
+
136
+				return;
137
+			}
138
+		}
139
+		else {
140
+			$this->assignCSRFToken();
141
+			$this->assign('user', $user);
142
+			$this->setTemplate('forgot-password/forgotpwreset.tpl');
143
+			$this->addJs("/vendor/dropbox/zxcvbn/dist/zxcvbn.js");
144
+		}
145
+	}
146
+
147
+	/**
148
+	 * Gets the user resetting their password from the database, or throwing an exception if that is not possible.
149
+	 *
150
+	 * @param integer     $id       The ID of the user to retrieve
151
+	 * @param PdoDatabase $database The database object to use
152
+	 * @param string      $si       The reset hash provided
153
+	 *
154
+	 * @return User
155
+	 * @throws ApplicationLogicException
156
+	 */
157
+	private function getResettingUser($id, $database, $si)
158
+	{
159
+		$user = User::getById($id, $database);
160
+
161
+		if ($user === false || $user->isCommunityUser()) {
162
+			throw new ApplicationLogicException("Password reset failed. Please try again.");
163
+		}
164
+
165
+		$statement = $database->prepare("SELECT * FROM credential WHERE type = 'reset' AND user = :user;");
166
+		$statement->execute([':user' => $user->getId()]);
167
+
168
+		/** @var Credential $credential */
169
+		$credential = $statement->fetchObject(Credential::class);
170
+
171
+		$statement->closeCursor();
172
+
173
+		if ($credential === false) {
174
+			throw new ApplicationLogicException("Password reset failed. Please try again.");
175
+		}
176
+
177
+		$credential->setDatabase($database);
178
+
179
+		$encryptionHelper = new EncryptionHelper($this->getSiteConfiguration());
180
+		if ($encryptionHelper->decryptData($credential->getData()) != $si) {
181
+			throw new ApplicationLogicException("Password reset failed. Please try again.");
182
+		}
183
+
184
+		if ($credential->getTimeout() < new DateTimeImmutable()) {
185
+			$credential->delete();
186
+			throw new ApplicationLogicException("Password reset token expired. Please try again.");
187
+		}
188
+
189
+		return $user;
190
+	}
191
+
192
+	/**
193
+	 * Performs the setting of the new password
194
+	 *
195
+	 * @param User $user The user to set the password for
196
+	 *
197
+	 * @throws ApplicationLogicException
198
+	 */
199
+	private function doReset(User $user)
200
+	{
201
+		$pw = WebRequest::postString('newpassword');
202
+		$pw2 = WebRequest::postString('newpasswordconfirm');
203
+
204
+		if ($pw !== $pw2) {
205
+			throw new ApplicationLogicException('Passwords do not match!');
206
+		}
207
+
208
+		$passwordCredentialProvider = new PasswordCredentialProvider($user->getDatabase(), $this->getSiteConfiguration());
209
+		$passwordCredentialProvider->setCredential($user, 1, $pw);
210
+
211
+		SessionAlert::success('You may now log in!');
212
+		$this->redirect('login');
213
+	}
214
+
215
+	protected function isProtectedPage()
216
+	{
217
+		return false;
218
+	}
219
+
220
+	/**
221
+	 * @param $user
222
+	 */
223
+	private function cleanExistingTokens($user): void
224
+	{
225
+		// clean out existing reset tokens
226
+		$statement = $this->getDatabase()->prepare("SELECT * FROM credential WHERE type = 'reset' AND user = :user;");
227
+		$statement->execute([':user' => $user->getId()]);
228
+		$existing = $statement->fetchAll(PdoDatabase::FETCH_CLASS, Credential::class);
229
+
230
+		foreach ($existing as $c) {
231
+			$c->setDatabase($this->getDatabase());
232
+			$c->delete();
233
+		}
234
+	}
235 235
 }
Please login to merge, or discard this patch.
includes/Pages/UserAuth/Login/PagePasswordLogin.php 1 patch
Indentation   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -13,31 +13,31 @@
 block discarded – undo
13 13
 
14 14
 class PagePasswordLogin extends LoginCredentialPageBase
15 15
 {
16
-    protected function providerSpecificSetup()
17
-    {
18
-        list($partialId, $partialStage) = WebRequest::getAuthPartialLogin();
19
-
20
-        if ($partialId !== null && $partialStage > 1) {
21
-            $sql = 'SELECT type FROM credential WHERE user = :user AND factor = :stage AND disabled = 0 ORDER BY priority';
22
-            $statement = $this->getDatabase()->prepare($sql);
23
-            $statement->execute(array(':user' => $partialId, ':stage' => $partialStage));
24
-            $nextStage = $statement->fetchColumn();
25
-            $statement->closeCursor();
26
-
27
-            $this->redirect("login/" . $this->nextPageMap[$nextStage]);
28
-            return;
29
-        }
30
-
31
-        $this->setTemplate('login/password.tpl');
32
-    }
33
-
34
-    protected function getProviderCredentials()
35
-    {
36
-        $password = WebRequest::postString("password");
37
-        if ($password === null || $password === "") {
38
-            throw new ApplicationLogicException("No password specified");
39
-        }
40
-
41
-        return $password;
42
-    }
16
+	protected function providerSpecificSetup()
17
+	{
18
+		list($partialId, $partialStage) = WebRequest::getAuthPartialLogin();
19
+
20
+		if ($partialId !== null && $partialStage > 1) {
21
+			$sql = 'SELECT type FROM credential WHERE user = :user AND factor = :stage AND disabled = 0 ORDER BY priority';
22
+			$statement = $this->getDatabase()->prepare($sql);
23
+			$statement->execute(array(':user' => $partialId, ':stage' => $partialStage));
24
+			$nextStage = $statement->fetchColumn();
25
+			$statement->closeCursor();
26
+
27
+			$this->redirect("login/" . $this->nextPageMap[$nextStage]);
28
+			return;
29
+		}
30
+
31
+		$this->setTemplate('login/password.tpl');
32
+	}
33
+
34
+	protected function getProviderCredentials()
35
+	{
36
+		$password = WebRequest::postString("password");
37
+		if ($password === null || $password === "") {
38
+			throw new ApplicationLogicException("No password specified");
39
+		}
40
+
41
+		return $password;
42
+	}
43 43
 }
44 44
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Pages/UserAuth/Login/LoginCredentialPageBase.php 1 patch
Indentation   +306 added lines, -306 removed lines patch added patch discarded remove patch
@@ -21,310 +21,310 @@
 block discarded – undo
21 21
 
22 22
 abstract class LoginCredentialPageBase extends InternalPageBase
23 23
 {
24
-    /** @var User */
25
-    protected $partialUser = null;
26
-    protected $nextPageMap = array(
27
-        'yubikeyotp' => 'otp',
28
-        'totp'       => 'otp',
29
-        'scratch'    => 'otp',
30
-    );
31
-    protected $names = array(
32
-        'yubikeyotp' => 'Yubikey OTP',
33
-        'totp'       => 'TOTP (phone code generator)',
34
-        'scratch'    => 'scratch token',
35
-    );
36
-
37
-    /**
38
-     * Main function for this page, when no specific actions are called.
39
-     * @return void
40
-     */
41
-    protected function main()
42
-    {
43
-        if (!$this->enforceHttps()) {
44
-            return;
45
-        }
46
-
47
-        if (WebRequest::wasPosted()) {
48
-            $this->validateCSRFToken();
49
-
50
-            $database = $this->getDatabase();
51
-            try {
52
-                list($partialId, $partialStage) = WebRequest::getAuthPartialLogin();
53
-
54
-                if ($partialStage === null) {
55
-                    $partialStage = 1;
56
-                }
57
-
58
-                if ($partialId === null) {
59
-                    $username = WebRequest::postString('username');
60
-
61
-                    if ($username === null || trim($username) === '') {
62
-                        throw new ApplicationLogicException('No username specified.');
63
-                    }
64
-
65
-                    $user = User::getByUsername($username, $database);
66
-                }
67
-                else {
68
-                    $user = User::getById($partialId, $database);
69
-                }
70
-
71
-                if ($user === false) {
72
-                    throw new ApplicationLogicException("Authentication failed");
73
-                }
74
-
75
-                $authMan = new AuthenticationManager($database, $this->getSiteConfiguration(),
76
-                    $this->getHttpHelper());
77
-
78
-                $credential = $this->getProviderCredentials();
79
-
80
-                $authResult = $authMan->authenticate($user, $credential, $partialStage);
81
-
82
-                if ($authResult === AuthenticationManager::AUTH_FAIL) {
83
-                    throw new ApplicationLogicException("Authentication failed");
84
-                }
85
-
86
-                if ($authResult === AuthenticationManager::AUTH_REQUIRE_NEXT_STAGE) {
87
-                    $this->processJumpNextStage($user, $partialStage, $database);
88
-
89
-                    return;
90
-                }
91
-
92
-                if ($authResult === AuthenticationManager::AUTH_OK) {
93
-                    $this->processLoginSuccess($user);
94
-
95
-                    return;
96
-                }
97
-            }
98
-            catch (ApplicationLogicException $ex) {
99
-                WebRequest::clearAuthPartialLogin();
100
-
101
-                SessionAlert::error($ex->getMessage());
102
-                $this->redirect('login');
103
-
104
-                return;
105
-            }
106
-        }
107
-        else {
108
-            $this->assign('showSignIn', true);
109
-
110
-            $this->setupPartial();
111
-            $this->assignCSRFToken();
112
-            $this->providerSpecificSetup();
113
-        }
114
-    }
115
-
116
-    protected function isProtectedPage()
117
-    {
118
-        return false;
119
-    }
120
-
121
-    /**
122
-     * Enforces HTTPS on the login form
123
-     *
124
-     * @return bool
125
-     */
126
-    private function enforceHttps()
127
-    {
128
-        if ($this->getSiteConfiguration()->getUseStrictTransportSecurity() !== false) {
129
-            if (WebRequest::isHttps()) {
130
-                // Client can clearly use HTTPS, so let's enforce it for all connections.
131
-                $this->headerQueue[] = "Strict-Transport-Security: max-age=15768000";
132
-            }
133
-            else {
134
-                // This is the login form, not the request form. We need protection here.
135
-                $this->redirectUrl('https://' . WebRequest::serverName() . WebRequest::requestUri());
136
-
137
-                return false;
138
-            }
139
-        }
140
-
141
-        return true;
142
-    }
143
-
144
-    protected abstract function providerSpecificSetup();
145
-
146
-    protected function setupPartial()
147
-    {
148
-        $database = $this->getDatabase();
149
-
150
-        // default stuff
151
-        $this->assign('alternatives', array()); // 'u2f' => array('U2F token'), 'otp' => array('TOTP', 'scratch', 'yubiotp')));
152
-
153
-        // is this stage one?
154
-        list($partialId, $partialStage) = WebRequest::getAuthPartialLogin();
155
-        if ($partialStage === null || $partialId === null) {
156
-            WebRequest::clearAuthPartialLogin();
157
-        }
158
-
159
-        // Check to see if we have a partial login in progress
160
-        $username = null;
161
-        if ($partialId !== null) {
162
-            // Yes, enforce this username
163
-            $this->partialUser = User::getById($partialId, $database);
164
-            $username = $this->partialUser->getUsername();
165
-
166
-            $this->setupAlternates($this->partialUser, $partialStage, $database);
167
-        }
168
-        else {
169
-            // No, see if we've preloaded a username
170
-            $preloadUsername = WebRequest::getString('tplUsername');
171
-            if ($preloadUsername !== null) {
172
-                $username = $preloadUsername;
173
-            }
174
-        }
175
-
176
-        if ($partialStage === null) {
177
-            $partialStage = 1;
178
-        }
179
-
180
-        $this->assign('partialStage', $partialStage);
181
-        $this->assign('username', $username);
182
-    }
183
-
184
-    /**
185
-     * Redirect the user back to wherever they came from after a successful login
186
-     *
187
-     * @param User $user
188
-     */
189
-    protected function goBackWhenceYouCame(User $user)
190
-    {
191
-        // Redirect to wherever the user came from
192
-        $redirectDestination = WebRequest::clearPostLoginRedirect();
193
-        if ($redirectDestination !== null) {
194
-            $this->redirectUrl($redirectDestination);
195
-        }
196
-        else {
197
-            if ($user->isNewUser()) {
198
-                // home page isn't allowed, go to preferences instead
199
-                $this->redirect('preferences');
200
-            }
201
-            else {
202
-                // go to the home page
203
-                $this->redirect('');
204
-            }
205
-        }
206
-    }
207
-
208
-    private function processLoginSuccess(User $user)
209
-    {
210
-        // Touch force logout
211
-        $user->setForceLogout(false);
212
-        $user->save();
213
-
214
-        $oauth = new OAuthUserHelper($user, $this->getDatabase(), $this->getOAuthProtocolHelper(),
215
-            $this->getSiteConfiguration());
216
-
217
-        if ($oauth->isFullyLinked()) {
218
-            try {
219
-                // Reload the user's identity ticket.
220
-                $oauth->refreshIdentity();
221
-
222
-                // Check for blocks
223
-                if ($oauth->getIdentity()->getBlocked()) {
224
-                    // blocked!
225
-                    SessionAlert::error("You are currently blocked on-wiki. You will not be able to log in until you are unblocked.");
226
-                    $this->redirect('login');
227
-
228
-                    return;
229
-                }
230
-            }
231
-            catch (OAuthException $ex) {
232
-                // Oops. Refreshing ticket failed. Force a re-auth.
233
-                $authoriseUrl = $oauth->getRequestToken();
234
-                WebRequest::setOAuthPartialLogin($user);
235
-                $this->redirectUrl($authoriseUrl);
236
-
237
-                return;
238
-            }
239
-        }
240
-
241
-        if (($this->getSiteConfiguration()->getEnforceOAuth() && !$oauth->isFullyLinked())
242
-            || $oauth->isPartiallyLinked()
243
-        ) {
244
-            $authoriseUrl = $oauth->getRequestToken();
245
-            WebRequest::setOAuthPartialLogin($user);
246
-            $this->redirectUrl($authoriseUrl);
247
-
248
-            return;
249
-        }
250
-
251
-        WebRequest::setLoggedInUser($user);
252
-        $this->getDomainAccessManager()->switchToDefaultDomain($user);
253
-
254
-        $this->goBackWhenceYouCame($user);
255
-    }
256
-
257
-    protected abstract function getProviderCredentials();
258
-
259
-    /**
260
-     * @param User        $user
261
-     * @param int         $partialStage
262
-     * @param PdoDatabase $database
263
-     *
264
-     * @throws ApplicationLogicException
265
-     */
266
-    private function processJumpNextStage(User $user, $partialStage, PdoDatabase $database)
267
-    {
268
-        WebRequest::setAuthPartialLogin($user->getId(), $partialStage + 1);
269
-
270
-        $sql = 'SELECT type FROM credential WHERE user = :user AND factor = :stage AND disabled = 0 ORDER BY priority';
271
-        $statement = $database->prepare($sql);
272
-        $statement->execute(array(':user' => $user->getId(), ':stage' => $partialStage + 1));
273
-        $nextStage = $statement->fetchColumn();
274
-        $statement->closeCursor();
275
-
276
-        if (!isset($this->nextPageMap[$nextStage])) {
277
-            throw new ApplicationLogicException('Unknown page handler for next authentication stage.');
278
-        }
279
-
280
-        $this->redirect("login/" . $this->nextPageMap[$nextStage]);
281
-    }
282
-
283
-    private function setupAlternates(User $user, $partialStage, PdoDatabase $database)
284
-    {
285
-        // get the providers available
286
-        $sql = 'SELECT type FROM credential WHERE user = :user AND factor = :stage AND disabled = 0';
287
-        $statement = $database->prepare($sql);
288
-        $statement->execute(array(':user' => $user->getId(), ':stage' => $partialStage));
289
-        $alternates = $statement->fetchAll(PDO::FETCH_COLUMN);
290
-
291
-        $types = array();
292
-        foreach ($alternates as $item) {
293
-            $type = $this->nextPageMap[$item];
294
-            if (!isset($types[$type])) {
295
-                $types[$type] = array();
296
-            }
297
-
298
-            $types[$type][] = $item;
299
-        }
300
-
301
-        $userOptions = array();
302
-        if (get_called_class() !== PageOtpLogin::class) {
303
-            $userOptions = array_merge($userOptions, $this->setupUserOptionsForType($types, 'otp', $userOptions));
304
-        }
305
-
306
-        $this->assign('alternatives', $userOptions);
307
-    }
308
-
309
-    /**
310
-     * @param $types
311
-     * @param $type
312
-     * @param $userOptions
313
-     *
314
-     * @return mixed
315
-     */
316
-    private function setupUserOptionsForType($types, $type, $userOptions)
317
-    {
318
-        if (isset($types[$type])) {
319
-            $options = $types[$type];
320
-
321
-            array_walk($options, function(&$val) {
322
-                $val = $this->names[$val];
323
-            });
324
-
325
-            $userOptions[$type] = $options;
326
-        }
327
-
328
-        return $userOptions;
329
-    }
24
+	/** @var User */
25
+	protected $partialUser = null;
26
+	protected $nextPageMap = array(
27
+		'yubikeyotp' => 'otp',
28
+		'totp'       => 'otp',
29
+		'scratch'    => 'otp',
30
+	);
31
+	protected $names = array(
32
+		'yubikeyotp' => 'Yubikey OTP',
33
+		'totp'       => 'TOTP (phone code generator)',
34
+		'scratch'    => 'scratch token',
35
+	);
36
+
37
+	/**
38
+	 * Main function for this page, when no specific actions are called.
39
+	 * @return void
40
+	 */
41
+	protected function main()
42
+	{
43
+		if (!$this->enforceHttps()) {
44
+			return;
45
+		}
46
+
47
+		if (WebRequest::wasPosted()) {
48
+			$this->validateCSRFToken();
49
+
50
+			$database = $this->getDatabase();
51
+			try {
52
+				list($partialId, $partialStage) = WebRequest::getAuthPartialLogin();
53
+
54
+				if ($partialStage === null) {
55
+					$partialStage = 1;
56
+				}
57
+
58
+				if ($partialId === null) {
59
+					$username = WebRequest::postString('username');
60
+
61
+					if ($username === null || trim($username) === '') {
62
+						throw new ApplicationLogicException('No username specified.');
63
+					}
64
+
65
+					$user = User::getByUsername($username, $database);
66
+				}
67
+				else {
68
+					$user = User::getById($partialId, $database);
69
+				}
70
+
71
+				if ($user === false) {
72
+					throw new ApplicationLogicException("Authentication failed");
73
+				}
74
+
75
+				$authMan = new AuthenticationManager($database, $this->getSiteConfiguration(),
76
+					$this->getHttpHelper());
77
+
78
+				$credential = $this->getProviderCredentials();
79
+
80
+				$authResult = $authMan->authenticate($user, $credential, $partialStage);
81
+
82
+				if ($authResult === AuthenticationManager::AUTH_FAIL) {
83
+					throw new ApplicationLogicException("Authentication failed");
84
+				}
85
+
86
+				if ($authResult === AuthenticationManager::AUTH_REQUIRE_NEXT_STAGE) {
87
+					$this->processJumpNextStage($user, $partialStage, $database);
88
+
89
+					return;
90
+				}
91
+
92
+				if ($authResult === AuthenticationManager::AUTH_OK) {
93
+					$this->processLoginSuccess($user);
94
+
95
+					return;
96
+				}
97
+			}
98
+			catch (ApplicationLogicException $ex) {
99
+				WebRequest::clearAuthPartialLogin();
100
+
101
+				SessionAlert::error($ex->getMessage());
102
+				$this->redirect('login');
103
+
104
+				return;
105
+			}
106
+		}
107
+		else {
108
+			$this->assign('showSignIn', true);
109
+
110
+			$this->setupPartial();
111
+			$this->assignCSRFToken();
112
+			$this->providerSpecificSetup();
113
+		}
114
+	}
115
+
116
+	protected function isProtectedPage()
117
+	{
118
+		return false;
119
+	}
120
+
121
+	/**
122
+	 * Enforces HTTPS on the login form
123
+	 *
124
+	 * @return bool
125
+	 */
126
+	private function enforceHttps()
127
+	{
128
+		if ($this->getSiteConfiguration()->getUseStrictTransportSecurity() !== false) {
129
+			if (WebRequest::isHttps()) {
130
+				// Client can clearly use HTTPS, so let's enforce it for all connections.
131
+				$this->headerQueue[] = "Strict-Transport-Security: max-age=15768000";
132
+			}
133
+			else {
134
+				// This is the login form, not the request form. We need protection here.
135
+				$this->redirectUrl('https://' . WebRequest::serverName() . WebRequest::requestUri());
136
+
137
+				return false;
138
+			}
139
+		}
140
+
141
+		return true;
142
+	}
143
+
144
+	protected abstract function providerSpecificSetup();
145
+
146
+	protected function setupPartial()
147
+	{
148
+		$database = $this->getDatabase();
149
+
150
+		// default stuff
151
+		$this->assign('alternatives', array()); // 'u2f' => array('U2F token'), 'otp' => array('TOTP', 'scratch', 'yubiotp')));
152
+
153
+		// is this stage one?
154
+		list($partialId, $partialStage) = WebRequest::getAuthPartialLogin();
155
+		if ($partialStage === null || $partialId === null) {
156
+			WebRequest::clearAuthPartialLogin();
157
+		}
158
+
159
+		// Check to see if we have a partial login in progress
160
+		$username = null;
161
+		if ($partialId !== null) {
162
+			// Yes, enforce this username
163
+			$this->partialUser = User::getById($partialId, $database);
164
+			$username = $this->partialUser->getUsername();
165
+
166
+			$this->setupAlternates($this->partialUser, $partialStage, $database);
167
+		}
168
+		else {
169
+			// No, see if we've preloaded a username
170
+			$preloadUsername = WebRequest::getString('tplUsername');
171
+			if ($preloadUsername !== null) {
172
+				$username = $preloadUsername;
173
+			}
174
+		}
175
+
176
+		if ($partialStage === null) {
177
+			$partialStage = 1;
178
+		}
179
+
180
+		$this->assign('partialStage', $partialStage);
181
+		$this->assign('username', $username);
182
+	}
183
+
184
+	/**
185
+	 * Redirect the user back to wherever they came from after a successful login
186
+	 *
187
+	 * @param User $user
188
+	 */
189
+	protected function goBackWhenceYouCame(User $user)
190
+	{
191
+		// Redirect to wherever the user came from
192
+		$redirectDestination = WebRequest::clearPostLoginRedirect();
193
+		if ($redirectDestination !== null) {
194
+			$this->redirectUrl($redirectDestination);
195
+		}
196
+		else {
197
+			if ($user->isNewUser()) {
198
+				// home page isn't allowed, go to preferences instead
199
+				$this->redirect('preferences');
200
+			}
201
+			else {
202
+				// go to the home page
203
+				$this->redirect('');
204
+			}
205
+		}
206
+	}
207
+
208
+	private function processLoginSuccess(User $user)
209
+	{
210
+		// Touch force logout
211
+		$user->setForceLogout(false);
212
+		$user->save();
213
+
214
+		$oauth = new OAuthUserHelper($user, $this->getDatabase(), $this->getOAuthProtocolHelper(),
215
+			$this->getSiteConfiguration());
216
+
217
+		if ($oauth->isFullyLinked()) {
218
+			try {
219
+				// Reload the user's identity ticket.
220
+				$oauth->refreshIdentity();
221
+
222
+				// Check for blocks
223
+				if ($oauth->getIdentity()->getBlocked()) {
224
+					// blocked!
225
+					SessionAlert::error("You are currently blocked on-wiki. You will not be able to log in until you are unblocked.");
226
+					$this->redirect('login');
227
+
228
+					return;
229
+				}
230
+			}
231
+			catch (OAuthException $ex) {
232
+				// Oops. Refreshing ticket failed. Force a re-auth.
233
+				$authoriseUrl = $oauth->getRequestToken();
234
+				WebRequest::setOAuthPartialLogin($user);
235
+				$this->redirectUrl($authoriseUrl);
236
+
237
+				return;
238
+			}
239
+		}
240
+
241
+		if (($this->getSiteConfiguration()->getEnforceOAuth() && !$oauth->isFullyLinked())
242
+			|| $oauth->isPartiallyLinked()
243
+		) {
244
+			$authoriseUrl = $oauth->getRequestToken();
245
+			WebRequest::setOAuthPartialLogin($user);
246
+			$this->redirectUrl($authoriseUrl);
247
+
248
+			return;
249
+		}
250
+
251
+		WebRequest::setLoggedInUser($user);
252
+		$this->getDomainAccessManager()->switchToDefaultDomain($user);
253
+
254
+		$this->goBackWhenceYouCame($user);
255
+	}
256
+
257
+	protected abstract function getProviderCredentials();
258
+
259
+	/**
260
+	 * @param User        $user
261
+	 * @param int         $partialStage
262
+	 * @param PdoDatabase $database
263
+	 *
264
+	 * @throws ApplicationLogicException
265
+	 */
266
+	private function processJumpNextStage(User $user, $partialStage, PdoDatabase $database)
267
+	{
268
+		WebRequest::setAuthPartialLogin($user->getId(), $partialStage + 1);
269
+
270
+		$sql = 'SELECT type FROM credential WHERE user = :user AND factor = :stage AND disabled = 0 ORDER BY priority';
271
+		$statement = $database->prepare($sql);
272
+		$statement->execute(array(':user' => $user->getId(), ':stage' => $partialStage + 1));
273
+		$nextStage = $statement->fetchColumn();
274
+		$statement->closeCursor();
275
+
276
+		if (!isset($this->nextPageMap[$nextStage])) {
277
+			throw new ApplicationLogicException('Unknown page handler for next authentication stage.');
278
+		}
279
+
280
+		$this->redirect("login/" . $this->nextPageMap[$nextStage]);
281
+	}
282
+
283
+	private function setupAlternates(User $user, $partialStage, PdoDatabase $database)
284
+	{
285
+		// get the providers available
286
+		$sql = 'SELECT type FROM credential WHERE user = :user AND factor = :stage AND disabled = 0';
287
+		$statement = $database->prepare($sql);
288
+		$statement->execute(array(':user' => $user->getId(), ':stage' => $partialStage));
289
+		$alternates = $statement->fetchAll(PDO::FETCH_COLUMN);
290
+
291
+		$types = array();
292
+		foreach ($alternates as $item) {
293
+			$type = $this->nextPageMap[$item];
294
+			if (!isset($types[$type])) {
295
+				$types[$type] = array();
296
+			}
297
+
298
+			$types[$type][] = $item;
299
+		}
300
+
301
+		$userOptions = array();
302
+		if (get_called_class() !== PageOtpLogin::class) {
303
+			$userOptions = array_merge($userOptions, $this->setupUserOptionsForType($types, 'otp', $userOptions));
304
+		}
305
+
306
+		$this->assign('alternatives', $userOptions);
307
+	}
308
+
309
+	/**
310
+	 * @param $types
311
+	 * @param $type
312
+	 * @param $userOptions
313
+	 *
314
+	 * @return mixed
315
+	 */
316
+	private function setupUserOptionsForType($types, $type, $userOptions)
317
+	{
318
+		if (isset($types[$type])) {
319
+			$options = $types[$type];
320
+
321
+			array_walk($options, function(&$val) {
322
+				$val = $this->names[$val];
323
+			});
324
+
325
+			$userOptions[$type] = $options;
326
+		}
327
+
328
+		return $userOptions;
329
+	}
330 330
 }
Please login to merge, or discard this patch.
includes/Pages/UserAuth/MultiFactor/PageMultiFactor.php 1 patch
Indentation   +293 added lines, -293 removed lines patch added patch discarded remove patch
@@ -26,297 +26,297 @@
 block discarded – undo
26 26
 
27 27
 class PageMultiFactor extends InternalPageBase
28 28
 {
29
-    /**
30
-     * Main function for this page, when no specific actions are called.
31
-     * @return void
32
-     */
33
-    protected function main()
34
-    {
35
-        $database = $this->getDatabase();
36
-        $currentUser = User::getCurrent($database);
37
-
38
-        $yubikeyOtpCredentialProvider = new YubikeyOtpCredentialProvider($database, $this->getSiteConfiguration(),
39
-            $this->getHttpHelper());
40
-        $this->assign('yubikeyOtpIdentity', $yubikeyOtpCredentialProvider->getYubikeyData($currentUser->getId()));
41
-        $this->assign('yubikeyOtpEnrolled', $yubikeyOtpCredentialProvider->userIsEnrolled($currentUser->getId()));
42
-
43
-        $totpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration());
44
-        $this->assign('totpEnrolled', $totpCredentialProvider->userIsEnrolled($currentUser->getId()));
45
-
46
-        $scratchCredentialProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
47
-        $this->assign('scratchEnrolled', $scratchCredentialProvider->userIsEnrolled($currentUser->getId()));
48
-        $this->assign('scratchRemaining', $scratchCredentialProvider->getRemaining($currentUser->getId()));
49
-
50
-        $this->assign('allowedTotp', $this->barrierTest('enableTotp', $currentUser));
51
-        $this->assign('allowedYubikey', $this->barrierTest('enableYubikeyOtp', $currentUser));
52
-
53
-        $this->setTemplate('mfa/mfa.tpl');
54
-    }
55
-
56
-    protected function enableYubikeyOtp()
57
-    {
58
-        $database = $this->getDatabase();
59
-        $currentUser = User::getCurrent($database);
60
-
61
-        $otpCredentialProvider = new YubikeyOtpCredentialProvider($database,
62
-            $this->getSiteConfiguration(), $this->getHttpHelper());
63
-
64
-        if (WebRequest::wasPosted()) {
65
-            $this->validateCSRFToken();
66
-
67
-            $passwordCredentialProvider = new PasswordCredentialProvider($database,
68
-                $this->getSiteConfiguration());
69
-
70
-            $password = WebRequest::postString('password');
71
-            $otp = WebRequest::postString('otp');
72
-
73
-            $result = $passwordCredentialProvider->authenticate($currentUser, $password);
74
-
75
-            if ($result) {
76
-                try {
77
-                    $otpCredentialProvider->setCredential($currentUser, 2, $otp);
78
-                    SessionAlert::success('Enabled YubiKey OTP.');
79
-
80
-                    $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
81
-                    if ($scratchProvider->getRemaining($currentUser->getId()) < 3) {
82
-                        $scratchProvider->setCredential($currentUser, 2, null);
83
-                        $tokens = $scratchProvider->getTokens();
84
-                        $this->assign('tokens', $tokens);
85
-                        $this->setTemplate('mfa/regenScratchTokens.tpl');
86
-                        return;
87
-                    }
88
-                }
89
-                catch (ApplicationLogicException $ex) {
90
-                    SessionAlert::error('Error enabling YubiKey OTP: ' . $ex->getMessage());
91
-                }
92
-
93
-                $this->redirect('multiFactor');
94
-            }
95
-            else {
96
-                SessionAlert::error('Error enabling YubiKey OTP - invalid credentials.');
97
-                $this->redirect('multiFactor');
98
-            }
99
-        }
100
-        else {
101
-            if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
102
-                // user is not enrolled, we shouldn't have got here.
103
-                throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism');
104
-            }
105
-
106
-            $this->assignCSRFToken();
107
-            $this->setTemplate('mfa/enableYubikey.tpl');
108
-        }
109
-    }
110
-
111
-    protected function disableYubikeyOtp()
112
-    {
113
-        $database = $this->getDatabase();
114
-        $currentUser = User::getCurrent($database);
115
-
116
-        $otpCredentialProvider = new YubikeyOtpCredentialProvider($database,
117
-            $this->getSiteConfiguration(), $this->getHttpHelper());
118
-
119
-        $factorType = 'YubiKey OTP';
120
-
121
-        $this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType);
122
-    }
123
-
124
-    protected function enableTotp()
125
-    {
126
-        $database = $this->getDatabase();
127
-        $currentUser = User::getCurrent($database);
128
-
129
-        $otpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration());
130
-
131
-        if (WebRequest::wasPosted()) {
132
-            $this->validateCSRFToken();
133
-
134
-            // used for routing only, not security
135
-            $stage = WebRequest::postString('stage');
136
-
137
-            if ($stage === "auth") {
138
-                $password = WebRequest::postString('password');
139
-
140
-                $passwordCredentialProvider = new PasswordCredentialProvider($database,
141
-                    $this->getSiteConfiguration());
142
-                $result = $passwordCredentialProvider->authenticate($currentUser, $password);
143
-
144
-                if ($result) {
145
-                    $otpCredentialProvider->setCredential($currentUser, 2, null);
146
-
147
-                    $provisioningUrl = $otpCredentialProvider->getProvisioningUrl($currentUser);
148
-
149
-                    $renderer = new ImageRenderer(
150
-                        new RendererStyle(256),
151
-                        new SvgImageBackEnd()
152
-                    );
153
-
154
-                    $writer = new Writer($renderer);
155
-                    $svg = $writer->writeString($provisioningUrl);
156
-
157
-                    $this->assign('svg', $svg);
158
-                    $this->assign('secret', $otpCredentialProvider->getSecret($currentUser));
159
-
160
-                    $this->assignCSRFToken();
161
-                    $this->setTemplate('mfa/enableTotpEnroll.tpl');
162
-
163
-                    return;
164
-                }
165
-                else {
166
-                    SessionAlert::error('Error enabling TOTP - invalid credentials.');
167
-                    $this->redirect('multiFactor');
168
-
169
-                    return;
170
-                }
171
-            }
172
-
173
-            if ($stage === "enroll") {
174
-                // we *must* have a defined credential already here,
175
-                if ($otpCredentialProvider->isPartiallyEnrolled($currentUser)) {
176
-                    $otp = WebRequest::postString('otp');
177
-                    $result = $otpCredentialProvider->verifyEnable($currentUser, $otp);
178
-
179
-                    if ($result) {
180
-                        SessionAlert::success('Enabled TOTP.');
181
-
182
-                        $scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
183
-                        if ($scratchProvider->getRemaining($currentUser->getId()) < 3) {
184
-                            $scratchProvider->setCredential($currentUser, 2, null);
185
-                            $tokens = $scratchProvider->getTokens();
186
-                            $this->assign('tokens', $tokens);
187
-                            $this->setTemplate('mfa/regenScratchTokens.tpl');
188
-                            return;
189
-                        }
190
-                    }
191
-                    else {
192
-                        $otpCredentialProvider->deleteCredential($currentUser);
193
-                        SessionAlert::error('Error enabling TOTP: invalid token provided');
194
-                    }
195
-
196
-
197
-                    $this->redirect('multiFactor');
198
-                    return;
199
-                }
200
-                else {
201
-                    SessionAlert::error('Error enabling TOTP - no enrollment found or enrollment expired.');
202
-                    $this->redirect('multiFactor');
203
-
204
-                    return;
205
-                }
206
-            }
207
-
208
-            // urgh, dunno what happened, but it's not something expected.
209
-            throw new ApplicationLogicException();
210
-        }
211
-        else {
212
-            if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
213
-                // user is not enrolled, we shouldn't have got here.
214
-                throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism');
215
-            }
216
-
217
-            $this->assignCSRFToken();
218
-
219
-            $this->assign('alertmessage', 'To enable your multi-factor credentials, please prove you are who you say you are by providing your tool password below.');
220
-            $this->assign('alertheader', 'Provide credentials');
221
-            $this->assign('continueText', 'Verify password');
222
-            $this->setTemplate('mfa/enableAuth.tpl');
223
-        }
224
-    }
225
-
226
-    protected function disableTotp()
227
-    {
228
-        $database = $this->getDatabase();
229
-        $currentUser = User::getCurrent($database);
230
-
231
-        $otpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration());
232
-
233
-        $factorType = 'TOTP';
234
-
235
-        $this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType);
236
-    }
237
-
238
-    protected function scratch()
239
-    {
240
-        $database = $this->getDatabase();
241
-        $currentUser = User::getCurrent($database);
242
-
243
-        if (WebRequest::wasPosted()) {
244
-            $this->validateCSRFToken();
245
-
246
-            $passwordCredentialProvider = new PasswordCredentialProvider($database,
247
-                $this->getSiteConfiguration());
248
-
249
-            $otpCredentialProvider = new ScratchTokenCredentialProvider($database,
250
-                $this->getSiteConfiguration());
251
-
252
-            $password = WebRequest::postString('password');
253
-
254
-            $result = $passwordCredentialProvider->authenticate($currentUser, $password);
255
-
256
-            if ($result) {
257
-                $otpCredentialProvider->setCredential($currentUser, 2, null);
258
-                $tokens = $otpCredentialProvider->getTokens();
259
-                $this->assign('tokens', $tokens);
260
-                $this->setTemplate('mfa/regenScratchTokens.tpl');
261
-            }
262
-            else {
263
-                SessionAlert::error('Error refreshing scratch tokens - invalid credentials.');
264
-                $this->redirect('multiFactor');
265
-            }
266
-        }
267
-        else {
268
-            $this->assignCSRFToken();
269
-
270
-            $this->assign('alertmessage', 'To regenerate your emergency scratch tokens, please prove you are who you say you are by providing your tool password below. Note that continuing will invalidate all remaining scratch tokens, and provide a set of new ones.');
271
-            $this->assign('alertheader', 'Re-generate scratch tokens');
272
-            $this->assign('continueText', 'Regenerate Scratch Tokens');
273
-
274
-            $this->setTemplate('mfa/enableAuth.tpl');
275
-        }
276
-    }
277
-
278
-    /**
279
-     * @param PdoDatabase         $database
280
-     * @param User                $currentUser
281
-     * @param ICredentialProvider $otpCredentialProvider
282
-     * @param string              $factorType
283
-     *
284
-     * @throws ApplicationLogicException
285
-     */
286
-    private function deleteCredential(
287
-        PdoDatabase $database,
288
-        User $currentUser,
289
-        ICredentialProvider $otpCredentialProvider,
290
-        $factorType
291
-    ) {
292
-        if (WebRequest::wasPosted()) {
293
-            $passwordCredentialProvider = new PasswordCredentialProvider($database,
294
-                $this->getSiteConfiguration());
295
-
296
-            $this->validateCSRFToken();
297
-
298
-            $password = WebRequest::postString('password');
299
-            $result = $passwordCredentialProvider->authenticate($currentUser, $password);
300
-
301
-            if ($result) {
302
-                $otpCredentialProvider->deleteCredential($currentUser);
303
-                SessionAlert::success('Disabled ' . $factorType . '.');
304
-                $this->redirect('multiFactor');
305
-            }
306
-            else {
307
-                SessionAlert::error('Error disabling ' . $factorType . ' - invalid credentials.');
308
-                $this->redirect('multiFactor');
309
-            }
310
-        }
311
-        else {
312
-            if (!$otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
313
-                // user is not enrolled, we shouldn't have got here.
314
-                throw new ApplicationLogicException('User is not enrolled in the selected MFA mechanism');
315
-            }
316
-
317
-            $this->assignCSRFToken();
318
-            $this->assign('otpType', $factorType);
319
-            $this->setTemplate('mfa/disableOtp.tpl');
320
-        }
321
-    }
29
+	/**
30
+	 * Main function for this page, when no specific actions are called.
31
+	 * @return void
32
+	 */
33
+	protected function main()
34
+	{
35
+		$database = $this->getDatabase();
36
+		$currentUser = User::getCurrent($database);
37
+
38
+		$yubikeyOtpCredentialProvider = new YubikeyOtpCredentialProvider($database, $this->getSiteConfiguration(),
39
+			$this->getHttpHelper());
40
+		$this->assign('yubikeyOtpIdentity', $yubikeyOtpCredentialProvider->getYubikeyData($currentUser->getId()));
41
+		$this->assign('yubikeyOtpEnrolled', $yubikeyOtpCredentialProvider->userIsEnrolled($currentUser->getId()));
42
+
43
+		$totpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration());
44
+		$this->assign('totpEnrolled', $totpCredentialProvider->userIsEnrolled($currentUser->getId()));
45
+
46
+		$scratchCredentialProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
47
+		$this->assign('scratchEnrolled', $scratchCredentialProvider->userIsEnrolled($currentUser->getId()));
48
+		$this->assign('scratchRemaining', $scratchCredentialProvider->getRemaining($currentUser->getId()));
49
+
50
+		$this->assign('allowedTotp', $this->barrierTest('enableTotp', $currentUser));
51
+		$this->assign('allowedYubikey', $this->barrierTest('enableYubikeyOtp', $currentUser));
52
+
53
+		$this->setTemplate('mfa/mfa.tpl');
54
+	}
55
+
56
+	protected function enableYubikeyOtp()
57
+	{
58
+		$database = $this->getDatabase();
59
+		$currentUser = User::getCurrent($database);
60
+
61
+		$otpCredentialProvider = new YubikeyOtpCredentialProvider($database,
62
+			$this->getSiteConfiguration(), $this->getHttpHelper());
63
+
64
+		if (WebRequest::wasPosted()) {
65
+			$this->validateCSRFToken();
66
+
67
+			$passwordCredentialProvider = new PasswordCredentialProvider($database,
68
+				$this->getSiteConfiguration());
69
+
70
+			$password = WebRequest::postString('password');
71
+			$otp = WebRequest::postString('otp');
72
+
73
+			$result = $passwordCredentialProvider->authenticate($currentUser, $password);
74
+
75
+			if ($result) {
76
+				try {
77
+					$otpCredentialProvider->setCredential($currentUser, 2, $otp);
78
+					SessionAlert::success('Enabled YubiKey OTP.');
79
+
80
+					$scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
81
+					if ($scratchProvider->getRemaining($currentUser->getId()) < 3) {
82
+						$scratchProvider->setCredential($currentUser, 2, null);
83
+						$tokens = $scratchProvider->getTokens();
84
+						$this->assign('tokens', $tokens);
85
+						$this->setTemplate('mfa/regenScratchTokens.tpl');
86
+						return;
87
+					}
88
+				}
89
+				catch (ApplicationLogicException $ex) {
90
+					SessionAlert::error('Error enabling YubiKey OTP: ' . $ex->getMessage());
91
+				}
92
+
93
+				$this->redirect('multiFactor');
94
+			}
95
+			else {
96
+				SessionAlert::error('Error enabling YubiKey OTP - invalid credentials.');
97
+				$this->redirect('multiFactor');
98
+			}
99
+		}
100
+		else {
101
+			if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
102
+				// user is not enrolled, we shouldn't have got here.
103
+				throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism');
104
+			}
105
+
106
+			$this->assignCSRFToken();
107
+			$this->setTemplate('mfa/enableYubikey.tpl');
108
+		}
109
+	}
110
+
111
+	protected function disableYubikeyOtp()
112
+	{
113
+		$database = $this->getDatabase();
114
+		$currentUser = User::getCurrent($database);
115
+
116
+		$otpCredentialProvider = new YubikeyOtpCredentialProvider($database,
117
+			$this->getSiteConfiguration(), $this->getHttpHelper());
118
+
119
+		$factorType = 'YubiKey OTP';
120
+
121
+		$this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType);
122
+	}
123
+
124
+	protected function enableTotp()
125
+	{
126
+		$database = $this->getDatabase();
127
+		$currentUser = User::getCurrent($database);
128
+
129
+		$otpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration());
130
+
131
+		if (WebRequest::wasPosted()) {
132
+			$this->validateCSRFToken();
133
+
134
+			// used for routing only, not security
135
+			$stage = WebRequest::postString('stage');
136
+
137
+			if ($stage === "auth") {
138
+				$password = WebRequest::postString('password');
139
+
140
+				$passwordCredentialProvider = new PasswordCredentialProvider($database,
141
+					$this->getSiteConfiguration());
142
+				$result = $passwordCredentialProvider->authenticate($currentUser, $password);
143
+
144
+				if ($result) {
145
+					$otpCredentialProvider->setCredential($currentUser, 2, null);
146
+
147
+					$provisioningUrl = $otpCredentialProvider->getProvisioningUrl($currentUser);
148
+
149
+					$renderer = new ImageRenderer(
150
+						new RendererStyle(256),
151
+						new SvgImageBackEnd()
152
+					);
153
+
154
+					$writer = new Writer($renderer);
155
+					$svg = $writer->writeString($provisioningUrl);
156
+
157
+					$this->assign('svg', $svg);
158
+					$this->assign('secret', $otpCredentialProvider->getSecret($currentUser));
159
+
160
+					$this->assignCSRFToken();
161
+					$this->setTemplate('mfa/enableTotpEnroll.tpl');
162
+
163
+					return;
164
+				}
165
+				else {
166
+					SessionAlert::error('Error enabling TOTP - invalid credentials.');
167
+					$this->redirect('multiFactor');
168
+
169
+					return;
170
+				}
171
+			}
172
+
173
+			if ($stage === "enroll") {
174
+				// we *must* have a defined credential already here,
175
+				if ($otpCredentialProvider->isPartiallyEnrolled($currentUser)) {
176
+					$otp = WebRequest::postString('otp');
177
+					$result = $otpCredentialProvider->verifyEnable($currentUser, $otp);
178
+
179
+					if ($result) {
180
+						SessionAlert::success('Enabled TOTP.');
181
+
182
+						$scratchProvider = new ScratchTokenCredentialProvider($database, $this->getSiteConfiguration());
183
+						if ($scratchProvider->getRemaining($currentUser->getId()) < 3) {
184
+							$scratchProvider->setCredential($currentUser, 2, null);
185
+							$tokens = $scratchProvider->getTokens();
186
+							$this->assign('tokens', $tokens);
187
+							$this->setTemplate('mfa/regenScratchTokens.tpl');
188
+							return;
189
+						}
190
+					}
191
+					else {
192
+						$otpCredentialProvider->deleteCredential($currentUser);
193
+						SessionAlert::error('Error enabling TOTP: invalid token provided');
194
+					}
195
+
196
+
197
+					$this->redirect('multiFactor');
198
+					return;
199
+				}
200
+				else {
201
+					SessionAlert::error('Error enabling TOTP - no enrollment found or enrollment expired.');
202
+					$this->redirect('multiFactor');
203
+
204
+					return;
205
+				}
206
+			}
207
+
208
+			// urgh, dunno what happened, but it's not something expected.
209
+			throw new ApplicationLogicException();
210
+		}
211
+		else {
212
+			if ($otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
213
+				// user is not enrolled, we shouldn't have got here.
214
+				throw new ApplicationLogicException('User is already enrolled in the selected MFA mechanism');
215
+			}
216
+
217
+			$this->assignCSRFToken();
218
+
219
+			$this->assign('alertmessage', 'To enable your multi-factor credentials, please prove you are who you say you are by providing your tool password below.');
220
+			$this->assign('alertheader', 'Provide credentials');
221
+			$this->assign('continueText', 'Verify password');
222
+			$this->setTemplate('mfa/enableAuth.tpl');
223
+		}
224
+	}
225
+
226
+	protected function disableTotp()
227
+	{
228
+		$database = $this->getDatabase();
229
+		$currentUser = User::getCurrent($database);
230
+
231
+		$otpCredentialProvider = new TotpCredentialProvider($database, $this->getSiteConfiguration());
232
+
233
+		$factorType = 'TOTP';
234
+
235
+		$this->deleteCredential($database, $currentUser, $otpCredentialProvider, $factorType);
236
+	}
237
+
238
+	protected function scratch()
239
+	{
240
+		$database = $this->getDatabase();
241
+		$currentUser = User::getCurrent($database);
242
+
243
+		if (WebRequest::wasPosted()) {
244
+			$this->validateCSRFToken();
245
+
246
+			$passwordCredentialProvider = new PasswordCredentialProvider($database,
247
+				$this->getSiteConfiguration());
248
+
249
+			$otpCredentialProvider = new ScratchTokenCredentialProvider($database,
250
+				$this->getSiteConfiguration());
251
+
252
+			$password = WebRequest::postString('password');
253
+
254
+			$result = $passwordCredentialProvider->authenticate($currentUser, $password);
255
+
256
+			if ($result) {
257
+				$otpCredentialProvider->setCredential($currentUser, 2, null);
258
+				$tokens = $otpCredentialProvider->getTokens();
259
+				$this->assign('tokens', $tokens);
260
+				$this->setTemplate('mfa/regenScratchTokens.tpl');
261
+			}
262
+			else {
263
+				SessionAlert::error('Error refreshing scratch tokens - invalid credentials.');
264
+				$this->redirect('multiFactor');
265
+			}
266
+		}
267
+		else {
268
+			$this->assignCSRFToken();
269
+
270
+			$this->assign('alertmessage', 'To regenerate your emergency scratch tokens, please prove you are who you say you are by providing your tool password below. Note that continuing will invalidate all remaining scratch tokens, and provide a set of new ones.');
271
+			$this->assign('alertheader', 'Re-generate scratch tokens');
272
+			$this->assign('continueText', 'Regenerate Scratch Tokens');
273
+
274
+			$this->setTemplate('mfa/enableAuth.tpl');
275
+		}
276
+	}
277
+
278
+	/**
279
+	 * @param PdoDatabase         $database
280
+	 * @param User                $currentUser
281
+	 * @param ICredentialProvider $otpCredentialProvider
282
+	 * @param string              $factorType
283
+	 *
284
+	 * @throws ApplicationLogicException
285
+	 */
286
+	private function deleteCredential(
287
+		PdoDatabase $database,
288
+		User $currentUser,
289
+		ICredentialProvider $otpCredentialProvider,
290
+		$factorType
291
+	) {
292
+		if (WebRequest::wasPosted()) {
293
+			$passwordCredentialProvider = new PasswordCredentialProvider($database,
294
+				$this->getSiteConfiguration());
295
+
296
+			$this->validateCSRFToken();
297
+
298
+			$password = WebRequest::postString('password');
299
+			$result = $passwordCredentialProvider->authenticate($currentUser, $password);
300
+
301
+			if ($result) {
302
+				$otpCredentialProvider->deleteCredential($currentUser);
303
+				SessionAlert::success('Disabled ' . $factorType . '.');
304
+				$this->redirect('multiFactor');
305
+			}
306
+			else {
307
+				SessionAlert::error('Error disabling ' . $factorType . ' - invalid credentials.');
308
+				$this->redirect('multiFactor');
309
+			}
310
+		}
311
+		else {
312
+			if (!$otpCredentialProvider->userIsEnrolled($currentUser->getId())) {
313
+				// user is not enrolled, we shouldn't have got here.
314
+				throw new ApplicationLogicException('User is not enrolled in the selected MFA mechanism');
315
+			}
316
+
317
+			$this->assignCSRFToken();
318
+			$this->assign('otpType', $factorType);
319
+			$this->setTemplate('mfa/disableOtp.tpl');
320
+		}
321
+	}
322 322
 }
Please login to merge, or discard this patch.
includes/Pages/UserAuth/PageLogout.php 1 patch
Indentation   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -14,22 +14,22 @@
 block discarded – undo
14 14
 
15 15
 class PageLogout extends InternalPageBase
16 16
 {
17
-    /**
18
-     * Main function for this page, when no specific actions are called.
19
-     */
20
-    protected function main()
21
-    {
22
-        if (WebRequest::wasPosted()) {
23
-            Session::destroy();
24
-            $this->redirect("login");
25
-            return;
26
-        }
17
+	/**
18
+	 * Main function for this page, when no specific actions are called.
19
+	 */
20
+	protected function main()
21
+	{
22
+		if (WebRequest::wasPosted()) {
23
+			Session::destroy();
24
+			$this->redirect("login");
25
+			return;
26
+		}
27 27
 
28
-        $this->redirect();
29
-    }
28
+		$this->redirect();
29
+	}
30 30
 
31
-    protected function isProtectedPage()
32
-    {
33
-        return false;
34
-    }
31
+	protected function isProtectedPage()
32
+	{
33
+		return false;
34
+	}
35 35
 }
Please login to merge, or discard this patch.
includes/Pages/UserAuth/PageChangePassword.php 1 patch
Indentation   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -17,71 +17,71 @@
 block discarded – undo
17 17
 
18 18
 class PageChangePassword extends InternalPageBase
19 19
 {
20
-    /**
21
-     * Main function for this page, when no specific actions are called.
22
-     * @return void
23
-     */
24
-    protected function main()
25
-    {
26
-        $this->setHtmlTitle('Change Password');
20
+	/**
21
+	 * Main function for this page, when no specific actions are called.
22
+	 * @return void
23
+	 */
24
+	protected function main()
25
+	{
26
+		$this->setHtmlTitle('Change Password');
27 27
 
28
-        if (WebRequest::wasPosted()) {
29
-            $this->validateCSRFToken();
30
-            try {
31
-                $oldPassword = WebRequest::postString('password');
32
-                $newPassword = WebRequest::postString('newpassword');
33
-                $newPasswordConfirmation = WebRequest::postString('newpasswordconfirm');
28
+		if (WebRequest::wasPosted()) {
29
+			$this->validateCSRFToken();
30
+			try {
31
+				$oldPassword = WebRequest::postString('password');
32
+				$newPassword = WebRequest::postString('newpassword');
33
+				$newPasswordConfirmation = WebRequest::postString('newpasswordconfirm');
34 34
 
35
-                $user = User::getCurrent($this->getDatabase());
36
-                if (!$user instanceof User) {
37
-                    throw new ApplicationLogicException('User not found');
38
-                }
35
+				$user = User::getCurrent($this->getDatabase());
36
+				if (!$user instanceof User) {
37
+					throw new ApplicationLogicException('User not found');
38
+				}
39 39
 
40
-                $this->validateNewPassword($oldPassword, $newPassword, $newPasswordConfirmation, $user);
40
+				$this->validateNewPassword($oldPassword, $newPassword, $newPasswordConfirmation, $user);
41 41
 
42
-                $passwordProvider = new PasswordCredentialProvider($this->getDatabase(), $this->getSiteConfiguration());
43
-                $passwordProvider->setCredential($user, 1, $newPassword);
44
-            }
45
-            catch (ApplicationLogicException $ex) {
46
-                SessionAlert::error($ex->getMessage());
47
-                $this->redirect('changePassword');
42
+				$passwordProvider = new PasswordCredentialProvider($this->getDatabase(), $this->getSiteConfiguration());
43
+				$passwordProvider->setCredential($user, 1, $newPassword);
44
+			}
45
+			catch (ApplicationLogicException $ex) {
46
+				SessionAlert::error($ex->getMessage());
47
+				$this->redirect('changePassword');
48 48
 
49
-                return;
50
-            }
49
+				return;
50
+			}
51 51
 
52
-            SessionAlert::success('Password changed successfully!');
52
+			SessionAlert::success('Password changed successfully!');
53 53
 
54
-            $this->redirect('preferences');
55
-        }
56
-        else {
57
-            $this->assignCSRFToken();
58
-            $this->setTemplate('preferences/changePassword.tpl');
59
-            $this->addJs("/vendor/dropbox/zxcvbn/dist/zxcvbn.js");
60
-        }
61
-    }
54
+			$this->redirect('preferences');
55
+		}
56
+		else {
57
+			$this->assignCSRFToken();
58
+			$this->setTemplate('preferences/changePassword.tpl');
59
+			$this->addJs("/vendor/dropbox/zxcvbn/dist/zxcvbn.js");
60
+		}
61
+	}
62 62
 
63
-    /**
64
-     * @param string $oldPassword
65
-     * @param string $newPassword
66
-     * @param string $newPasswordConfirmation
67
-     * @param User   $user
68
-     *
69
-     * @throws ApplicationLogicException
70
-     */
71
-    protected function validateNewPassword($oldPassword, $newPassword, $newPasswordConfirmation, User $user)
72
-    {
73
-        if ($oldPassword === null || $newPassword === null || $newPasswordConfirmation === null) {
74
-            throw new ApplicationLogicException('All three fields must be completed to change your password');
75
-        }
63
+	/**
64
+	 * @param string $oldPassword
65
+	 * @param string $newPassword
66
+	 * @param string $newPasswordConfirmation
67
+	 * @param User   $user
68
+	 *
69
+	 * @throws ApplicationLogicException
70
+	 */
71
+	protected function validateNewPassword($oldPassword, $newPassword, $newPasswordConfirmation, User $user)
72
+	{
73
+		if ($oldPassword === null || $newPassword === null || $newPasswordConfirmation === null) {
74
+			throw new ApplicationLogicException('All three fields must be completed to change your password');
75
+		}
76 76
 
77
-        if ($newPassword !== $newPasswordConfirmation) {
78
-            throw new ApplicationLogicException('Your new passwords did not match!');
79
-        }
77
+		if ($newPassword !== $newPasswordConfirmation) {
78
+			throw new ApplicationLogicException('Your new passwords did not match!');
79
+		}
80 80
 
81
-        // TODO: adapt for MFA support
82
-        $passwordProvider = new PasswordCredentialProvider($this->getDatabase(), $this->getSiteConfiguration());
83
-        if (!$passwordProvider->authenticate($user, $oldPassword)) {
84
-            throw new ApplicationLogicException('The password you entered was incorrect.');
85
-        }
86
-    }
81
+		// TODO: adapt for MFA support
82
+		$passwordProvider = new PasswordCredentialProvider($this->getDatabase(), $this->getSiteConfiguration());
83
+		if (!$passwordProvider->authenticate($user, $oldPassword)) {
84
+			throw new ApplicationLogicException('The password you entered was incorrect.');
85
+		}
86
+	}
87 87
 }
Please login to merge, or discard this patch.
includes/Pages/UserAuth/PageOAuthCallback.php 1 patch
Indentation   +78 added lines, -78 removed lines patch added patch discarded remove patch
@@ -18,93 +18,93 @@
 block discarded – undo
18 18
 
19 19
 class PageOAuthCallback extends InternalPageBase
20 20
 {
21
-    /**
22
-     * @return bool
23
-     */
24
-    protected function isProtectedPage()
25
-    {
26
-        // This page is critical to ensuring OAuth functionality is operational.
27
-        return false;
28
-    }
21
+	/**
22
+	 * @return bool
23
+	 */
24
+	protected function isProtectedPage()
25
+	{
26
+		// This page is critical to ensuring OAuth functionality is operational.
27
+		return false;
28
+	}
29 29
 
30
-    /**
31
-     * Main function for this page, when no specific actions are called.
32
-     * @return void
33
-     */
34
-    protected function main()
35
-    {
36
-        // This should never get hit except by URL manipulation.
37
-        $this->redirect('');
38
-    }
30
+	/**
31
+	 * Main function for this page, when no specific actions are called.
32
+	 * @return void
33
+	 */
34
+	protected function main()
35
+	{
36
+		// This should never get hit except by URL manipulation.
37
+		$this->redirect('');
38
+	}
39 39
 
40
-    /**
41
-     * Registered endpoint for the account creation callback.
42
-     *
43
-     * If this ever gets hit, something is wrong somewhere.
44
-     */
45
-    protected function create()
46
-    {
47
-        throw new Exception('OAuth account creation endpoint triggered.');
48
-    }
40
+	/**
41
+	 * Registered endpoint for the account creation callback.
42
+	 *
43
+	 * If this ever gets hit, something is wrong somewhere.
44
+	 */
45
+	protected function create()
46
+	{
47
+		throw new Exception('OAuth account creation endpoint triggered.');
48
+	}
49 49
 
50
-    /**
51
-     * Callback entry point
52
-     * @throws ApplicationLogicException
53
-     * @throws OptimisticLockFailedException
54
-     */
55
-    protected function authorise()
56
-    {
57
-        $oauthToken = WebRequest::getString('oauth_token');
58
-        $oauthVerifier = WebRequest::getString('oauth_verifier');
50
+	/**
51
+	 * Callback entry point
52
+	 * @throws ApplicationLogicException
53
+	 * @throws OptimisticLockFailedException
54
+	 */
55
+	protected function authorise()
56
+	{
57
+		$oauthToken = WebRequest::getString('oauth_token');
58
+		$oauthVerifier = WebRequest::getString('oauth_verifier');
59 59
 
60
-        $this->doCallbackValidation($oauthToken, $oauthVerifier);
60
+		$this->doCallbackValidation($oauthToken, $oauthVerifier);
61 61
 
62
-        $database = $this->getDatabase();
62
+		$database = $this->getDatabase();
63 63
 
64
-        $user = OAuthUserHelper::findUserByRequestToken($oauthToken, $database);
65
-        $oauth = new OAuthUserHelper($user, $database, $this->getOAuthProtocolHelper(), $this->getSiteConfiguration());
64
+		$user = OAuthUserHelper::findUserByRequestToken($oauthToken, $database);
65
+		$oauth = new OAuthUserHelper($user, $database, $this->getOAuthProtocolHelper(), $this->getSiteConfiguration());
66 66
 
67
-        try {
68
-            $oauth->completeHandshake($oauthVerifier);
69
-        }
70
-        catch (CurlException $ex) {
71
-            throw new ApplicationLogicException($ex->getMessage(), 0, $ex);
72
-        }
67
+		try {
68
+			$oauth->completeHandshake($oauthVerifier);
69
+		}
70
+		catch (CurlException $ex) {
71
+			throw new ApplicationLogicException($ex->getMessage(), 0, $ex);
72
+		}
73 73
 
74
-        // OK, we're the same session that just did a partial login that was redirected to OAuth. Let's upgrade the
75
-        // login to a full login
76
-        if (WebRequest::getOAuthPartialLogin() === $user->getId()) {
77
-            WebRequest::setLoggedInUser($user);
78
-            $this->getDomainAccessManager()->switchToDefaultDomain($user);
79
-        }
74
+		// OK, we're the same session that just did a partial login that was redirected to OAuth. Let's upgrade the
75
+		// login to a full login
76
+		if (WebRequest::getOAuthPartialLogin() === $user->getId()) {
77
+			WebRequest::setLoggedInUser($user);
78
+			$this->getDomainAccessManager()->switchToDefaultDomain($user);
79
+		}
80 80
 
81
-        // My thinking is there are three cases here:
82
-        //   a) new user => redirect to prefs - it's the only thing they can access other than stats
83
-        //   b) existing user hit the connect button in prefs => redirect to prefs since it's where they were
84
-        //   c) existing user logging in => redirect to wherever they came from
85
-        $redirectDestination = WebRequest::clearPostLoginRedirect();
86
-        if ($redirectDestination !== null && !$user->isNewUser()) {
87
-            $this->redirectUrl($redirectDestination);
88
-        }
89
-        else {
90
-            $this->redirect('preferences', null, null, 'internal.php');
91
-        }
92
-    }
81
+		// My thinking is there are three cases here:
82
+		//   a) new user => redirect to prefs - it's the only thing they can access other than stats
83
+		//   b) existing user hit the connect button in prefs => redirect to prefs since it's where they were
84
+		//   c) existing user logging in => redirect to wherever they came from
85
+		$redirectDestination = WebRequest::clearPostLoginRedirect();
86
+		if ($redirectDestination !== null && !$user->isNewUser()) {
87
+			$this->redirectUrl($redirectDestination);
88
+		}
89
+		else {
90
+			$this->redirect('preferences', null, null, 'internal.php');
91
+		}
92
+	}
93 93
 
94
-    /**
95
-     * @param string $oauthToken
96
-     * @param string $oauthVerifier
97
-     *
98
-     * @throws ApplicationLogicException
99
-     */
100
-    private function doCallbackValidation($oauthToken, $oauthVerifier)
101
-    {
102
-        if ($oauthToken === null) {
103
-            throw new ApplicationLogicException('No token provided');
104
-        }
94
+	/**
95
+	 * @param string $oauthToken
96
+	 * @param string $oauthVerifier
97
+	 *
98
+	 * @throws ApplicationLogicException
99
+	 */
100
+	private function doCallbackValidation($oauthToken, $oauthVerifier)
101
+	{
102
+		if ($oauthToken === null) {
103
+			throw new ApplicationLogicException('No token provided');
104
+		}
105 105
 
106
-        if ($oauthVerifier === null) {
107
-            throw new ApplicationLogicException('No oauth verifier provided.');
108
-        }
109
-    }
106
+		if ($oauthVerifier === null) {
107
+			throw new ApplicationLogicException('No oauth verifier provided.');
108
+		}
109
+	}
110 110
 }
111 111
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Pages/UserAuth/PageOAuth.php 1 patch
Indentation   +77 added lines, -77 removed lines patch added patch discarded remove patch
@@ -22,81 +22,81 @@
 block discarded – undo
22 22
 
23 23
 class PageOAuth extends InternalPageBase
24 24
 {
25
-    /**
26
-     * Attach entry point
27
-     *
28
-     * must be posted, or will redirect to preferences
29
-     */
30
-    protected function attach()
31
-    {
32
-        if (!WebRequest::wasPosted()) {
33
-            $this->redirect('preferences');
34
-
35
-            return;
36
-        }
37
-
38
-        $database = $this->getDatabase();
39
-
40
-        $this->validateCSRFToken();
41
-
42
-        $oauthProtocolHelper = $this->getOAuthProtocolHelper();
43
-        $user = User::getCurrent($database);
44
-        $oauth = new OAuthUserHelper($user, $database, $oauthProtocolHelper, $this->getSiteConfiguration());
45
-
46
-        try {
47
-            $authoriseUrl = $oauth->getRequestToken();
48
-            $this->redirectUrl($authoriseUrl);
49
-        }
50
-        catch (CurlException $ex) {
51
-            throw new ApplicationLogicException($ex->getMessage(), 0, $ex);
52
-        }
53
-    }
54
-
55
-    /**
56
-     * Detach account entry point
57
-     * @throws Exception
58
-     */
59
-    protected function detach()
60
-    {
61
-        if ($this->getSiteConfiguration()->getEnforceOAuth()) {
62
-            throw new AccessDeniedException($this->getSecurityManager(), $this->getDomainAccessManager());
63
-        }
64
-
65
-        $database = $this->getDatabase();
66
-        $user = User::getCurrent($database);
67
-        $oauth = new OAuthUserHelper($user, $database, $this->getOAuthProtocolHelper(), $this->getSiteConfiguration());
68
-
69
-        try {
70
-            $oauth->refreshIdentity();
71
-        }
72
-        catch (CurlException $ex) {
73
-            // do nothing. The user's already revoked this access anyway.
74
-        }
75
-        catch (OAuthException $ex) {
76
-            // do nothing. The user's already revoked this access anyway.
77
-        }
78
-        catch (OptimisticLockFailedException $e) {
79
-            // do nothing. The user's already revoked this access anyway.
80
-        }
81
-
82
-        $oauth->detach();
83
-
84
-        // TODO: figure out why we need to force logout after a detach.
85
-        $user->setForcelogout(true);
86
-        $user->save();
87
-
88
-        // force the user to log out
89
-        Session::destroy();
90
-
91
-        $this->redirect('login');
92
-    }
93
-
94
-    /**
95
-     * Main function for this page, when no specific actions are called.
96
-     * @return void
97
-     */
98
-    protected function main()
99
-    {
100
-        $this->redirect('preferences');
101
-    }
25
+	/**
26
+	 * Attach entry point
27
+	 *
28
+	 * must be posted, or will redirect to preferences
29
+	 */
30
+	protected function attach()
31
+	{
32
+		if (!WebRequest::wasPosted()) {
33
+			$this->redirect('preferences');
34
+
35
+			return;
36
+		}
37
+
38
+		$database = $this->getDatabase();
39
+
40
+		$this->validateCSRFToken();
41
+
42
+		$oauthProtocolHelper = $this->getOAuthProtocolHelper();
43
+		$user = User::getCurrent($database);
44
+		$oauth = new OAuthUserHelper($user, $database, $oauthProtocolHelper, $this->getSiteConfiguration());
45
+
46
+		try {
47
+			$authoriseUrl = $oauth->getRequestToken();
48
+			$this->redirectUrl($authoriseUrl);
49
+		}
50
+		catch (CurlException $ex) {
51
+			throw new ApplicationLogicException($ex->getMessage(), 0, $ex);
52
+		}
53
+	}
54
+
55
+	/**
56
+	 * Detach account entry point
57
+	 * @throws Exception
58
+	 */
59
+	protected function detach()
60
+	{
61
+		if ($this->getSiteConfiguration()->getEnforceOAuth()) {
62
+			throw new AccessDeniedException($this->getSecurityManager(), $this->getDomainAccessManager());
63
+		}
64
+
65
+		$database = $this->getDatabase();
66
+		$user = User::getCurrent($database);
67
+		$oauth = new OAuthUserHelper($user, $database, $this->getOAuthProtocolHelper(), $this->getSiteConfiguration());
68
+
69
+		try {
70
+			$oauth->refreshIdentity();
71
+		}
72
+		catch (CurlException $ex) {
73
+			// do nothing. The user's already revoked this access anyway.
74
+		}
75
+		catch (OAuthException $ex) {
76
+			// do nothing. The user's already revoked this access anyway.
77
+		}
78
+		catch (OptimisticLockFailedException $e) {
79
+			// do nothing. The user's already revoked this access anyway.
80
+		}
81
+
82
+		$oauth->detach();
83
+
84
+		// TODO: figure out why we need to force logout after a detach.
85
+		$user->setForcelogout(true);
86
+		$user->save();
87
+
88
+		// force the user to log out
89
+		Session::destroy();
90
+
91
+		$this->redirect('login');
92
+	}
93
+
94
+	/**
95
+	 * Main function for this page, when no specific actions are called.
96
+	 * @return void
97
+	 */
98
+	protected function main()
99
+	{
100
+		$this->redirect('preferences');
101
+	}
102 102
 }
Please login to merge, or discard this patch.
includes/Pages/RequestAction/PageBreakReservation.php 1 patch
Indentation   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -19,81 +19,81 @@
 block discarded – undo
19 19
 
20 20
 class PageBreakReservation extends RequestActionBase
21 21
 {
22
-    protected function main()
23
-    {
24
-        $this->checkPosted();
25
-        $database = $this->getDatabase();
26
-        $request = $this->getRequest($database);
22
+	protected function main()
23
+	{
24
+		$this->checkPosted();
25
+		$database = $this->getDatabase();
26
+		$request = $this->getRequest($database);
27 27
 
28
-        if ($request->getReserved() === null) {
29
-            throw new ApplicationLogicException('Request is not reserved!');
30
-        }
28
+		if ($request->getReserved() === null) {
29
+			throw new ApplicationLogicException('Request is not reserved!');
30
+		}
31 31
 
32
-        $currentUser = User::getCurrent($database);
32
+		$currentUser = User::getCurrent($database);
33 33
 
34
-        if ($currentUser->getId() === $request->getReserved()) {
35
-            $this->doUnreserve($request, $database);
36
-        }
37
-        else {
38
-            // not the same user!
39
-            if ($this->barrierTest('force', $currentUser)) {
40
-                $this->doBreakReserve($request, $database);
41
-            }
42
-            else {
43
-                throw new AccessDeniedException($this->getSecurityManager(), $this->getDomainAccessManager());
44
-            }
45
-        }
46
-    }
34
+		if ($currentUser->getId() === $request->getReserved()) {
35
+			$this->doUnreserve($request, $database);
36
+		}
37
+		else {
38
+			// not the same user!
39
+			if ($this->barrierTest('force', $currentUser)) {
40
+				$this->doBreakReserve($request, $database);
41
+			}
42
+			else {
43
+				throw new AccessDeniedException($this->getSecurityManager(), $this->getDomainAccessManager());
44
+			}
45
+		}
46
+	}
47 47
 
48
-    /**
49
-     * @param Request     $request
50
-     * @param PdoDatabase $database
51
-     *
52
-     * @throws Exception
53
-     */
54
-    protected function doUnreserve(Request $request, PdoDatabase $database)
55
-    {
56
-        // same user! we allow people to unreserve their own stuff
57
-        $request->setReserved(null);
58
-        $request->setUpdateVersion(WebRequest::postInt('updateversion'));
59
-        $request->save();
48
+	/**
49
+	 * @param Request     $request
50
+	 * @param PdoDatabase $database
51
+	 *
52
+	 * @throws Exception
53
+	 */
54
+	protected function doUnreserve(Request $request, PdoDatabase $database)
55
+	{
56
+		// same user! we allow people to unreserve their own stuff
57
+		$request->setReserved(null);
58
+		$request->setUpdateVersion(WebRequest::postInt('updateversion'));
59
+		$request->save();
60 60
 
61
-        Logger::unreserve($database, $request);
62
-        $this->getNotificationHelper()->requestUnreserved($request);
61
+		Logger::unreserve($database, $request);
62
+		$this->getNotificationHelper()->requestUnreserved($request);
63 63
 
64
-        // Redirect home!
65
-        $this->redirect();
66
-    }
64
+		// Redirect home!
65
+		$this->redirect();
66
+	}
67 67
 
68
-    /**
69
-     * @param Request     $request
70
-     * @param PdoDatabase $database
71
-     *
72
-     * @throws Exception
73
-     */
74
-    protected function doBreakReserve(Request $request, PdoDatabase $database)
75
-    {
76
-        if (!WebRequest::postBoolean("confirm")) {
77
-            $this->assignCSRFToken();
68
+	/**
69
+	 * @param Request     $request
70
+	 * @param PdoDatabase $database
71
+	 *
72
+	 * @throws Exception
73
+	 */
74
+	protected function doBreakReserve(Request $request, PdoDatabase $database)
75
+	{
76
+		if (!WebRequest::postBoolean("confirm")) {
77
+			$this->assignCSRFToken();
78 78
 
79
-            $this->assign("request", $request->getId());
80
-            $this->assign("reservedUser", User::getById($request->getReserved(), $database));
81
-            $this->assign("updateversion", WebRequest::postInt('updateversion'));
79
+			$this->assign("request", $request->getId());
80
+			$this->assign("reservedUser", User::getById($request->getReserved(), $database));
81
+			$this->assign("updateversion", WebRequest::postInt('updateversion'));
82 82
 
83
-            $this->skipAlerts();
83
+			$this->skipAlerts();
84 84
 
85
-            $this->setTemplate("confirmations/breakreserve.tpl");
86
-        }
87
-        else {
88
-            $request->setReserved(null);
89
-            $request->setUpdateVersion(WebRequest::postInt('updateversion'));
90
-            $request->save();
85
+			$this->setTemplate("confirmations/breakreserve.tpl");
86
+		}
87
+		else {
88
+			$request->setReserved(null);
89
+			$request->setUpdateVersion(WebRequest::postInt('updateversion'));
90
+			$request->save();
91 91
 
92
-            Logger::breakReserve($database, $request);
93
-            $this->getNotificationHelper()->requestReserveBroken($request);
92
+			Logger::breakReserve($database, $request);
93
+			$this->getNotificationHelper()->requestReserveBroken($request);
94 94
 
95
-            // Redirect home!
96
-            $this->redirect();
97
-        }
98
-    }
95
+			// Redirect home!
96
+			$this->redirect();
97
+		}
98
+	}
99 99
 }
Please login to merge, or discard this patch.