This commit is contained in:
Roman 2024-12-30 12:10:03 +01:00
parent 2861eaa9a9
commit 9788289260
3 changed files with 24 additions and 6 deletions

@ -3,6 +3,7 @@
namespace Core\API { namespace Core\API {
use Core\Objects\Context; use Core\Objects\Context;
use Core\Objects\DatabaseEntity\SsoProvider;
use Core\Objects\DatabaseEntity\User; use Core\Objects\DatabaseEntity\User;
abstract class SsoAPI extends Request { abstract class SsoAPI extends Request {
@ -10,16 +11,18 @@ namespace Core\API {
parent::__construct($context, $externalCall, $params); parent::__construct($context, $externalCall, $params);
} }
protected function processLogin(User $user, ?string $redirectUrl): bool { protected function processLogin(SsoProvider $provider, User $user, ?string $redirectUrl): bool {
$sql = $this->context->getSQL(); $sql = $this->context->getSQL();
if ($user->getId() === null) { if ($user->getId() === null) {
// user didn't exit yet. try to insert into database // user didn't exit yet. try to insert into database
if (!$user->save($sql)) { if (!$user->save($sql)) {
return $this->createError("Could not create user: " . $sql->getLastError()); return $this->createError("Could not create user: " . $sql->getLastError());
} }
} } else if (!$user->isActive()) {
return $this->createError("This user is currently disabled. Contact the server administrator, if you believe this is a mistake.");
if (!$this->createSession($user)) { } else if ($user->getSsoProvider()?->getIdentifier() !== $provider->getIdentifier()) {
return $this->createError("An existing user is not managed by the used identity provider");
} else if (!$this->createSession($user)) {
return false; return false;
} }
@ -221,7 +224,7 @@ namespace Core\API\Sso {
if (!$parsedResponse->wasSuccessful()) { if (!$parsedResponse->wasSuccessful()) {
return $this->createError("Error parsing SAMLResponse: " . $parsedResponse->getError()); return $this->createError("Error parsing SAMLResponse: " . $parsedResponse->getError());
} else { } else {
return $this->processLogin($parsedResponse->getUser(), $parsedResponse->getRedirectURL()); return $this->processLogin($parsedResponse->getProvider(), $parsedResponse->getUser(), $parsedResponse->getRedirectURL());
} }
$sql = $this->context->getSQL(); $sql = $this->context->getSQL();

@ -176,4 +176,8 @@ class User extends DatabaseEntity {
public function isLocalAccount(): bool { public function isLocalAccount(): bool {
return $this->ssoProvider === null; return $this->ssoProvider === null;
} }
public function getSsoProvider(): ?SsoProvider {
return $this->ssoProvider;
}
} }

@ -2,6 +2,7 @@
namespace Core\Objects\SSO; namespace Core\Objects\SSO;
use Core\Driver\Logger\Logger;
use Core\Driver\SQL\Condition\Compare; use Core\Driver\SQL\Condition\Compare;
use Core\Objects\Context; use Core\Objects\Context;
use Core\Objects\DatabaseEntity\SsoProvider; use Core\Objects\DatabaseEntity\SsoProvider;
@ -16,6 +17,9 @@ class SAMLResponse {
private ?User $user; private ?User $user;
private ?SsoRequest $request; private ?SsoRequest $request;
private function __construct() {
}
private static function createSuccess(SsoRequest $request, User $user) : SAMLResponse { private static function createSuccess(SsoRequest $request, User $user) : SAMLResponse {
$response = new SAMLResponse(); $response = new SAMLResponse();
$response->user = $user; $response->user = $user;
@ -34,6 +38,7 @@ class SAMLResponse {
public static function parseResponse(Context $context, string $response) : SAMLResponse { public static function parseResponse(Context $context, string $response) : SAMLResponse {
$sql = $context->getSQL(); $sql = $context->getSQL();
$logger = new Logger("SAML", $sql);
$xml = new DOMDocument(); $xml = new DOMDocument();
$xml->loadXML($response); $xml->loadXML($response);
@ -90,6 +95,7 @@ class SAMLResponse {
$issuer = $xml->getElementsByTagName('Issuer')->item(0)->nodeValue; $issuer = $xml->getElementsByTagName('Issuer')->item(0)->nodeValue;
// TODO: validate issuer // TODO: validate issuer
// TODO: create a possibility to map attribute values to user properties
$username = $xml->getElementsByTagName('NameID')->item(0)->nodeValue; $username = $xml->getElementsByTagName('NameID')->item(0)->nodeValue;
$attributes = []; $attributes = [];
foreach ($xml->getElementsByTagName('Attribute') as $attribute) { foreach ($xml->getElementsByTagName('Attribute') as $attribute) {
@ -111,7 +117,8 @@ class SAMLResponse {
$fullName = implode(" ", $fullName); $fullName = implode(" ", $fullName);
$user = User::findBy(User::createBuilder($context->getSQL(), true) $user = User::findBy(User::createBuilder($context->getSQL(), true)
->where(new Compare("email", $email), new Compare("name", $username))); ->where(new Compare("email", $email), new Compare("name", $username))
->fetchEntities());
if ($user === false) { if ($user === false) {
return self::createError($ssoRequest, "Error fetching user: " . $sql->getLastError()); return self::createError($ssoRequest, "Error fetching user: " . $sql->getLastError());
@ -146,4 +153,8 @@ class SAMLResponse {
return $this->request->getRedirectUrl(); return $this->request->getRedirectUrl();
} }
public function getProvider(): SSOProvider {
return $this->request->getProvider();
}
} }