From 39b2fa58be2a62a221f93d7866ae2c0d454fd8c8 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 12 May 2025 15:12:22 +0400 Subject: [PATCH] =?UTF-8?q?g=C3=A9n=C3=A9rifier=20la=20m=C3=A9thode=20d'au?= =?UTF-8?q?thentification?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nur_src/b/authnz/AuthzManager.php | 122 ++++++++++++++++++++++++--- nur_src/b/authnz/CasAuthzManager.php | 99 ++++++++++++++++++++++ nur_src/b/authnz/ExtAuthzManager.php | 78 +++++++++++++++++ nur_src/b/authnz/ExtUserManager.php | 8 ++ nur_src/v/vp/AInitAuthzPage.php | 4 +- nur_src/v/vp/AInitPage.php | 5 ++ nur_src/v/vp/AppExtauthPage.php | 68 +++++++++++++++ nur_src/v/vp/BasicPage.php | 2 +- nur_src/v/vp/NavigablePage.php | 2 +- nur_src/v/vp/TAuthzLoginPage.php | 19 +++++ nur_src/v/vp/TFormLoginPage.php | 2 +- 11 files changed, 394 insertions(+), 15 deletions(-) create mode 100644 nur_src/b/authnz/ExtAuthzManager.php create mode 100644 nur_src/b/authnz/ExtUserManager.php create mode 100644 nur_src/v/vp/AppExtauthPage.php create mode 100644 nur_src/v/vp/TAuthzLoginPage.php diff --git a/nur_src/b/authnz/AuthzManager.php b/nur_src/b/authnz/AuthzManager.php index 12b8129..f188bc2 100644 --- a/nur_src/b/authnz/AuthzManager.php +++ b/nur_src/b/authnz/AuthzManager.php @@ -1,12 +1,22 @@ getCookieKey(), false); if ($value === false) return false; - if (!preg_match('/^(cas|form|):(.*)$/', $value, $ms)) return false; + if (!preg_match('/^(cas|form|ext|):(.*)$/', $value, $ms)) return false; $authType = $ms[1]; $username = $ms[2]; return true; @@ -191,6 +201,22 @@ class AuthzManager { page::redirect(page::bu($loginUrl, $params)); } + function extLogin(string $username): bool { + # l'utilisateur doit exister + $user = $this->getUserManager()->getAuthzUser($username, null); + # ce doit être un utilisateur valide + if ($user !== null && $user->isValid()) { + $this->setCookie($username, "ext"); + $this->initSession(self::STATUS_INITIAL); + session::set(self::SESSION_KEY_USERNAME, $username); + $this->onAuthOk($username); + session::set(self::SESSION_KEY_USER, $user); + $this->onAuthzOk($user); + return true; + } + return false; + } + function formLogin(string $username, string $password): bool { # l'utilisateur doit exister $user = $this->getUserManager()->getAuthzUser($username, null); @@ -202,7 +228,7 @@ class AuthzManager { if (config::is_devel() && !$password) $password = null; if ($password === null || $user->validatePassword($password)) { # c'est bon - $this->initSession(self::STATUS_INITIAL, null); + $this->initSession(self::STATUS_INITIAL); session::set(self::SESSION_KEY_USERNAME, $username); $this->onAuthOk($username); session::set(self::SESSION_KEY_USER, $user); @@ -221,14 +247,11 @@ class AuthzManager { $this->onAuthOk($username); # l'utilisateur doit exister $user = $this->getUserManager()->getAuthzUser($username, $overrides); - if ($user !== null) { - # ce doit être un utilisteur valide - if ($user->isValid()) { - # c'est bon - session::set(self::SESSION_KEY_USER, $user); - $this->onAuthzOk($user); - return true; - } + # ce doit être un utilisteur valide + if ($user !== null && $user->isValid()) { + session::set(self::SESSION_KEY_USER, $user); + $this->onAuthzOk($user); + return true; } return false; } @@ -317,4 +340,83 @@ class AuthzManager { /** Traiter le cas où l'utilisateur a été autorisé avec succès. */ function onAuthzOk(IAuthzUser $authz): void { } + + ############################################################################# + # Page login + + private $username = null; + private $authType = null; + + function beforeSetup(AInitAuthzPage $page): void { + # initialiser la session avant setup. ainsi, dans les fonction beforeSetup(), + # setup() et afterSetup(), la session est disponible + $username = P::get("u"); + $password = P::get("p"); + $destPage = F::get("d", $page->getMainUrl()); + $page->_ensureFormLoginAndRedirect($username, $password, $destPage); + + $this->checkSession($this->username, $this->authType); + } + + function print(AInitAuthzPage $page): void { + page::no_cache(); + $username = P::get("u"); + $password = P::get("p"); + + ly::row(); + vo::h1(["class" => "text-center", q($page->TITLE())]); + + ly::col(["sm" => 6, "sm-push" => 3]); + $status = $this->getStatus(); + switch ($status) { + case authz::DISCONNECTED: + msg::warning("Vous avez été déconnecté. Veuillez vous reconnecter"); + break; + case authz::UNAUTHORIZED: + msg::error(["user" => [ + "Connecté en tant que ", + v::b($this->getAuth()), + ", vous n'êtes pas autorisé à accéder à la page que vous avez demandé.", + ]]); + break; + } + + ly::panel("Connexion par identifiant/mot de passe"); + fo::start([ + "type" => "basic", + "action" => "", + "method" => "post", + ]); + fo::text("Identifiant", "u", $username?: $this->username, [ + "accesskey" => "q", + "placeholder" => "Votre identifiant", + ]); + fo::password("Mot de passe", "p", $password, [ + "placeholder" => "Votre mot de passe", + ]); + if ($username || $password) { + msg::error("$username: Votre identifiant et/ou votre mot de passe sont incorrects"); + } elseif ($username === "") { + msg::error("Vous devez saisir votre identifiant"); + } elseif ($password === "") { + msg::error("Vous devez saisir votre mot de passe"); + } + fo::submit(["Connexion", "accesskey" => "r"]); + if ($this->isAuth() && $this->authType === "form") { + if ($status != authz::UNAUTHORIZED) { + msg::warning(["user" => [ + "Connecté en tant que ", + v::b($this->getAuth()), + ", vous n'êtes pas autorisé à accéder à cette application.", + ]]); + } + fo::submit([ + "Vous déconnecter", "accesskey" => "z", + "formmethod" => "get", "formaction" => $page->getLogoutUrl(), + ]); + } + fo::end(); + + ly::end(); + } } diff --git a/nur_src/b/authnz/CasAuthzManager.php b/nur_src/b/authnz/CasAuthzManager.php index da544e0..ec02b97 100644 --- a/nur_src/b/authnz/CasAuthzManager.php +++ b/nur_src/b/authnz/CasAuthzManager.php @@ -1,8 +1,18 @@ userManager; } + + private $destPage = null; + + function beforeSetup(AInitAuthzPage $page): void { + # initialiser la session avant setup. ainsi, dans les fonction beforeSetup(), + # setup() et afterSetup(), la session est disponible + $this->destPage = F::get("d", $page->getMainUrl()); + $this->checkSession($username, $authType); + + if ($authType === "cas" && F::get("a")) { + # autologin + $casauthUrl = config::k("url")."/".$page->getCasauthUrl(); + page::redirect(page::bu($page->getCasLoginUrl(), [ + "service" => page::bu($casauthUrl, [ + "r" => $page->getLoginUrl(), + "d" => $this->destPage, + ]) + ])); + } + } + + function print(AInitAuthzPage $page): void { + page::no_cache(); + ly::row(); + vo::h1(["class" => "text-center", q($page->TITLE())]); + + ly::col(["sm" => 6, "sm-push" => 3]); + $status = $this->getStatus(); + switch ($status) { + case authz::DISCONNECTED: + msg::warning("Vous avez été déconnecté. Veuillez vous reconnecter"); + break; + case authz::UNAUTHORIZED: + msg::error(["user" => [ + "Connecté en tant que ", + v::b($this->getAuth()), + ", vous n'êtes pas autorisé à accéder à la page que vous avez demandé.", + ]]); + break; + } + + ly::panel("Connexion par CAS"); + if ($page->isDevauthAllowed()) { + fo::start([ + "type" => "basic", + "action" => $page->getCasauthUrl(), + "method" => "get", + ]); + fo::hidden("r", $page->getLoginUrl()); + fo::hidden("d", $this->destPage); + } else { + fo::start([ + "type" => "basic", + "action" => $page->getCasLoginUrl(), + "method" => "get", + ]); + $casauthUrl = config::k("url")."/".$page->getCasauthUrl(); + fo::hidden("service", page::bu($casauthUrl, [ + "r" => $page->getLoginUrl(), + "d" => $this->destPage, + ])); + } + #fo::p("Si vous avez un compte à l'université, vous pouvez vous connecter via CAS"); + vo::p("Si vous avez un compte à l'université, vous pouvez vous connecter via CAS"); + if ($this->isAuth()) { + if ($status != authz::UNAUTHORIZED) { + msg::warning(["user" => [ + "Connecté en tant que ", + v::b(authz::get_auth()), + ", vous n'êtes pas autorisé à accéder à cette application.", + ]]); + } + fo::submit([ + icon::logout("Vous déconnecter"), + "formaction" => $page->getLogoutUrl(), + "accesskey" => "z", + ]); + fo::hidden("renew", "true"); + fo::submit([ + icon::login("Changer de compte"), + "accesskey" => "r", + ]); + } else { + fo::submit(["Connexion par CAS", "accesskey" => "r"]); + } + fo::end(); + + ly::end(); + } } diff --git a/nur_src/b/authnz/ExtAuthzManager.php b/nur_src/b/authnz/ExtAuthzManager.php new file mode 100644 index 0000000..20e28d3 --- /dev/null +++ b/nur_src/b/authnz/ExtAuthzManager.php @@ -0,0 +1,78 @@ +destPage = F::get("d", $page->getMainUrl()); + $this->checkSession($username, $authType); + + if ($authType === "ext" && F::get("a")) { + # autologin + $extauthUrl = config::k("url")."/".$page->getExtauthUrl(); + page::redirect(page::bu($extauthUrl, [ + "d" => $this->destPage, + ])); + } + } + + function print(AInitAuthzPage $page): void { + page::no_cache(); + ly::row(); + vo::h1(["class" => "text-center", q($page->TITLE())]); + + ly::col(["sm" => 6, "sm-push" => 3]); + $status = $this->getStatus(); + switch ($status) { + case authz::DISCONNECTED: + msg::warning("Vous avez été déconnecté. Veuillez vous reconnecter"); + break; + case authz::UNAUTHORIZED: + msg::error(["user" => [ + "Connecté en tant que ", + v::b($this->getAuth()), + ", vous n'êtes pas autorisé à accéder à la page que vous avez demandé.", + ]]); + break; + } + + ly::panel("Connexion"); + fo::start([ + "type" => "basic", + "action" => $page->getExtauthUrl(), + "method" => "get", + ]); + fo::hidden("d", $this->destPage); + vo::p("Si vous avez un compte à l'université, vous pouvez vous connecter"); + if ($this->isAuth()) { + if ($status != authz::UNAUTHORIZED) { + msg::warning(["user" => [ + "Connecté en tant que ", + v::b($this->getAuth()), + ", vous n'êtes pas autorisé à accéder à cette application.", + ]]); + } + } else { + fo::submit(["Connexion", "accesskey" => "r"]); + } + fo::end(); + + ly::end(); + } +} diff --git a/nur_src/b/authnz/ExtUserManager.php b/nur_src/b/authnz/ExtUserManager.php new file mode 100644 index 0000000..4ca8f19 --- /dev/null +++ b/nur_src/b/authnz/ExtUserManager.php @@ -0,0 +1,8 @@ + $username]; + } +} diff --git a/nur_src/v/vp/AInitAuthzPage.php b/nur_src/v/vp/AInitAuthzPage.php index f316bba..bdafa02 100644 --- a/nur_src/v/vp/AInitAuthzPage.php +++ b/nur_src/v/vp/AInitAuthzPage.php @@ -64,7 +64,7 @@ class AInitAuthzPage extends AInitPage implements IBasicPage { } } - protected function ensureAuthOrRedirect(bool $requireAuth, bool $requireAuthz, $requireRole, $requirePerm): void { + protected function _ensureAuthOrRedirect(bool $requireAuth, bool $requireAuthz, $requireRole, $requirePerm): void { $am = authz::manager(); $loginUrl = $this->getLoginUrl(); $destUrl = page::self(true); @@ -88,7 +88,7 @@ class AInitAuthzPage extends AInitPage implements IBasicPage { if ($am->isAuth()) $am->setConnected(); } - protected function ensureFormLoginAndRedirect(?string $username, ?string $password, string $destUrl): void { + function _ensureFormLoginAndRedirect(?string $username, ?string $password, string $destUrl): void { if ($username === null && $password === null) return; if (authz::manager()->formLogin($username, $password)) { page::redirect($destUrl); diff --git a/nur_src/v/vp/AInitPage.php b/nur_src/v/vp/AInitPage.php index 08fd920..e497785 100644 --- a/nur_src/v/vp/AInitPage.php +++ b/nur_src/v/vp/AInitPage.php @@ -40,6 +40,11 @@ abstract class AInitPage extends AbstractPage { } } + /** obtenir l'url d'authentification externe. cet url doit être *relatif* */ + function getExtauthUrl(): string { + return page::bu(config::k("extauth_page", "_extauth.php")); + } + function getLogoutUrl(): string { return page::bu(config::k("logout_page","_logout.php")); } diff --git a/nur_src/v/vp/AppExtauthPage.php b/nur_src/v/vp/AppExtauthPage.php new file mode 100644 index 0000000..75a4653 --- /dev/null +++ b/nur_src/v/vp/AppExtauthPage.php @@ -0,0 +1,68 @@ +extLogin($user)) { + $destUrl = F::get("d"); + if ($destUrl && !$this->isDebug()) page::redirect($destUrl); + } + } else { + $user = "NONE"; + } + + $this->user = $user; + $this->destUrl = $destUrl; + } + + private $destUrl; + + function print(): void { + page::content_type("text/plain"); + page::no_cache(); + if ($this->isDebug()) { + echo "destUrl: $this->destUrl\n"; + echo "--- \$_SERVER\n\n"; + foreach ($_SERVER as $name => $value) { + echo "$name: $value\n"; + } + echo "\n--- \$_REQUEST\n\n"; + foreach ($_REQUEST as $name => $value) { + echo "$name: $value\n"; + } + echo "\n--- \$_SESSION\n\n"; + foreach ($_SESSION as $name => $value) { + echo "$name: ".var_export($value, true)."\n"; + } + } else { + echo $this->user; + } + } +} diff --git a/nur_src/v/vp/BasicPage.php b/nur_src/v/vp/BasicPage.php index 6eb4ef6..c83ca4a 100644 --- a/nur_src/v/vp/BasicPage.php +++ b/nur_src/v/vp/BasicPage.php @@ -13,7 +13,7 @@ class BasicPage extends AInitAuthzPage { function afterConfig(): void { # initialiser la session avant setup. ainsi, dans les fonction beforeSetup(), # setup() et afterSetup(), la session est disponible - $this->ensureAuthOrRedirect(static::REQUIRE_AUTH, static::REQUIRE_AUTHZ, static::REQUIRE_ROLE, static::REQUIRE_PERM); + $this->_ensureAuthOrRedirect(static::REQUIRE_AUTH, static::REQUIRE_AUTHZ, static::REQUIRE_ROLE, static::REQUIRE_PERM); parent::afterConfig(); } } diff --git a/nur_src/v/vp/NavigablePage.php b/nur_src/v/vp/NavigablePage.php index 23212c3..5225b6f 100644 --- a/nur_src/v/vp/NavigablePage.php +++ b/nur_src/v/vp/NavigablePage.php @@ -32,7 +32,7 @@ class NavigablePage extends AInitAuthzPage implements INavigablePage { function afterConfig(): void { # initialiser la session avant setup. ainsi, dans les fonction beforeSetup(), # setup() et afterSetup(), la session est disponible - $this->ensureAuthOrRedirect(static::REQUIRE_AUTH, static::REQUIRE_AUTHZ, static::REQUIRE_ROLE, static::REQUIRE_PERM); + $this->_ensureAuthOrRedirect(static::REQUIRE_AUTH, static::REQUIRE_AUTHZ, static::REQUIRE_ROLE, static::REQUIRE_PERM); parent::afterConfig(); } diff --git a/nur_src/v/vp/TAuthzLoginPage.php b/nur_src/v/vp/TAuthzLoginPage.php new file mode 100644 index 0000000..5517e56 --- /dev/null +++ b/nur_src/v/vp/TAuthzLoginPage.php @@ -0,0 +1,19 @@ +beforeSetup($this); + } + + function beforeSetup(): void { + $this->TLoginPage_beforeSetup(); + parent::beforeSetup(); + } + + function print(): void { + authz::manager()->print($this); + } +} diff --git a/nur_src/v/vp/TFormLoginPage.php b/nur_src/v/vp/TFormLoginPage.php index 088f1a7..387f776 100644 --- a/nur_src/v/vp/TFormLoginPage.php +++ b/nur_src/v/vp/TFormLoginPage.php @@ -17,7 +17,7 @@ trait TFormLoginPage { $username = P::get("u"); $password = P::get("p"); $destPage = F::get("d", $this->getMainUrl()); - $this->ensureFormLoginAndRedirect($username, $password, $destPage); + $this->_ensureFormLoginAndRedirect($username, $password, $destPage); authz::manager()->checkSession($flcUsername, $flcAuthType); $this->flcUsername = $flcUsername;