diff --git a/Core/API/SsoAPI.class.php b/Core/API/SsoAPI.class.php index 97f0413..97d8617 100644 --- a/Core/API/SsoAPI.class.php +++ b/Core/API/SsoAPI.class.php @@ -3,6 +3,7 @@ namespace Core\API { use Core\Objects\Context; + use Core\Objects\DatabaseEntity\SsoProvider; use Core\Objects\DatabaseEntity\User; abstract class SsoAPI extends Request { @@ -10,16 +11,18 @@ namespace Core\API { 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(); if ($user->getId() === null) { // user didn't exit yet. try to insert into database if (!$user->save($sql)) { return $this->createError("Could not create user: " . $sql->getLastError()); } - } - - if (!$this->createSession($user)) { + } else if (!$user->isActive()) { + return $this->createError("This user is currently disabled. Contact the server administrator, if you believe this is a mistake."); + } 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; } @@ -221,7 +224,7 @@ namespace Core\API\Sso { if (!$parsedResponse->wasSuccessful()) { return $this->createError("Error parsing SAMLResponse: " . $parsedResponse->getError()); } else { - return $this->processLogin($parsedResponse->getUser(), $parsedResponse->getRedirectURL()); + return $this->processLogin($parsedResponse->getProvider(), $parsedResponse->getUser(), $parsedResponse->getRedirectURL()); } $sql = $this->context->getSQL(); diff --git a/Core/Objects/DatabaseEntity/User.class.php b/Core/Objects/DatabaseEntity/User.class.php index c215c70..62296ff 100644 --- a/Core/Objects/DatabaseEntity/User.class.php +++ b/Core/Objects/DatabaseEntity/User.class.php @@ -176,4 +176,8 @@ class User extends DatabaseEntity { public function isLocalAccount(): bool { return $this->ssoProvider === null; } + + public function getSsoProvider(): ?SsoProvider { + return $this->ssoProvider; + } } \ No newline at end of file diff --git a/Core/Objects/SSO/SAMLResponse.class.php b/Core/Objects/SSO/SAMLResponse.class.php index d55b64d..590a0fd 100644 --- a/Core/Objects/SSO/SAMLResponse.class.php +++ b/Core/Objects/SSO/SAMLResponse.class.php @@ -2,6 +2,7 @@ namespace Core\Objects\SSO; +use Core\Driver\Logger\Logger; use Core\Driver\SQL\Condition\Compare; use Core\Objects\Context; use Core\Objects\DatabaseEntity\SsoProvider; @@ -16,6 +17,9 @@ class SAMLResponse { private ?User $user; private ?SsoRequest $request; + private function __construct() { + } + private static function createSuccess(SsoRequest $request, User $user) : SAMLResponse { $response = new SAMLResponse(); $response->user = $user; @@ -34,6 +38,7 @@ class SAMLResponse { public static function parseResponse(Context $context, string $response) : SAMLResponse { $sql = $context->getSQL(); + $logger = new Logger("SAML", $sql); $xml = new DOMDocument(); $xml->loadXML($response); @@ -90,6 +95,7 @@ class SAMLResponse { $issuer = $xml->getElementsByTagName('Issuer')->item(0)->nodeValue; // TODO: validate issuer + // TODO: create a possibility to map attribute values to user properties $username = $xml->getElementsByTagName('NameID')->item(0)->nodeValue; $attributes = []; foreach ($xml->getElementsByTagName('Attribute') as $attribute) { @@ -111,7 +117,8 @@ class SAMLResponse { $fullName = implode(" ", $fullName); $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) { return self::createError($ssoRequest, "Error fetching user: " . $sql->getLastError()); @@ -146,4 +153,8 @@ class SAMLResponse { return $this->request->getRedirectUrl(); } + public function getProvider(): SSOProvider { + return $this->request->getProvider(); + } + } \ No newline at end of file