visual
This commit is contained in:
@@ -47,6 +47,62 @@ final class KeycloakAuth
|
||||
return isset($_SESSION['desktop_auth']) && is_array($_SESSION['desktop_auth']);
|
||||
}
|
||||
|
||||
public function ensureAuthenticatedSession(): bool
|
||||
{
|
||||
if (!$this->isAuthenticated()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->hasUsableAccessToken()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$this->hasUsableRefreshToken()) {
|
||||
$this->logout();
|
||||
return false;
|
||||
}
|
||||
|
||||
$refreshToken = (string) ($_SESSION['desktop_auth']['refresh_token'] ?? '');
|
||||
if ($refreshToken === '') {
|
||||
$this->logout();
|
||||
return false;
|
||||
}
|
||||
|
||||
$refreshResponse = $this->postForm(
|
||||
$this->tokenEndpoint(),
|
||||
[
|
||||
'grant_type' => 'refresh_token',
|
||||
'refresh_token' => $refreshToken,
|
||||
'client_id' => $this->clientId(),
|
||||
'client_secret' => $this->clientSecret(),
|
||||
]
|
||||
);
|
||||
|
||||
if (($refreshResponse['success'] ?? false) !== true) {
|
||||
$this->logout();
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var array<string, mixed> $tokenPayload */
|
||||
$tokenPayload = $refreshResponse['data'];
|
||||
$accessToken = (string) ($tokenPayload['access_token'] ?? '');
|
||||
if ($accessToken === '') {
|
||||
$this->logout();
|
||||
return false;
|
||||
}
|
||||
|
||||
$userInfo = $this->fetchUserInfo($accessToken);
|
||||
if (($userInfo['success'] ?? false) !== true) {
|
||||
$this->logout();
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var array<string, mixed> $userPayload */
|
||||
$userPayload = $userInfo['data'];
|
||||
$this->establishSession($tokenPayload, $userPayload);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function shouldShowDesktop(): bool
|
||||
{
|
||||
if (!$this->enforceLogin()) {
|
||||
@@ -385,6 +441,37 @@ final class KeycloakAuth
|
||||
return is_array($claims) ? $claims : [];
|
||||
}
|
||||
|
||||
private function hasUsableAccessToken(): bool
|
||||
{
|
||||
$accessToken = (string) ($_SESSION['desktop_auth']['access_token'] ?? '');
|
||||
if ($accessToken === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->secondsUntilSessionExpiry('expires_in') > 30;
|
||||
}
|
||||
|
||||
private function hasUsableRefreshToken(): bool
|
||||
{
|
||||
$refreshToken = (string) ($_SESSION['desktop_auth']['refresh_token'] ?? '');
|
||||
if ($refreshToken === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->secondsUntilSessionExpiry('refresh_expires_in') > 30;
|
||||
}
|
||||
|
||||
private function secondsUntilSessionExpiry(string $ttlField): int
|
||||
{
|
||||
$authenticatedAt = (int) ($_SESSION['desktop_auth']['authenticated_at'] ?? 0);
|
||||
$ttl = (int) ($_SESSION['desktop_auth'][$ttlField] ?? 0);
|
||||
if ($authenticatedAt <= 0 || $ttl <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ($authenticatedAt + $ttl) - time();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $fields
|
||||
* @return array{success: bool, data?: array<string, mixed>, error?: string}
|
||||
|
||||
@@ -14,8 +14,9 @@ final class ModuleHttp
|
||||
{
|
||||
$auth = new KeycloakAuth(ConfigLoader::load($projectRoot, 'keycloak'));
|
||||
$accountGate = new AccountGate(ConfigLoader::load($projectRoot, 'registration'));
|
||||
$hasAuthenticatedSession = $auth->ensureAuthenticatedSession();
|
||||
|
||||
if ($auth->isAuthenticated()) {
|
||||
if ($hasAuthenticatedSession) {
|
||||
$currentUser = is_array($_SESSION['desktop_auth']['user'] ?? null) ? $_SESSION['desktop_auth']['user'] : [];
|
||||
$accountCheck = $accountGate->checkUsername((string) ($currentUser['username'] ?? ''));
|
||||
|
||||
@@ -35,7 +36,7 @@ final class ModuleHttp
|
||||
}
|
||||
}
|
||||
|
||||
if (!$auth->shouldShowDesktop()) {
|
||||
if (!$hasAuthenticatedSession && !$auth->shouldShowDesktop()) {
|
||||
if ($json) {
|
||||
self::respondJson(['error' => 'Nicht autorisiert.'], 401);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user