keycloak
This commit is contained in:
82
public/auth/callback/index.php
Normal file
82
public/auth/callback/index.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once dirname(__DIR__, 3) . '/src/App/bootstrap.php';
|
||||
|
||||
use App\ConfigLoader;
|
||||
use App\KeycloakAuth;
|
||||
|
||||
session_start();
|
||||
|
||||
$projectRoot = dirname(__DIR__, 3);
|
||||
$auth = new KeycloakAuth(ConfigLoader::load($projectRoot, 'keycloak'));
|
||||
$state = (string) ($_GET['state'] ?? '');
|
||||
$expectedState = (string) ($_SESSION['keycloak_oauth_state'] ?? '');
|
||||
$code = (string) ($_GET['code'] ?? '');
|
||||
|
||||
$title = 'Keycloak Callback';
|
||||
$message = 'Anmeldung wird verarbeitet.';
|
||||
$redirectTarget = '/';
|
||||
|
||||
if ($state === '' || $expectedState === '' || !hash_equals($expectedState, $state)) {
|
||||
http_response_code(400);
|
||||
$message = 'State-Pruefung fehlgeschlagen. Bitte den Login erneut starten.';
|
||||
} elseif ($code === '') {
|
||||
http_response_code(400);
|
||||
$message = 'Kein Authorization Code von Keycloak erhalten.';
|
||||
} else {
|
||||
unset($_SESSION['keycloak_oauth_state']);
|
||||
|
||||
$tokenExchange = $auth->exchangeAuthorizationCode($code);
|
||||
|
||||
if (($tokenExchange['success'] ?? false) !== true) {
|
||||
http_response_code(502);
|
||||
$message = (string) ($tokenExchange['error'] ?? 'Token-Austausch mit Keycloak fehlgeschlagen.');
|
||||
} else {
|
||||
/** @var array<string, mixed> $tokenPayload */
|
||||
$tokenPayload = $tokenExchange['data'];
|
||||
$accessToken = (string) ($tokenPayload['access_token'] ?? '');
|
||||
|
||||
if ($accessToken === '') {
|
||||
http_response_code(502);
|
||||
$message = 'Keycloak hat kein Access Token geliefert.';
|
||||
} else {
|
||||
$userInfo = $auth->fetchUserInfo($accessToken);
|
||||
|
||||
if (($userInfo['success'] ?? false) !== true) {
|
||||
http_response_code(502);
|
||||
$message = (string) ($userInfo['error'] ?? 'Userinfo-Abruf fehlgeschlagen.');
|
||||
} else {
|
||||
/** @var array<string, mixed> $userPayload */
|
||||
$userPayload = $userInfo['data'];
|
||||
$auth->establishSession($tokenPayload, $userPayload);
|
||||
header('Location: ' . $redirectTarget, true, 302);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?><!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title><?= htmlspecialchars($title, ENT_QUOTES) ?></title>
|
||||
<link rel="stylesheet" href="/assets/auth/login.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="login-shell">
|
||||
<section class="login-panel">
|
||||
<div class="login-panel-top">
|
||||
<p class="login-kicker">Kusche.Berlin</p>
|
||||
<h1><?= htmlspecialchars($title, ENT_QUOTES) ?></h1>
|
||||
<p class="login-copy"><?= htmlspecialchars($message, ENT_QUOTES) ?></p>
|
||||
</div>
|
||||
<div class="login-actions">
|
||||
<a class="login-button login-button-secondary" href="/auth/login">Zurueck zum Login</a>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
22
public/auth/keycloak/index.php
Normal file
22
public/auth/keycloak/index.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once dirname(__DIR__, 3) . '/src/App/bootstrap.php';
|
||||
|
||||
use App\ConfigLoader;
|
||||
use App\KeycloakAuth;
|
||||
|
||||
session_start();
|
||||
|
||||
$projectRoot = dirname(__DIR__, 3);
|
||||
$auth = new KeycloakAuth(ConfigLoader::load($projectRoot, 'keycloak'));
|
||||
$loginUrl = $auth->loginUrl();
|
||||
|
||||
if ($loginUrl === null) {
|
||||
header('Location: /auth/login');
|
||||
exit;
|
||||
}
|
||||
|
||||
header('Location: ' . $loginUrl, true, 302);
|
||||
exit;
|
||||
26
public/auth/login/index.php
Normal file
26
public/auth/login/index.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once dirname(__DIR__, 3) . '/src/App/bootstrap.php';
|
||||
|
||||
use App\ConfigLoader;
|
||||
use App\KeycloakAuth;
|
||||
|
||||
session_start();
|
||||
|
||||
$projectRoot = dirname(__DIR__, 3);
|
||||
$auth = new KeycloakAuth(ConfigLoader::load($projectRoot, 'keycloak'));
|
||||
$previewUrl = $auth->allowDesktopPreview()
|
||||
? '/?' . urlencode($auth->previewQueryKey()) . '=1'
|
||||
: null;
|
||||
|
||||
$loginScreen = [
|
||||
'branding' => $auth->branding(),
|
||||
'login_url' => $auth->isConfigured() ? '/auth/keycloak' : null,
|
||||
'preview_url' => $previewUrl,
|
||||
'keycloak_ready' => $auth->isConfigured(),
|
||||
'callback_url' => $auth->redirectUri(),
|
||||
];
|
||||
|
||||
require $projectRoot . '/partials/auth/login_screen.php';
|
||||
28
public/auth/logout/index.php
Normal file
28
public/auth/logout/index.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once dirname(__DIR__, 3) . '/src/App/bootstrap.php';
|
||||
|
||||
use App\ConfigLoader;
|
||||
use App\KeycloakAuth;
|
||||
|
||||
session_start();
|
||||
|
||||
$projectRoot = dirname(__DIR__, 3);
|
||||
$auth = new KeycloakAuth(ConfigLoader::load($projectRoot, 'keycloak'));
|
||||
$logoutUrl = null;
|
||||
|
||||
if ($auth->isConfigured() && $auth->isAuthenticated()) {
|
||||
$logoutUrl = $auth->logoutUrl();
|
||||
}
|
||||
|
||||
$auth->logout();
|
||||
|
||||
if ($logoutUrl !== null) {
|
||||
header('Location: ' . $logoutUrl, true, 302);
|
||||
exit;
|
||||
}
|
||||
|
||||
header('Location: /auth/login', true, 302);
|
||||
exit;
|
||||
Reference in New Issue
Block a user