2024-12-30 09:44:47 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Core\Objects\SSO;
|
|
|
|
|
|
|
|
use Core\Objects\Context;
|
|
|
|
use Core\Objects\DatabaseEntity\SsoProvider;
|
2024-12-30 10:41:13 +01:00
|
|
|
use Core\Objects\DatabaseEntity\SsoRequest;
|
2024-12-30 09:44:47 +01:00
|
|
|
|
|
|
|
class SSOProviderSAML extends SSOProvider {
|
|
|
|
|
|
|
|
const TYPE = "saml";
|
|
|
|
|
|
|
|
public function __construct(?int $id = null) {
|
|
|
|
parent::__construct(self::TYPE, $id);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function login(Context $context, ?string $redirectUrl) {
|
|
|
|
|
2024-12-30 10:41:13 +01:00
|
|
|
$sql = $context->getSQL();
|
2024-12-30 09:44:47 +01:00
|
|
|
$settings = $context->getSettings();
|
|
|
|
$baseUrl = $settings->getBaseUrl();
|
2024-12-30 10:41:13 +01:00
|
|
|
$ssoRequest = SsoRequest::create($sql, $this, $redirectUrl);
|
|
|
|
if (!$ssoRequest) {
|
|
|
|
throw new \Exception("Could not save SSO request: " . $sql->getLastError());
|
2024-12-30 09:44:47 +01:00
|
|
|
}
|
|
|
|
|
2024-12-30 10:41:13 +01:00
|
|
|
$acsUrl = $baseUrl . "/api/sso/saml";
|
2024-12-30 09:44:47 +01:00
|
|
|
$samlp = html_tag_ex("samlp:AuthnRequest", [
|
|
|
|
"xmlns:samlp" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
|
|
|
"xmlns:saml" => "urn:oasis:names:tc:SAML:2.0:assertion",
|
2024-12-30 10:41:13 +01:00
|
|
|
"ID" => $ssoRequest->getIdentifier(),
|
2024-12-30 09:44:47 +01:00
|
|
|
"Version" => "2.0",
|
|
|
|
"IssueInstant" => gmdate('Y-m-d\TH:i:s\Z'),
|
|
|
|
"Destination" => $this->ssoUrl,
|
|
|
|
"ProtocolBinding" => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
|
|
|
|
"AssertionConsumerServiceURL" => $acsUrl
|
2024-12-31 13:53:57 +01:00
|
|
|
], html_tag("saml:Issuer", [], $this->clientId), false);
|
2024-12-30 09:44:47 +01:00
|
|
|
|
2024-12-31 13:53:57 +01:00
|
|
|
$samlRequest = base64_encode($samlp);
|
|
|
|
$req = new \Core\API\Template\Render($context);
|
|
|
|
$success = $req->execute([
|
|
|
|
"file" => "sso.twig",
|
|
|
|
"parameters" => [
|
|
|
|
"sso" => [
|
|
|
|
"url" => $this->ssoUrl,
|
|
|
|
"data" => [
|
|
|
|
"SAMLRequest" => $samlRequest
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]);
|
2024-12-30 09:44:47 +01:00
|
|
|
|
2024-12-31 13:53:57 +01:00
|
|
|
if (!$success) {
|
|
|
|
throw new \Exception("Could not redirect: " . $req->getLastError());
|
2024-12-30 09:44:47 +01:00
|
|
|
}
|
|
|
|
|
2024-12-31 13:53:57 +01:00
|
|
|
die($req->getResult()["html"]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function validateSignature(string $what, string $signature, int $algorithm) : bool {
|
|
|
|
$publicKey = openssl_pkey_get_public($this->certificate);
|
|
|
|
if (!$publicKey) {
|
|
|
|
throw new \Exception("Failed to load certificate: " . openssl_error_string());
|
|
|
|
}
|
|
|
|
|
|
|
|
$result = openssl_verify($what, $signature, $publicKey, $algorithm);
|
|
|
|
if ($result === 1) {
|
|
|
|
return true;
|
|
|
|
} else if ($result === 0) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
throw new \Exception("Failed to validate signature: " . openssl_error_string());
|
|
|
|
}
|
2024-12-30 09:44:47 +01:00
|
|
|
}
|
|
|
|
}
|