Skip to content

Commit f626d63

Browse files
author
Dave MacFarlane
committed
PHPCS
1 parent d5c971d commit f626d63

File tree

16 files changed

+481
-327
lines changed

16 files changed

+481
-327
lines changed

modules/api/php/endpoints/login.class.inc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ class Login extends Endpoint
105105

106106
$user = $requestdata['username'] ?? null;
107107
$password = $requestdata['password'] ?? null;
108-
$mfacode = $requestdata['code'] ?? null;
109108

110109
if ($user === null || $password === null) {
111110
return new \LORIS\Http\Response\JSON\BadRequest(
@@ -115,7 +114,7 @@ class Login extends Endpoint
115114

116115
$login = $this->getLoginAuthenticator();
117116

118-
if ($login->passwordAuthenticate($user, $password, $mfacode, false)) {
117+
if ($login->passwordAuthenticate($user, $password, false)) {
119118
$token = $this->getEncodedToken($user);
120119
if (!empty($token)) {
121120
return new \LORIS\Http\Response\JsonResponse(

modules/login/php/authentication.class.inc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ class Authentication extends \NDB_Page implements ETagCalculator
160160
$success = $login->passwordAuthenticate(
161161
$values['username'],
162162
$values['password'],
163-
null,
164163
false,
165164
);
166165
if ($success) {

modules/login/php/mfa.class.inc

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,23 @@ namespace LORIS\login;
44

55
use \Psr\Http\Message\ServerRequestInterface;
66
use \Psr\Http\Message\ResponseInterface;
7-
use \LORIS\Middleware\ETagCalculator;
87

98
/**
10-
* POST request for authentication.
9+
* Perform multi-factor authentication for LORIS.
1110
*
12-
* Used to request account.
11+
* This page is used by the MFA middleware to prompt for and
12+
* validate a 2 factor authentication code.
1313
*
14-
* @category Loris
15-
* @package Login
16-
* @author Alizée Wickenheiser <[email protected]>
17-
* @license http://www.gnu.org/licenses/gpl-3.0.txt GPLv3
18-
* @link https://www.github.com/aces/Loris/
14+
* @license http://www.gnu.org/licenses/gpl-3.0.txt GPLv3
1915
*/
2016
class MFA extends \NDB_Page
2117
{
2218
public $skipTemplate = true;
2319

2420
/**
25-
* Include additional JS files
21+
* {@inheritDoc}
2622
*
27-
* @return array of javascript to be inserted
23+
* @return array
2824
*/
2925
function getJSDependencies()
3026
{
@@ -38,10 +34,11 @@ class MFA extends \NDB_Page
3834
]
3935
);
4036
}
37+
4138
/**
42-
* Include additional CSS files:
39+
* {@inheritDoc}
4340
*
44-
* @return array of javascript to be inserted
41+
* @return array
4542
*/
4643
function getCSSDependencies()
4744
{
@@ -64,8 +61,8 @@ class MFA extends \NDB_Page
6461
{
6562
// Ensure POST request.
6663
switch ($request->getMethod()) {
67-
case 'GET':
68-
return parent::handle($request);
64+
case 'GET':
65+
return parent::handle($request);
6966
case 'POST':
7067
return $this->_handlePOST($request);
7168
default:
@@ -84,22 +81,22 @@ class MFA extends \NDB_Page
8481
*/
8582
private function _handlePOST(ServerRequestInterface $request) : ResponseInterface
8683
{
87-
$requestdata = json_decode((string )$request->getBody(), true);
88-
$user = $request->getAttribute("user");
89-
if(!isset($requestdata['code'])) {
90-
return new \LORIS\Http\Response\JSON\Unauthorized("missing code");
91-
}
84+
$requestdata = json_decode((string )$request->getBody(), true);
85+
$user = $request->getAttribute("user");
86+
if (!isset($requestdata['code'])) {
87+
return new \LORIS\Http\Response\JSON\Unauthorized("missing code");
88+
}
9289

93-
$validator = $user->getTOTPValidator();
94-
$counter = $validator->getTimeCounter();
95-
$wantCode = $validator->getCode($counter, 6);
96-
if($wantCode === $requestdata['code']) {
97-
$login = $_SESSION['State']->getProperty('login');
98-
$login->setPassedMFA();
99-
return new \LORIS\Http\Response\JSON\OK(["success" => "validated code"]);
100-
} else {
101-
return new \LORIS\Http\Response\JSON\Unauthorized("invalid code");
102-
}
90+
$validator = $user->getTOTPValidator();
91+
$counter = $validator->getTimeCounter();
92+
$wantCode = $validator->getCode($counter, 6);
93+
if ($wantCode === $requestdata['code']) {
94+
$login = $_SESSION['State']->getProperty('login');
95+
$login->setPassedMFA();
96+
return new \LORIS\Http\Response\JSON\OK(["success" => "validated code"]);
97+
} else {
98+
return new \LORIS\Http\Response\JSON\Unauthorized("invalid code");
99+
}
103100
}
104101

105102
/**

modules/my_preferences/jsx/mfa.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ function CodeValidator(props: {
3636
return resp.json()
3737
}).then( (json) => {
3838
if (json.ok == 'success') {
39-
swal.fire('Success!', json.message, 'success')
39+
swal.fire('Success!', json.message, 'success').then( () => {
40+
window.location.href = loris.BaseURL + "/my_preferences/";
41+
});
42+
4043
} else if (json.error) {
4144
swal.fire('Error', json.error, 'error')
4245
} else {

modules/my_preferences/php/mfa.class.inc

Lines changed: 69 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,24 @@ use \Psr\Http\Message\ResponseInterface;
1212
*/
1313
class MFA extends \NDB_Page
1414
{
15-
public $skipTemplate = true;
15+
public $skipTemplate = true;
1616

17-
public function getBreadcrumbs(): \LORIS\BreadcrumbTrail
18-
{
19-
return new \LORIS\BreadcrumbTrail(
20-
new \LORIS\Breadcrumb(
21-
dgettext("loris", "My Preferences")
22-
),
23-
new \LORIS\Breadcrumb(
24-
dgettext("my_preferences", "Configure 2FA")
25-
),
26-
);
27-
}
17+
/**
18+
* {@inheritDoc}
19+
*
20+
* @return \LORIS\BreadcrumbTrail
21+
*/
22+
public function getBreadcrumbs(): \LORIS\BreadcrumbTrail
23+
{
24+
return new \LORIS\BreadcrumbTrail(
25+
new \LORIS\Breadcrumb(
26+
dgettext("loris", "My Preferences")
27+
),
28+
new \LORIS\Breadcrumb(
29+
dgettext("my_preferences", "Configure 2FA")
30+
),
31+
);
32+
}
2833

2934
/**
3035
* {@inheritDoc}
@@ -35,15 +40,18 @@ class MFA extends \NDB_Page
3540
*/
3641
public function handle(ServerRequestInterface $request) : ResponseInterface
3742
{
38-
switch($request->getMethod()) {
39-
case 'GET':
40-
return parent::handle($request);
41-
case 'POST':
42-
return $this->validateCodeAndSave($request->getAttribute("user"), $request->getParsedBody());
43-
default:
44-
return new \LORIS\Http\Response\JSON\MethodNotAllowed(['GET', 'POST']);
43+
switch ($request->getMethod()) {
44+
case 'GET':
45+
return parent::handle($request);
46+
case 'POST':
47+
return $this->validateCodeAndSave(
48+
$request->getAttribute("user"),
49+
$request->getParsedBody()
50+
);
51+
default:
52+
return new \LORIS\Http\Response\JSON\MethodNotAllowed(['GET', 'POST']);
4553

46-
}
54+
}
4755
}
4856
/**
4957
* {@inheritDoc}
@@ -63,27 +71,48 @@ class MFA extends \NDB_Page
6371
);
6472
}
6573

66-
function validateCodeAndSave(\User $user, array $values): ResponseInterface {
67-
if(!isset($values['code']) || !isset($values['secret'])) {
68-
return new \LORIS\Http\Response\JSON\BadRequest('Missing code or secret to validate');
69-
}
70-
$base32Decoder = new Base32();
71-
$secret = $base32Decoder->decode($values['secret']);
72-
$validator = new \LORIS\Security\OTP\TOTP(secret: $secret);
73-
$counter = $validator->getTimeCounter();
74-
$wantCode = $validator->getCode($counter, 6);
75-
if($wantCode !== strval($values['code'])) {
76-
return new \LORIS\Http\Response\JSON\BadRequest('Code does not match expected value');
77-
}
78-
$db = $this->loris->getDatabaseConnection();
79-
$db->_trackChanges = false;
80-
// We are dealing with binary data that never gets exposed to the user
81-
$db->unsafeUpdate("users", ['TOTPSecret' => $secret], ['ID' => $user->getId()]);
74+
/**
75+
* Validates the code passed by the user matches the secret key that they
76+
* provided and save the secret key to the database if it matches
77+
*
78+
* @param \User $user The user providing the 2FA code
79+
* @param array $values The parsed values submitted by the user
80+
*
81+
* @return ResponseInterface
82+
*/
83+
function validateCodeAndSave(\User $user, array $values): ResponseInterface
84+
{
85+
if (!isset($values['code']) || !isset($values['secret'])) {
86+
return new \LORIS\Http\Response\JSON\BadRequest(
87+
'Missing code or secret to validate'
88+
);
89+
}
90+
$base32Decoder = new Base32();
91+
$secret = $base32Decoder->decode($values['secret']);
92+
$validator = new \LORIS\Security\OTP\TOTP(secret: $secret);
93+
$counter = $validator->getTimeCounter();
94+
$wantCode = $validator->getCode($counter, 6);
95+
if ($wantCode !== strval($values['code'])) {
96+
return new \LORIS\Http\Response\JSON\BadRequest(
97+
'Code does not match expected value'
98+
);
99+
}
100+
$db = $this->loris->getDatabaseConnection();
101+
$db->_trackChanges = false;
102+
// We are dealing with binary data that never gets exposed to the user
103+
$db->unsafeUpdate(
104+
"users",
105+
['TOTPSecret' => $secret],
106+
['ID' => $user->getId()]
107+
);
82108

83-
$login = $_SESSION['state']->getProperty('login');
84-
$login->setPassedMFA();
85-
return new \LORIS\Http\Response\JSON\OK(['ok' => 'success',
86-
'message' => 'Successfully registered multifactor authenticator']);
109+
$login = $_SESSION['State']->getProperty('login');
110+
$login->setPassedMFA();
111+
return new \LORIS\Http\Response\JSON\OK(
112+
['ok' => 'success',
113+
'message' => 'Successfully registered multifactor authenticator'
114+
]
115+
);
87116
}
88117
}
89118

modules/my_preferences/php/my_preferences.class.inc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<?php declare(strict_types=1);
22

33
namespace LORIS\my_preferences;
4-
use chillerlan\QRCode\QRCode;
54

65
/**
76
* Implements the my preferences page.

php/libraries/AnonymousUser.class.inc

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,13 @@ class AnonymousUser extends \User
8686
return [];
8787
}
8888

89-
function totpRequired() : bool {
90-
return false;
89+
/**
90+
* {@inheritDoc}
91+
*
92+
* @return bool
93+
*/
94+
function totpRequired() : bool
95+
{
96+
return false;
9197
}
9298
}

php/libraries/NDB_Client.class.inc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,6 @@ class NDB_Client
152152
header("Location: /login/password-expiry");
153153

154154
}
155-
if($login->needsMFA()) {
156-
return false;
157-
}
158155
$login->setState();
159156
} elseif ($auth === false) {
160157
// only send a 403 error if they were attempting to log in,

php/libraries/SinglePointLogin.class.inc

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -185,18 +185,18 @@ class SinglePointLogin
185185
* @param string $password The password to validate
186186
* @param bool $redirect If this flag is true, this
187187
* function may instead print
188-
* out a login or password expiry
189-
* page. when trying to authenticate.
190-
* If false, it won't provide any output
191-
* in those situation.
188+
* out a login or password
189+
* expiry page. when trying
190+
* to authenticate. If false,
191+
* it won't provide any
192+
* output in those situation.
192193
*
193194
* @return bool False unless account is valid and password correct.
194195
* @access public
195196
*/
196197
function passwordAuthenticate(
197198
string $username,
198199
string $password,
199-
?string $code = null,
200200
bool $redirect = true
201201
): bool {
202202

@@ -308,8 +308,6 @@ class SinglePointLogin
308308
['UserID' => $username]
309309
);
310310
}
311-
//if($user->totpRequired() && $!$this->passedMFA()) {
312-
//}
313311
}
314312

315313
if ($row['Active'] == 'N'
@@ -601,15 +599,30 @@ class SinglePointLogin
601599
$_SESSION['State']->setProperty('login', $this);
602600
}
603601

604-
public function passedMFA() {
605-
return $_SESSION['PassedMFA'] ?? false === true;
602+
/**
603+
* Returns true if this login session has already passed a 2 factor
604+
* authentication check
605+
*
606+
* @return bool
607+
*/
608+
public function passedMFA(): bool
609+
{
610+
return $_SESSION['PassedMFA'] ?? false === true;
606611
}
607-
public function setPassedMFA() {
608-
// NDB_Client called session_write_close, we need to re-start it
609-
// to edit a session variable.
610-
session_start();
611-
$_SESSION['PassedMFA'] = true;
612-
session_write_close();
612+
613+
/**
614+
* Declare this session as having passed a 2 factor authentication
615+
* check
616+
*
617+
* @return void
618+
*/
619+
public function setPassedMFA()
620+
{
621+
// NDB_Client called session_write_close, we need to re-start it
622+
// to edit a session variable.
623+
session_start();
624+
$_SESSION['PassedMFA'] = true;
625+
session_write_close();
613626
}
614627

615628
}

0 commit comments

Comments
 (0)