Request: loginRequired => loginRequirements, SsoRequest, SAML

This commit is contained in:
2024-12-30 10:41:13 +01:00
parent 50cc0fc5be
commit 2861eaa9a9
15 changed files with 316 additions and 154 deletions

View File

@@ -2,11 +2,9 @@
namespace Core\Objects\SSO;
use Core\Driver\SQL\Condition\Compare;
use Core\Objects\Context;
use Core\Objects\DatabaseEntity\SsoProvider;
use Core\Objects\DatabaseEntity\User;
use DOMDocument;
use Core\Objects\DatabaseEntity\SsoRequest;
class SSOProviderSAML extends SSOProvider {
@@ -18,19 +16,19 @@ class SSOProviderSAML extends SSOProvider {
public function login(Context $context, ?string $redirectUrl) {
$sql = $context->getSQL();
$settings = $context->getSettings();
$baseUrl = $settings->getBaseUrl();
$params = ["provider" => $this->getIdentifier()];
if (!empty($redirectUrl)) {
$params["redirect"] = $redirectUrl;
$ssoRequest = SsoRequest::create($sql, $this, $redirectUrl);
if (!$ssoRequest) {
throw new \Exception("Could not save SSO request: " . $sql->getLastError());
}
$acsUrl = $baseUrl . "/api/sso/saml?" . http_build_query($params);
$acsUrl = $baseUrl . "/api/sso/saml";
$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",
"ID" => "_" . uniqid(),
"ID" => $ssoRequest->getIdentifier(),
"Version" => "2.0",
"IssueInstant" => gmdate('Y-m-d\TH:i:s\Z'),
"Destination" => $this->ssoUrl,
@@ -48,70 +46,4 @@ class SSOProviderSAML extends SSOProvider {
$context->router->redirect(302, $samlUrl);
die();
}
public function parseResponse(Context $context, string $response): ?User {
$xml = new DOMDocument();
$xml->loadXML($response);
// Validate XML and extract user info
if (!$xml->getElementsByTagName("Assertion")->length) {
return null;
}
$assertion = $xml->getElementsByTagName('Assertion')->item(0);
if (!$assertion->getElementsByTagName("Signature")->length) {
return null;
}
$signature = $assertion->getElementsByTagName("Signature")->item(0);
// TODO: parse and validate signature
$statusCode = $xml->getElementsByTagName('StatusCode')->item(0);
if ($statusCode->getAttribute("Value") !== "urn:oasis:names:tc:SAML:2.0:status:Success") {
return null;
}
$issuer = $xml->getElementsByTagName('Issuer')->item(0)->nodeValue;
// TODO: validate issuer
$username = $xml->getElementsByTagName('NameID')->item(0)->nodeValue;
$attributes = [];
foreach ($xml->getElementsByTagName('Attribute') as $attribute) {
$name = $attribute->getAttribute('Name');
$value = $attribute->getElementsByTagName('AttributeValue')->item(0)->nodeValue;
$attributes[$name] = $value;
}
$email = $attributes["email"];
$fullName = [];
if (isset($attributes["firstName"])) {
$fullName[] = $attributes["firstName"];
}
if (isset($attributes["lastName"])) {
$fullName[] = $attributes["lastName"];
}
$fullName = implode(" ", $fullName);
$user = User::findBy(User::createBuilder($context->getSQL(), true)
->where(new Compare("email", $email), new Compare("name", $username)));
if ($user === false) {
return null;
} else if ($user === null) {
$user = new User();
$user->fullName = $fullName;
$user->email = $email;
$user->name = $username;
$user->password = null;
$user->ssoProvider = $this;
$user->confirmed = true;
$user->active = true;
$user->groups = []; // TODO: create a possibility to set auto-groups for SSO registered users
}
return $user;
}
}