Migrated IDE platform; accepting nonexisting diffs to make IDE happy
This commit is contained in:
@ -1,147 +1,150 @@
|
||||
<?php
|
||||
|
||||
$configurationFile = '../lucidAuth.config.php';
|
||||
if (!file_exists($configurationFile)) {
|
||||
throw new Exception(sprintf('Missing config file. Please rename \'%1$s.example\' to \'%1$s\' and edit it to reflect your setup.', explode('../', $configurationFile)[1]));
|
||||
}
|
||||
$settings = include_once($configurationFile);
|
||||
try {
|
||||
# switch ($settings->Database['Driver']) {
|
||||
# case 'sqlite':
|
||||
# $database = new PDO('sqlite:' . $settings->Database['Path']);
|
||||
if (is_writable($settings->Sqlite['Path'])) {
|
||||
$pdoDB = new PDO('sqlite:' . $settings->Sqlite['Path']);
|
||||
} else {
|
||||
throw new Exception(sprintf('Database file \'%1$s\' is not writable', $settings->Sqlite['Path']));
|
||||
}
|
||||
# }
|
||||
}
|
||||
catch (Exception $e) {
|
||||
throw new Exception(sprintf('Unable to connect to database \'%1$s\'', $settings->Sqlite['Path']));
|
||||
}
|
||||
|
||||
function authenticateLDAP (string $username, string $password) {
|
||||
global $settings;
|
||||
|
||||
if (!empty($username) && !empty($password)) {
|
||||
// Handle login requests
|
||||
|
||||
$ds = ldap_connect($settings->LDAP['Server'], $settings->LDAP['Port']);
|
||||
|
||||
// Strict namingconvention: only allow alphabetic characters
|
||||
$sanitizedUsername = preg_replace('([^a-zA-Z]*)', '', $_POST['username']);
|
||||
$qualifiedUsername = $settings->LDAP['Domain'] . '\\' . $sanitizedUsername;
|
||||
|
||||
if (@ldap_bind($ds, $qualifiedUsername, utf8_encode($_POST['password']))) {
|
||||
// Successful authentication; get additional userdetails from authenticationsource
|
||||
$ldapSearchResults = ldap_search($ds, $settings->LDAP['BaseDN'], "sAMAccountName=$sanitizedUsername");
|
||||
$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)
|
||||
];
|
||||
|
||||
$secureToken = JWT::encode($jwtPayload, base64_decode($settings->JWT['PrivateKey_base64']));
|
||||
|
||||
return ['status' => 'Success', 'token' => $secureToken];
|
||||
} else {
|
||||
// LDAP authentication failed!
|
||||
return ['status' => 'Fail', 'reason' => '1'];
|
||||
}
|
||||
} else {
|
||||
// Empty username or passwords not allowed!
|
||||
return ['status' => 'Fail', 'reason' => '1'];
|
||||
}
|
||||
}
|
||||
|
||||
function storeToken (string $secureToken, string $qualifiedUsername, string $httpHost) {
|
||||
global $settings, $pdoDB;
|
||||
|
||||
// Save authentication token in database serverside
|
||||
try {
|
||||
$pdoQuery = $pdoDB->prepare('
|
||||
INSERT INTO SecureToken (UserId, Value)
|
||||
SELECT User.Id, :securetoken
|
||||
FROM User
|
||||
WHERE User.Username = :qualifiedusername
|
||||
');
|
||||
$pdoQuery->execute([
|
||||
':securetoken' => $secureToken,
|
||||
':qualifiedusername' => $qualifiedUsername
|
||||
]);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
return ['status' => 'Fail', 'reason' => $e];
|
||||
}
|
||||
|
||||
// Save authentication token in cookie clientside
|
||||
$cookieDomain = array_values(array_filter($settings->Session['CookieDomains'], function ($value) use ($httpHost) {
|
||||
// Check if $_SERVER['HTTP_HOST'] matches any of the configured domains (either explicitly or as a subdomain)
|
||||
// This might seem backwards, but relying on $_SERVER directly allows spoofed values with potential security risks
|
||||
return (strlen($value) > strlen($httpHost)) ? false : (0 === substr_compare($httpHost, $value, -strlen($value)));
|
||||
}))[0];
|
||||
if ($cookieDomain && setcookie('JWT', $secureToken, (time() + $settings->Session['Duration']), '/', '.' . $cookieDomain)) {
|
||||
return ['status' => 'Success'];
|
||||
} else {
|
||||
return ['status' => 'Fail', 'reason' => 'Unable to store cookie(s)'];
|
||||
}
|
||||
}
|
||||
|
||||
function validateToken (string $secureToken) {
|
||||
global $settings, $pdoDB;
|
||||
|
||||
// Decode provided authentication token
|
||||
try {
|
||||
$jwtPayload = JWT::decode($secureToken, base64_decode($settings->JWT['PrivateKey_base64']), $settings->JWT['Algorithm']);
|
||||
} catch (Exception $e) {
|
||||
// Invalid token
|
||||
if ($settings->Debug['LogToFile']) {
|
||||
file_put_contents('../validateToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Provided token could not be decoded' . PHP_EOL, FILE_APPEND);
|
||||
}
|
||||
return ['status' => 'Fail', 'reason' => '1'];
|
||||
}
|
||||
|
||||
if ((int)$jwtPayload->iat < (time() - (int)$settings->Session['Duration'])) {
|
||||
// Expired token
|
||||
if ($settings->Debug['LogToFile']) {
|
||||
file_put_contents('../validateToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Provided token has expired' . PHP_EOL, FILE_APPEND);
|
||||
}
|
||||
return ['status' => 'Fail', 'reason' => '3'];
|
||||
}
|
||||
|
||||
// Retrieve all authentication tokens from database matching username
|
||||
$pdoQuery = $pdoDB->prepare('
|
||||
SELECT SecureToken.Value
|
||||
FROM SecureToken
|
||||
LEFT JOIN User
|
||||
ON (User.Id=SecureToken.UserId)
|
||||
WHERE User.Username = :username
|
||||
');
|
||||
$pdoQuery->execute([
|
||||
':username' => (string)$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']);
|
||||
} catch (Exception $e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare provided authentication token to all stored tokens in database
|
||||
if (!empty($storedTokens) && sizeof(array_filter($storedTokens, function ($value) use ($jwtPayload) {
|
||||
return $value->iat === $jwtPayload->iat;
|
||||
})) === 1) {
|
||||
return ['status' => 'Success'];
|
||||
} else {
|
||||
if ($settings->Debug['LogToFile']) {
|
||||
file_put_contents('../validateToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- No matching token in database' . PHP_EOL, FILE_APPEND);
|
||||
}
|
||||
return ['status' => 'Fail', 'reason' => '2'];
|
||||
}
|
||||
}
|
||||
|
||||
<?php
|
||||
|
||||
$configurationFile = '../lucidAuth.config.php';
|
||||
if (!file_exists($configurationFile)) {
|
||||
throw new Exception(sprintf('Missing config file. Please rename \'%1$s.example\' to \'%1$s\' and edit it to reflect your setup.', explode('../', $configurationFile)[1]));
|
||||
}
|
||||
$settings = include_once($configurationFile);
|
||||
try {
|
||||
# switch ($settings->Database['Driver']) {
|
||||
# case 'sqlite':
|
||||
# $database = new PDO('sqlite:' . $settings->Database['Path']);
|
||||
if (is_writable($settings->Sqlite['Path'])) {
|
||||
$pdoDB = new PDO('sqlite:' . $settings->Sqlite['Path']);
|
||||
} else {
|
||||
throw new Exception(sprintf('Database file \'%1$s\' is not writable', $settings->Sqlite['Path']));
|
||||
}
|
||||
# }
|
||||
}
|
||||
catch (Exception $e) {
|
||||
throw new Exception(sprintf('Unable to connect to database \'%1$s\'', $settings->Sqlite['Path']));
|
||||
}
|
||||
|
||||
function authenticateLDAP (string $username, string $password) {
|
||||
global $settings;
|
||||
|
||||
if (!empty($username) && !empty($password)) {
|
||||
// Handle login requests
|
||||
|
||||
$ds = ldap_connect($settings->LDAP['Server'], $settings->LDAP['Port']);
|
||||
|
||||
// Strict namingconvention: only allow alphabetic characters
|
||||
$sanitizedUsername = preg_replace('([^a-zA-Z]*)', '', $_POST['username']);
|
||||
$qualifiedUsername = $settings->LDAP['Domain'] . '\\' . $sanitizedUsername;
|
||||
|
||||
if (@ldap_bind($ds, $qualifiedUsername, utf8_encode($_POST['password']))) {
|
||||
// Successful authentication; get additional userdetails from authenticationsource
|
||||
$ldapSearchResults = ldap_search($ds, $settings->LDAP['BaseDN'], "sAMAccountName=$sanitizedUsername");
|
||||
$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)
|
||||
];
|
||||
|
||||
$secureToken = JWT::encode($jwtPayload, base64_decode($settings->JWT['PrivateKey_base64']));
|
||||
|
||||
return ['status' => 'Success', 'token' => $secureToken];
|
||||
} else {
|
||||
// LDAP authentication failed!
|
||||
return ['status' => 'Fail', 'reason' => '1'];
|
||||
}
|
||||
} else {
|
||||
// Empty username or passwords not allowed!
|
||||
return ['status' => 'Fail', 'reason' => '1'];
|
||||
}
|
||||
}
|
||||
|
||||
function storeToken (string $secureToken, string $qualifiedUsername, string $httpHost) {
|
||||
global $settings, $pdoDB;
|
||||
|
||||
// Save authentication token in database serverside
|
||||
try {
|
||||
$pdoQuery = $pdoDB->prepare('
|
||||
INSERT INTO SecureToken (UserId, Value)
|
||||
SELECT User.Id, :securetoken
|
||||
FROM User
|
||||
WHERE User.Username = :qualifiedusername
|
||||
');
|
||||
$pdoQuery->execute([
|
||||
':securetoken' => $secureToken,
|
||||
':qualifiedusername' => $qualifiedUsername
|
||||
]);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
return ['status' => 'Fail', 'reason' => $e];
|
||||
}
|
||||
|
||||
// Save authentication token in cookie clientside
|
||||
$cookieDomain = array_values(array_filter($settings->Session['CookieDomains'], function ($value) use ($httpHost) {
|
||||
// Check if $_SERVER['HTTP_HOST'] matches any of the configured domains (either explicitly or as a subdomain)
|
||||
// This might seem backwards, but relying on $_SERVER directly allows spoofed values with potential security risks
|
||||
return (strlen($value) > strlen($httpHost)) ? false : (0 === substr_compare($httpHost, $value, -strlen($value)));
|
||||
}))[0];
|
||||
if ($cookieDomain && setcookie('JWT', $secureToken, (time() + $settings->Session['Duration']), '/', '.' . $cookieDomain)) {
|
||||
return ['status' => 'Success'];
|
||||
} else {
|
||||
return ['status' => 'Fail', 'reason' => 'Unable to store cookie(s)'];
|
||||
}
|
||||
}
|
||||
|
||||
function validateToken (string $secureToken) {
|
||||
global $settings, $pdoDB;
|
||||
|
||||
// Decode provided authentication token
|
||||
try {
|
||||
$jwtPayload = JWT::decode($secureToken, base64_decode($settings->JWT['PrivateKey_base64']), $settings->JWT['Algorithm']);
|
||||
} catch (Exception $e) {
|
||||
// Invalid token
|
||||
if ($settings->Debug['LogToFile']) {
|
||||
file_put_contents('../validateToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Provided token could not be decoded' . PHP_EOL, FILE_APPEND);
|
||||
}
|
||||
return ['status' => 'Fail', 'reason' => '1'];
|
||||
}
|
||||
|
||||
if ((int)$jwtPayload->iat < (time() - (int)$settings->Session['Duration'])) {
|
||||
// Expired token
|
||||
if ($settings->Debug['LogToFile']) {
|
||||
file_put_contents('../validateToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Provided token has expired' . PHP_EOL, FILE_APPEND);
|
||||
}
|
||||
return ['status' => 'Fail', 'reason' => '3'];
|
||||
}
|
||||
|
||||
// Retrieve all authentication tokens from database matching username
|
||||
$pdoQuery = $pdoDB->prepare('
|
||||
SELECT SecureToken.Value
|
||||
FROM SecureToken
|
||||
LEFT JOIN User
|
||||
ON (User.Id=SecureToken.UserId)
|
||||
WHERE User.Username = :username
|
||||
');
|
||||
$pdoQuery->execute([
|
||||
':username' => (string)$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']);
|
||||
} catch (Exception $e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare provided authentication token to all stored tokens in database
|
||||
if (!empty($storedTokens) && sizeof(array_filter($storedTokens, function ($value) use ($jwtPayload) {
|
||||
return $value->iat === $jwtPayload->iat;
|
||||
})) === 1) {
|
||||
return [
|
||||
'status' => 'Success',
|
||||
'name' => $jwtPayload->name
|
||||
];
|
||||
} else {
|
||||
if ($settings->Debug['LogToFile']) {
|
||||
file_put_contents('../validateToken.log', (new DateTime())->format('Y-m-d\TH:i:s.u') . ' --- Either no matching token or multiple matching tokens found in database' . PHP_EOL, FILE_APPEND);
|
||||
}
|
||||
return ['status' => 'Fail', 'reason' => '2'];
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
Reference in New Issue
Block a user