125 lines
4.8 KiB
PHP
125 lines
4.8 KiB
PHP
<?php
|
|
/**
|
|
* Keycloak SSO Callback Controller
|
|
*
|
|
* Handles: /admin/index.php?module=keycloak/callback
|
|
*
|
|
* This controller does NOT extend Base to avoid login requirement check
|
|
*/
|
|
|
|
namespace Vvveb\Controller\Keycloak;
|
|
|
|
use Vvveb\System\Core\Request;
|
|
use Vvveb\System\Core\Response;
|
|
use Vvveb\System\Core\View;
|
|
use Vvveb\System\Session;
|
|
use Jumbojett\OpenIDConnectClient;
|
|
use Vvveb\System\User\Admin;
|
|
|
|
#[\AllowDynamicProperties]
|
|
class Callback {
|
|
// Declare properties to avoid dynamic property warnings in PHP 8.2+
|
|
public $request;
|
|
public $response;
|
|
public $view;
|
|
public $session;
|
|
|
|
function index() {
|
|
// Properties are injected by FrontController::di() automatically
|
|
// Suppress deprecation warnings from jumbojett library (PHP 8.5 compatibility)
|
|
// E_STRICT removed in PHP 8.4+, so we don't include it
|
|
// Suppress warnings temporarily to prevent output before headers
|
|
$oldErrorReporting = error_reporting(E_ALL & ~E_DEPRECATED & ~E_WARNING);
|
|
|
|
// Load Keycloak configuration from config file
|
|
$keycloakConfig = \Vvveb\config('keycloak', []);
|
|
|
|
// Fallback to hardcoded values if config file doesn't exist
|
|
$keycloakUrl = $keycloakConfig['server_url'] ?? 'https://connect.slm-lab.net/realms/cercle';
|
|
$keycloakClient = $keycloakConfig['client_id'] ?? 'page.slm-lab.net';
|
|
$keycloakSecret = $keycloakConfig['client_secret'] ?? 'IGFw1QWDs9xQ7OyRp6YM8VRgQxn09tFF';
|
|
|
|
// Redirect URL - MUST match exactly the one configured in Keycloak
|
|
$redirectUrl = $keycloakConfig['redirect_uri'] ?? 'https://www.slm-lab.net/admin/index.php?module=keycloak/callback';
|
|
|
|
try {
|
|
// Create OpenID Connect client
|
|
$oidc = new OpenIDConnectClient(
|
|
$keycloakUrl,
|
|
$keycloakClient,
|
|
$keycloakSecret
|
|
);
|
|
|
|
$oidc->setRedirectURL($redirectUrl);
|
|
$oidc->addScope(['openid', 'profile', 'email']);
|
|
|
|
// Complete the OAuth2 flow (exchange code for tokens)
|
|
$oidc->authenticate();
|
|
|
|
// Get user information from Keycloak
|
|
$userInfo = $oidc->requestUserInfo();
|
|
|
|
// Restore error reporting
|
|
error_reporting($oldErrorReporting);
|
|
|
|
// Extract email from Keycloak response
|
|
$email = $userInfo->email ?? null;
|
|
|
|
if (!$email) {
|
|
throw new \Exception('Keycloak did not return an email address.');
|
|
}
|
|
|
|
// Find admin user in Vvveb database using Vvveb API
|
|
// Only get active admins (status = 1)
|
|
$adminInfo = Admin::get([
|
|
'email' => $email,
|
|
'status' => 1,
|
|
]);
|
|
|
|
if (!$adminInfo) {
|
|
// User not found or not active - redirect to login with error
|
|
header('Location: /admin/index.php?module=user/login&error=' . urlencode("The email {$email} is not registered as an active admin in Vvveb."));
|
|
exit;
|
|
}
|
|
|
|
// Create Vvveb admin session (same way Admin::login() does it)
|
|
$this->session->regenerateId(true);
|
|
|
|
// Remove password hash from session data
|
|
if (isset($adminInfo['password'])) {
|
|
unset($adminInfo['password']);
|
|
}
|
|
|
|
// Set admin session (namespace 'admin' is used by Vvveb\System\User\Admin)
|
|
$this->session->set('admin', $adminInfo);
|
|
|
|
// Check if there's a redirect URL stored in session (from auto-login)
|
|
$redirectUrl = $this->session->get('keycloak_redirect');
|
|
if ($redirectUrl) {
|
|
// Remove redirect URL from session
|
|
$this->session->delete('keycloak_redirect');
|
|
// Redirect to original page
|
|
header('Location: ' . $redirectUrl);
|
|
} else {
|
|
// Redirect to admin dashboard
|
|
$adminPath = \Vvveb\adminPath() ?: '/admin/';
|
|
header('Location: ' . $adminPath . 'index.php');
|
|
}
|
|
exit;
|
|
|
|
} catch (\Exception $e) {
|
|
// Restore error reporting
|
|
error_reporting($oldErrorReporting);
|
|
|
|
// Log error if logging is available
|
|
if (function_exists('error_log')) {
|
|
error_log('Keycloak SSO Error: ' . $e->getMessage());
|
|
}
|
|
|
|
// Redirect to login page with error
|
|
header('Location: /admin/index.php?module=user/login&error=' . urlencode('Keycloak authentication failed: ' . $e->getMessage()));
|
|
exit;
|
|
}
|
|
}
|
|
}
|