Added garbage collection for expired and defunct tokens in database.
This commit is contained in:
@ -38,10 +38,11 @@ function authenticateLDAP (string $username, string $password) {
|
||||
$commonName = ldap_get_entries($ds, $ldapSearchResults)[0]['cn'][0];
|
||||
// Create JWT-payload
|
||||
$jwtPayload = [
|
||||
'iat' => time(), // Issued at: time when the token was generated
|
||||
'iss' => $_SERVER['SERVER_NAME'], // Issuer
|
||||
'sub' => $qualifiedUsername, // Subject (ie. username)
|
||||
'name' => $commonName // Common name (as retrieved from AD)
|
||||
'iat' => time(), // Issued at: time when the token was generated
|
||||
'iss' => $_SERVER['SERVER_NAME'], // Issuer
|
||||
'sub' => $qualifiedUsername, // Subject (ie. username)
|
||||
'name' => $commonName, // Common name (as retrieved from AD)
|
||||
'fp' => base64_encode(json_encode(get_browser(null, True))) // Fingerprint (based on `HTTP_USER_AGENT`)
|
||||
];
|
||||
|
||||
$secureToken = JWT::encode($jwtPayload, base64_decode($settings->JWT['PrivateKey_base64']));
|
||||
@ -121,8 +122,8 @@ function validateToken (string $secureToken) {
|
||||
WHERE LOWER(User.Username) = :username
|
||||
');
|
||||
$pdoQuery->execute([
|
||||
':username' => (string) strtolower($jwtPayload->sub)
|
||||
]);
|
||||
':username' => (string) strtolower($jwtPayload->sub)
|
||||
]);
|
||||
foreach($pdoQuery->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
||||
try {
|
||||
$storedTokens[] = JWT::decode($row['Value'], base64_decode($settings->JWT['PrivateKey_base64']), $settings->JWT['Algorithm']);
|
||||
@ -136,7 +137,9 @@ function validateToken (string $secureToken) {
|
||||
if (!empty($storedTokens) && sizeof(array_filter($storedTokens, function ($value) use ($jwtPayload) {
|
||||
return $value->iat === $jwtPayload->iat;
|
||||
})) === 1) {
|
||||
return [
|
||||
purgeTokens($currentUserId, $settings->Session['Duration']);
|
||||
|
||||
return [
|
||||
'status' => 'Success',
|
||||
'name' => $jwtPayload->name,
|
||||
'uid' => $currentUserId
|
||||
@ -149,4 +152,54 @@ function validateToken (string $secureToken) {
|
||||
}
|
||||
}
|
||||
|
||||
function purgeTokens(int $userID, int $maximumTokenAge) {
|
||||
global $settings, $pdoDB;
|
||||
|
||||
$defunctTokens = []; $expiredTokens = [];
|
||||
|
||||
$pdoQuery = $pdoDB->prepare('
|
||||
SELECT SecureToken.Id, SecureToken.Value
|
||||
FROM SecureToken
|
||||
WHERE SecureToken.UserId = :userid
|
||||
');
|
||||
$pdoQuery->execute([
|
||||
':userid' => (int) $userID
|
||||
]);
|
||||
foreach($pdoQuery->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
||||
try {
|
||||
$token = JWT::decode($row['Value'], base64_decode($settings->JWT['PrivateKey_base64']), $settings->JWT['Algorithm']);
|
||||
if ($token->iat < (time() - $maximumTokenAge)) {
|
||||
$expiredTokens[] = $row['Id'];
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$defunctTokens[] = $row['Id'];
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Sadly, PDO does not support named parameters in constructions like 'IN ( :array )'
|
||||
// instead, the supported syntax is unnamed placeholders like 'IN (?, ?, ?, ...)'
|
||||
$pdoQuery = $pdoDB->prepare('
|
||||
DELETE FROM SecureToken
|
||||
WHERE SecureToken.Id IN (' . implode( ',', array_fill(0, count(array_merge($defunctTokens, $expiredTokens)), '?')) . ')
|
||||
');
|
||||
$pdoQuery->execute(array_merge($defunctTokens, $expiredTokens));
|
||||
|
||||
if ($settings->Debug['LogToFile']) {
|
||||
file_put_contents('../purgeToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Garbage collection succeeded (' . $userID . ' => ' . $pdoQuery->rowCount() . ')' . PHP_EOL, FILE_APPEND);
|
||||
}
|
||||
|
||||
return [
|
||||
'status' => 'Success',
|
||||
'amount' => $pdoQuery->rowCount()
|
||||
];
|
||||
} catch (Exception $e) {
|
||||
if ($settings->Debug['LogToFile']) {
|
||||
file_put_contents('../purgeToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Garbage collection failed (' . $userID . ' => ' . $e . ')' . PHP_EOL, FILE_APPEND);
|
||||
}
|
||||
|
||||
return ['status' => 'Fail', 'reason' => $e];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
Reference in New Issue
Block a user