fix: persistent sessiebeheer (remember-me), HTTPS-cookie herstel en Microsoft OAuth signed state flow
This commit is contained in:
@@ -7,22 +7,54 @@
|
||||
require_once __DIR__ . '/../includes/auth.php';
|
||||
require_once __DIR__ . '/../includes/integrations/microsoft.php';
|
||||
|
||||
$user = require_auth();
|
||||
start_secure_session();
|
||||
|
||||
// 1. CSRF State validatie & Sessieherstel
|
||||
$receivedState = $_GET['state'] ?? '';
|
||||
$stateUserId = !empty($receivedState) ? verify_oauth_state($receivedState) : null;
|
||||
|
||||
// Als de sessie verloren is gegaan tijdens de externe cross-site redirect vanaf Microsoft,
|
||||
// herstellen we de gebruiker veilig aan de hand van de cryptografisch ondertekende OAuth state!
|
||||
if (empty($_SESSION['user_id']) && $stateUserId) {
|
||||
try {
|
||||
$db = get_db_connection();
|
||||
$stmtUser = $db->prepare("SELECT id, name, email, role, two_factor_enabled, created_at FROM users WHERE id = ?");
|
||||
$stmtUser->execute([$stateUserId]);
|
||||
$recoveredUser = $stmtUser->fetch();
|
||||
if ($recoveredUser) {
|
||||
$_SESSION['user_id'] = $recoveredUser['id'];
|
||||
$_SESSION['user_name'] = $recoveredUser['name'];
|
||||
$_SESSION['user_email'] = $recoveredUser['email'];
|
||||
$_SESSION['user_role'] = $recoveredUser['role'];
|
||||
$_SESSION['is_2fa_verified'] = true;
|
||||
issue_remember_token((int)$recoveredUser['id']);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
// Foutafhandeling
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Controleer authenticatie
|
||||
$user = get_logged_in_user();
|
||||
if (!$user) {
|
||||
header('Location: /auth/login.php?error=' . urlencode('Sessie verlopen tijdens Microsoft koppeling. Log opnieuw in en probeer het nogmaals.'));
|
||||
exit;
|
||||
}
|
||||
|
||||
$db = get_db_connection();
|
||||
|
||||
// 1. Foutafhandeling vanuit Microsoft
|
||||
// 3. Foutafhandeling vanuit Microsoft (bijv. gebruiker weigerde machtiging)
|
||||
if (!empty($_GET['error'])) {
|
||||
$errorDescription = $_GET['error_description'] ?? $_GET['error'];
|
||||
header('Location: /integrations.php?error=' . urlencode("Microsoft melding: {$errorDescription}"));
|
||||
exit;
|
||||
}
|
||||
|
||||
// 2. CSRF State validatie
|
||||
$receivedState = $_GET['state'] ?? '';
|
||||
// 4. Valideer de state (via HMAC handtekening of fallback sessiestate)
|
||||
$expectedState = $_SESSION['ms_oauth_state'] ?? '';
|
||||
unset($_SESSION['ms_oauth_state']);
|
||||
unset($_SESSION['ms_oauth_state'], $_SESSION['ms_oauth_user_id']);
|
||||
|
||||
if (empty($receivedState) || !hash_equals($expectedState, $receivedState)) {
|
||||
if (!$stateUserId && (empty($receivedState) || empty($expectedState) || !hash_equals($expectedState, $receivedState))) {
|
||||
header('Location: /integrations.php?error=' . urlencode('Ongeldige sessie of CSRF-controle mislukt. Probeer opnieuw in te loggen via Microsoft.'));
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$_SESSION['user_email'] = $invite['email'];
|
||||
$_SESSION['user_role'] = $invite['role'];
|
||||
$_SESSION['is_2fa_verified'] = true;
|
||||
issue_remember_token($newUserId);
|
||||
unset($_SESSION['invite_totp_secret']);
|
||||
|
||||
header('Location: /planner.php');
|
||||
|
||||
+6
-2
@@ -12,8 +12,9 @@ if (!has_admin_user()) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Als al volledig ingelogd en 2FA geverifieerd, ga naar planner
|
||||
if (!empty($_SESSION['user_id']) && !empty($_SESSION['is_2fa_verified'])) {
|
||||
// Als al ingelogd (via actieve sessie of persistente cookie), ga direct naar planner
|
||||
$currentUser = get_logged_in_user();
|
||||
if ($currentUser) {
|
||||
header('Location: /planner.php');
|
||||
exit;
|
||||
}
|
||||
@@ -96,6 +97,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$_SESSION['user_role'] = $user['role'];
|
||||
$_SESSION['is_2fa_verified'] = true;
|
||||
|
||||
// Activeer persistente remember token (30 dagen blijf ingelogd)
|
||||
issue_remember_token((int)$user['id']);
|
||||
|
||||
unset($_SESSION['pending_2fa_user_id'], $_SESSION['pending_2fa_user_email'], $_SESSION['pending_2fa_user_name']);
|
||||
|
||||
header('Location: /planner.php');
|
||||
|
||||
@@ -6,6 +6,21 @@
|
||||
require_once __DIR__ . '/../includes/auth.php';
|
||||
start_secure_session();
|
||||
|
||||
// Vernietig persistente login in database
|
||||
if (!empty($_SESSION['user_id'])) {
|
||||
try {
|
||||
$db = get_db_connection();
|
||||
ensure_remember_token_columns($db);
|
||||
$stmt = $db->prepare("UPDATE users SET remember_token = NULL, remember_token_expires_at = NULL WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
} catch (Throwable $e) {
|
||||
// Stil negeren bij uitloggen
|
||||
}
|
||||
}
|
||||
|
||||
// Verwijder remember cookie
|
||||
clear_remember_cookie();
|
||||
|
||||
// Vernietig alle sessie variabelen
|
||||
$_SESSION = [];
|
||||
|
||||
|
||||
@@ -31,10 +31,10 @@ if (empty($clientId)) {
|
||||
// Bepaal de dynamische of geconfigureerde redirect URI
|
||||
$redirectUri = rtrim(APP_URL, '/') . '/auth/callback_microsoft.php';
|
||||
|
||||
// Genereer unieke CSRF state
|
||||
$state = bin2hex(random_bytes(16));
|
||||
// Genereer cryptografisch ondertekende OAuth state waarin de user_id en timestamp veilig zijn opgeslagen
|
||||
$state = generate_oauth_state((int)$user['id']);
|
||||
$_SESSION['ms_oauth_state'] = $state;
|
||||
$_SESSION['ms_oauth_user_id'] = $user['id'];
|
||||
$_SESSION['ms_oauth_user_id'] = (int)$user['id'];
|
||||
|
||||
// Stuur gebruiker door naar Microsoft login
|
||||
$authUrl = microsoft_get_auth_url($clientId, $redirectUri, $tenantId, $state);
|
||||
|
||||
@@ -68,6 +68,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$_SESSION['user_email'] = $email;
|
||||
$_SESSION['user_role'] = 'ADMIN';
|
||||
$_SESSION['is_2fa_verified'] = true;
|
||||
issue_remember_token($adminId);
|
||||
unset($_SESSION['setup_totp_secret']);
|
||||
|
||||
$success = true;
|
||||
|
||||
Reference in New Issue
Block a user