2019-01-16 10:37:35 +00:00
< ? php
2019-01-17 14:06:16 +00:00
$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 ]));
2019-01-16 17:01:30 +00:00
}
2019-01-17 14:06:16 +00:00
$settings = include_once ( $configurationFile );
2019-01-23 21:08:30 +00:00
try {
# switch ($settings->Database['Driver']) {
# case 'sqlite':
# $database = new PDO('sqlite:' . $settings->Database['Path']);
2019-01-28 10:48:05 +00:00
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' ]));
}
2019-01-23 21:08:30 +00:00
# }
}
catch ( Exception $e ) {
throw new Exception ( sprintf ( 'Unable to connect to database \'%1$s\'' , $settings -> Sqlite [ 'Path' ]));
}
2019-01-16 17:01:30 +00:00
2019-01-16 10:37:35 +00:00
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
2019-01-17 14:06:16 +00:00
$sanitizedUsername = preg_replace ( '([^a-zA-Z]*)' , '' , $_POST [ 'username' ]);
$qualifiedUsername = $settings -> LDAP [ 'Domain' ] . '\\' . $sanitizedUsername ;
2019-01-16 10:37:35 +00:00
2019-01-17 14:06:16 +00:00
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 ];
2019-01-16 10:37:35 +00:00
// Create JWT-payload
$jwtPayload = [
2019-01-17 14:06:16 +00:00
'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)
2019-01-16 10:37:35 +00:00
];
$secureToken = JWT :: encode ( $jwtPayload , base64_decode ( $settings -> JWT [ 'PrivateKey_base64' ]));
2019-01-28 10:48:05 +00:00
2019-01-16 10:37:35 +00:00
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 $username , string $password , object $cookie ) {
global $settings ;
}
2019-01-23 21:08:30 +00:00
function retrieveTokenFromDB ( string $username , string $foo ) {
2019-01-16 10:37:35 +00:00
global $settings ;
}
2019-01-24 16:17:53 +00:00
function validateToken ( string $secureToken ) {
2019-01-28 10:48:05 +00:00
global $settings , $pdoDB ;
2019-01-16 10:37:35 +00:00
2019-01-23 21:08:30 +00:00
try {
2019-01-24 16:17:53 +00:00
$jwtPayload = JWT :: decode ( $secureToken , base64_decode ( $settings -> JWT [ 'PrivateKey_base64' ]), $settings -> JWT [ 'Algorithm' ]);
2019-01-23 21:08:30 +00:00
} catch ( Exception $e ) {
2019-01-24 18:48:29 +00:00
// Invalid token
return [ 'status' => 'Fail' , 'reason' => '1' ];
2019-01-23 21:08:30 +00:00
}
2019-01-28 10:48:05 +00:00
if (( int ) $jwtPayload -> iat < ( time () - ( int ) $settings -> Session [ 'Duration' ])) {
// Expired token
return [ 'status' => 'Fail' , 'reason' => '3' ];
}
2019-01-23 21:08:30 +00:00
$pdoQuery = $pdoDB -> prepare ( '
2019-01-24 18:48:29 +00:00
SELECT SecureToken . Value
2019-01-23 21:08:30 +00:00
FROM SecureToken
LEFT JOIN User
ON ( User . Id = SecureToken . UserId )
WHERE User . Username = : username
' );
$pdoQuery -> execute ([
2019-01-28 10:48:05 +00:00
':username' => ( string ) $jwtPayload -> sub
2019-01-23 21:08:30 +00:00
]);
foreach ( $pdoQuery -> fetchAll ( PDO :: FETCH_ASSOC ) as $row ) {
2019-01-28 10:48:05 +00:00
try {
$storedTokens [] = JWT :: decode ( $row [ 'Value' ], base64_decode ( $settings -> JWT [ 'PrivateKey_base64' ]), $settings -> JWT [ 'Algorithm' ]);
} catch ( Exception $e ) {
continue ;
}
2019-01-16 17:01:30 +00:00
}
2019-01-23 21:08:30 +00:00
2019-01-28 10:48:05 +00:00
if ( ! empty ( $storedTokens ) && sizeof ( array_filter ( $storedTokens , function ( $value ) use ( $jwtPayload ) {
return $value [ 'iat' ] === $jwtPayload [ 'iat' ];
})) === 1 ) {
// At least one of the database-stored tokens match
return [ 'status' => 'Success' , 'token' => $jwtPayload ];
} else {
2019-01-24 18:48:29 +00:00
// No matching token in database
2019-01-28 10:48:05 +00:00
return [ 'status' => 'Fail' , 'reason' => '2' ];
2019-01-23 21:08:30 +00:00
}
2019-01-16 10:37:35 +00:00
}
?>