Casuser auth backend: add user access filters feature
This commit is contained in:
parent
82122089f9
commit
57aedc4869
8 changed files with 183 additions and 32 deletions
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1,7 +1,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: 2024-01-23 18:15+0000\n"
|
||||
"POT-Creation-Date: 2024-02-21 09:12+0000\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Benjamin Renard <brenard@easter-eggs.com>\n"
|
||||
"Language-Team: \n"
|
||||
|
@ -30,7 +30,7 @@ msgstr ""
|
|||
msgid "Unknown"
|
||||
msgstr "Inconnu"
|
||||
|
||||
#: Db.php:78
|
||||
#: Db.php:93
|
||||
msgid "Unable to connect to the database."
|
||||
msgstr "Impossible de se connecter à la base de données."
|
||||
|
||||
|
@ -46,7 +46,7 @@ msgstr "Connection"
|
|||
msgid "Authentication required"
|
||||
msgstr "Authentication requise"
|
||||
|
||||
#: Auth/Http.php:124 Auth/Http.php:127 Url.php:185
|
||||
#: Auth/Http.php:124 Auth/Http.php:127 Url.php:185 Auth.php:340 Auth.php:343
|
||||
msgid "Access denied"
|
||||
msgstr "Accès interdit"
|
||||
|
||||
|
@ -54,6 +54,10 @@ msgstr "Accès interdit"
|
|||
msgid "You must login to access this page."
|
||||
msgstr "Vous devez vous connecter pour accéder à cette page."
|
||||
|
||||
#: Auth/Casuser.php:88 Auth/Casuser.php:112
|
||||
msgid "Configuration error in CAS auth backend."
|
||||
msgstr "Erreur de configuration dans le backend d'authentification CAS."
|
||||
|
||||
#: Url.php:177
|
||||
msgid "Bad request"
|
||||
msgstr "Mauvaise requête"
|
||||
|
@ -120,6 +124,14 @@ msgstr "Authentication requise mais impossible pour vous authentifier."
|
|||
msgid "This request could not be processed correctly."
|
||||
msgstr "Cette requête n'a put être traitée correctement."
|
||||
|
||||
#: Auth.php:344
|
||||
msgid "You do not have access to this application."
|
||||
msgstr "Vous n'avez pas accès à cette application."
|
||||
|
||||
#: Auth.php:348
|
||||
msgid "Details:"
|
||||
msgstr "Détails :"
|
||||
|
||||
#: Cli.php:44
|
||||
msgid "Create a new project using EesyPHP framework"
|
||||
msgstr "Créer un nouveau project utilisant le framework EesyPHP"
|
||||
|
@ -261,13 +273,7 @@ msgstr ""
|
|||
"Port d'écoute spécifié invalid. Il doit s'agir d'un entier positif entre 1 "
|
||||
"et 65535."
|
||||
|
||||
#: Cli.php:418
|
||||
msgid "Can't invoke bash. Can't ask password prompt."
|
||||
msgstr ""
|
||||
"Impossible d'utiliser bash. Impossible de demander à l'utilisateur de saisir "
|
||||
"un not de passe."
|
||||
|
||||
#: Cli.php:421
|
||||
#: Cli.php:415
|
||||
msgid "Please enter password:"
|
||||
msgstr "Merci de saisir le not de passe :"
|
||||
|
||||
|
@ -300,19 +306,19 @@ msgstr "ns"
|
|||
msgid "Less than 1%s"
|
||||
msgstr "Moins de 1%s"
|
||||
|
||||
#: App.php:239 I18n.php:119
|
||||
#: App.php:242 I18n.php:119
|
||||
msgid "Hello world !"
|
||||
msgstr "Bonjour tout le monde !"
|
||||
|
||||
#: App.php:241
|
||||
#: App.php:244
|
||||
msgid "Hello world!"
|
||||
msgstr "Salut tout le monde !"
|
||||
|
||||
#: App.php:252
|
||||
#: App.php:255
|
||||
msgid "Disconnected"
|
||||
msgstr "Déconnecté"
|
||||
|
||||
#: App.php:254
|
||||
#: App.php:257
|
||||
msgid "You are now disconnected."
|
||||
msgstr "Vous êtes maintenant déconnecté."
|
||||
|
||||
|
@ -606,12 +612,12 @@ msgstr ""
|
|||
"\n"
|
||||
"Mail originalement destiné à %s."
|
||||
|
||||
#: Email.php:139
|
||||
#: Email.php:137
|
||||
#, php-format
|
||||
msgid "<p><small>%s: %s</small></p>"
|
||||
msgstr "<p><small>%s: %s</small></p>"
|
||||
|
||||
#: Email.php:140
|
||||
#: Email.php:138
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
|
@ -657,6 +663,10 @@ msgstr "Erreur : %1"
|
|||
msgid "Back"
|
||||
msgstr "Retour"
|
||||
|
||||
#: templates/access_denied.tpl:12
|
||||
msgid "Details: %1"
|
||||
msgstr "Détails : %1"
|
||||
|
||||
#: templates/empty.tpl:74
|
||||
msgid "Sign out"
|
||||
msgstr "Déconnexion"
|
||||
|
@ -701,6 +711,11 @@ msgstr ""
|
|||
"fichier <em>homepage.tpl</em> pour l'écraser. Vous pouvez également écraser "
|
||||
"le gestionnaire de l'URL racine de l'application web."
|
||||
|
||||
#~ msgid "Can't invoke bash. Can't ask password prompt."
|
||||
#~ msgstr ""
|
||||
#~ "Impossible d'utiliser bash. Impossible de demander à l'utilisateur de "
|
||||
#~ "saisir un not de passe."
|
||||
|
||||
#~ msgid "Confirmation"
|
||||
#~ msgstr "Confirmation"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"POT-Creation-Date: 2024-01-23 18:19+0000\n"
|
||||
"PO-Revision-Date: 2024-01-23 18:19+0000\n"
|
||||
"POT-Creation-Date: 2024-02-21 09:12+0000\n"
|
||||
"PO-Revision-Date: 2024-02-21 09:12+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -22,7 +22,7 @@ msgstr ""
|
|||
msgid "Unknown"
|
||||
msgstr ""
|
||||
|
||||
#: Db.php:78
|
||||
#: Db.php:93
|
||||
msgid "Unable to connect to the database."
|
||||
msgstr ""
|
||||
|
||||
|
@ -38,7 +38,7 @@ msgstr ""
|
|||
msgid "Authentication required"
|
||||
msgstr ""
|
||||
|
||||
#: Auth/Http.php:124 Auth/Http.php:127 Url.php:185
|
||||
#: Auth/Http.php:124 Auth/Http.php:127 Url.php:185 Auth.php:340 Auth.php:343
|
||||
msgid "Access denied"
|
||||
msgstr ""
|
||||
|
||||
|
@ -46,6 +46,10 @@ msgstr ""
|
|||
msgid "You must login to access this page."
|
||||
msgstr ""
|
||||
|
||||
#: Auth/Casuser.php:88 Auth/Casuser.php:112
|
||||
msgid "Configuration error in CAS auth backend."
|
||||
msgstr ""
|
||||
|
||||
#: Url.php:177
|
||||
msgid "Bad request"
|
||||
msgstr ""
|
||||
|
@ -104,6 +108,14 @@ msgstr ""
|
|||
msgid "This request could not be processed correctly."
|
||||
msgstr ""
|
||||
|
||||
#: Auth.php:344
|
||||
msgid "You do not have access to this application."
|
||||
msgstr ""
|
||||
|
||||
#: Auth.php:348
|
||||
msgid "Details:"
|
||||
msgstr ""
|
||||
|
||||
#: Cli.php:44
|
||||
msgid "Create a new project using EesyPHP framework"
|
||||
msgstr ""
|
||||
|
@ -223,11 +235,7 @@ msgid ""
|
|||
"65535."
|
||||
msgstr ""
|
||||
|
||||
#: Cli.php:418
|
||||
msgid "Can't invoke bash. Can't ask password prompt."
|
||||
msgstr ""
|
||||
|
||||
#: Cli.php:421
|
||||
#: Cli.php:415
|
||||
msgid "Please enter password:"
|
||||
msgstr ""
|
||||
|
||||
|
@ -260,19 +268,19 @@ msgstr ""
|
|||
msgid "Less than 1%s"
|
||||
msgstr ""
|
||||
|
||||
#: App.php:239 I18n.php:119
|
||||
#: App.php:242 I18n.php:119
|
||||
msgid "Hello world !"
|
||||
msgstr ""
|
||||
|
||||
#: App.php:241
|
||||
#: App.php:244
|
||||
msgid "Hello world!"
|
||||
msgstr ""
|
||||
|
||||
#: App.php:252
|
||||
#: App.php:255
|
||||
msgid "Disconnected"
|
||||
msgstr ""
|
||||
|
||||
#: App.php:254
|
||||
#: App.php:257
|
||||
msgid "You are now disconnected."
|
||||
msgstr ""
|
||||
|
||||
|
@ -523,12 +531,12 @@ msgid ""
|
|||
"Mail initially intended for %s."
|
||||
msgstr ""
|
||||
|
||||
#: Email.php:139
|
||||
#: Email.php:137
|
||||
#, php-format
|
||||
msgid "<p><small>%s: %s</small></p>"
|
||||
msgstr ""
|
||||
|
||||
#: Email.php:140
|
||||
#: Email.php:138
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
|
@ -569,6 +577,10 @@ msgstr ""
|
|||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
#: templates/access_denied.tpl:12
|
||||
msgid "Details: %1"
|
||||
msgstr ""
|
||||
|
||||
#: templates/empty.tpl:74
|
||||
msgid "Sign out"
|
||||
msgstr ""
|
||||
|
|
23
src/Auth.php
23
src/Auth.php
|
@ -328,4 +328,27 @@ class Auth {
|
|||
public static function user() {
|
||||
return self :: $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to trigger access denied error
|
||||
* @param string|null $details Reason or details about this error
|
||||
* @return never
|
||||
*/
|
||||
public static function access_denied($details=null) {
|
||||
if (Tpl::initialized()) {
|
||||
Tpl :: assign("details", $details);
|
||||
Tpl :: display("access_denied.tpl", I18n::_("Access denied"));
|
||||
}
|
||||
else {
|
||||
printf("<h1>%s</h1>", I18n::_("Access denied"));
|
||||
printf("<p>%s</p>", I18n::_("You do not have access to this application."));
|
||||
if ($details)
|
||||
printf(
|
||||
"<p><small>%s%s</small></p>",
|
||||
I18n::_("Details:"),
|
||||
$details
|
||||
);
|
||||
}
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,16 @@ class Cas extends Method {
|
|||
'default' => null,
|
||||
),
|
||||
),
|
||||
/*
|
||||
* CAS user backend access filters:
|
||||
* [
|
||||
* attr => regex,
|
||||
* attr => callable (will receive the username and the attr value as parameters),
|
||||
* callable, (will receive the username and an associative array of all attrs values as
|
||||
* parameters)
|
||||
* ]
|
||||
*/
|
||||
'user_filters' => array(),
|
||||
)
|
||||
);
|
||||
self :: $fake_authenticated_user = App :: get(
|
||||
|
|
|
@ -3,10 +3,14 @@
|
|||
namespace EesyPHP\Auth;
|
||||
|
||||
use EesyPHP\App;
|
||||
use EesyPHP\Auth;
|
||||
use EesyPHP\Auth\User;
|
||||
use EesyPHP\Check;
|
||||
use EesyPHP\Config;
|
||||
use EesyPHP\I18n;
|
||||
use EesyPHP\Log;
|
||||
use function EesyPHP\cast;
|
||||
use function EesyPHP\format_callable;
|
||||
use function EesyPHP\vardump;
|
||||
|
||||
use phpCAS;
|
||||
|
@ -37,6 +41,9 @@ class Casuser extends Backend {
|
|||
return null;
|
||||
}
|
||||
|
||||
// Check user filters and denied access if not match
|
||||
self :: check_user_filters($username);
|
||||
|
||||
$info = array();
|
||||
foreach(Config::get('auth.cas.user_attributes') as $name => $attr_config) {
|
||||
$cas_name = Config::get("cas_name", null, 'string', false, $attr_config);
|
||||
|
@ -52,4 +59,68 @@ class Casuser extends Backend {
|
|||
return new User($username, '\\EesyPHP\\Auth\\Casuser', $info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check authenticated user match with configured filters and denied access if not
|
||||
* @param string $username
|
||||
* @return void|never
|
||||
*/
|
||||
public static function check_user_filters($username) {
|
||||
foreach(Config::get('auth.cas.user_filters', [], 'array') as $attr => $filter) {
|
||||
if (is_callable($filter)) {
|
||||
if (
|
||||
!$filter(
|
||||
$username,
|
||||
is_string($attr)?phpCAS::getAttribute($attr):phpCAS::getAttributes()
|
||||
)
|
||||
)
|
||||
{
|
||||
Log::warning("get_user(%s): filter out by %s", $username, format_callable($filter));
|
||||
Auth::access_denied();
|
||||
}
|
||||
}
|
||||
else if (is_string($attr)) {
|
||||
$regex_valid = Check :: regex($filter, true);
|
||||
if ($regex_valid !== true) {
|
||||
Log::error(
|
||||
"Casuser auth backend: Invalid regex provided for attribute %s: %s (%s)",
|
||||
$attr, $regex_valid, $filter
|
||||
);
|
||||
Log::fatal(I18n::_("Configuration error in CAS auth backend."));
|
||||
}
|
||||
|
||||
$attr_values = self :: get_attr($attr, [], 'array');
|
||||
if (!$attr_values) {
|
||||
Log::warning(
|
||||
"get_user(%s): filter out by attribute %s (not defined)",
|
||||
$username, $attr
|
||||
);
|
||||
Auth::access_denied();
|
||||
}
|
||||
|
||||
$match = false;
|
||||
foreach ($attr_values as $attr_value) {
|
||||
if (preg_match($filter, $attr_value)) {
|
||||
$match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$match) {
|
||||
Log::warning(
|
||||
"get_user(%s): filter out by attribute %s (not match with '%s')",
|
||||
$username, $attr, $filter
|
||||
);
|
||||
Auth::access_denied();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log::error(
|
||||
"Casuser auth backend: Invalid filter rule configured (%s => %s)",
|
||||
vardump($attr), vardump($filter)
|
||||
);
|
||||
Log::fatal(I18n::_("Configuration error in CAS auth backend."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
20
templates/access_denied.tpl
Normal file
20
templates/access_denied.tpl
Normal file
|
@ -0,0 +1,20 @@
|
|||
{extends file='Tpl:empty.tpl'}
|
||||
{block name="pagetitle"}{/block}
|
||||
{block name="content"}
|
||||
<div class="p-5 mb-4 bg-light rounded-3">
|
||||
<div class="container-fluid py-5">
|
||||
<h1 class="display-5 fw-bold">{t domain=$CORE_TEXT_DOMAIN}Access denied{/t}</h1>
|
||||
<p class="col-md-8 fs-4">
|
||||
{t escape=off domain=$CORE_TEXT_DOMAIN}You do not have access to this application.{/t}
|
||||
</p>
|
||||
{if $details}
|
||||
<p class="col-md-8 fs-6 fw-lighter fst-italic">
|
||||
{t 1=$details domain=$CORE_TEXT_DOMAIN}Details: %1{/t}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
{*
|
||||
# vim: autoindent expandtab tabstop=2 shiftwidth=2 softtabstop=2
|
||||
*}
|
Loading…
Reference in a new issue