diff --git a/docs/en/events.md b/docs/en/events.md
index ee014dd..1f187d5 100644
--- a/docs/en/events.md
+++ b/docs/en/events.md
@@ -107,3 +107,9 @@ This event is sent to extend the content of the "view profile" page.
The view profile currently display information of the profile (username, first name, e-mail, ...) and a button to edit values.
use `addContent(string $content, int $position)` to add some content to the page. Initial content is on position 5.
+`AuthAdminGetIDPPlugin`
+-----------------
+
+This event is sent to build the IDP list (existing regardless the `[authentication]` configuration).
+
+Use the event when you create a module so that it is known by idpadmin module.
diff --git a/modules/authadmin/controllers/idpadmin.classic.php b/modules/authadmin/controllers/idpadmin.classic.php
new file mode 100644
index 0000000..a88c3a3
--- /dev/null
+++ b/modules/authadmin/controllers/idpadmin.classic.php
@@ -0,0 +1,109 @@
+ array('auth.required' => false, 'jacl2.right' => 'auth.idpadmin.view'),
+ 'save' => array('jacl2.right' => 'auth.idpadmin.edit'),
+ ];
+
+ private $idpList ;
+
+ public function __construct(jRequest $req)
+ {
+ $idpFinder = new IdpFinder();
+ $this->idpList = $idpFinder->findAllIDP();
+ parent::__construct($req);
+ }
+
+ public function index()
+ {
+ $resp = $this->getResponse('html');
+ // build form
+ $form = jForms::create('authadmin~idp');
+ $this->buildForm($form);
+ foreach($this->idpList as $idpInfo) {
+ $form->setData('chck_'.$idpInfo[0], $idpInfo[1]);
+ }
+ $tpl = new jTpl();
+ $tpl->assign('idps', $this->idpList);
+ $tpl->assign('form', $form);
+ $resp->body->assign('MAIN', $tpl->fetch('idp.list'));
+
+ return $resp;
+ }
+
+ public function prepareEdit()
+ {
+ $form = jForms::create('authadmin~idp');
+ $this->buildForm($form);
+ foreach($this->idpList as $idpInfo) {
+ $form->setData('chck_'.$idpInfo[0], $idpInfo[1]);
+ }
+ return $this->redirect('authadmin~idpadmin:showEdit');
+ }
+
+ public function showEdit()
+ {
+ $form = jForms::get('authadmin~idp');
+ if(is_null($form)) {
+ return $this->redirect('authadmin~idpadmin:prepareEdit');
+ }
+ $this->buildForm($form);
+ $resp = $this->getResponse('html');
+
+ $tpl = new jTpl();
+ $tpl->assign('idps', $this->idpList);
+ $tpl->assign('form', $form);
+ $resp->body->assign('MAIN', $tpl->fetch('idp.edit'));
+
+ return $resp;
+ }
+
+ public function save()
+ {
+ $modif = new IniModifier(jApp::varConfigPath('liveconfig.ini.php'));
+
+ // build form
+ $form = jForms::get('authadmin~idp');
+ $this->buildForm($form);
+ $form->initFromRequest();
+
+ if(!$form->check()) {
+ return $this->redirect('authadmin~idpadmin:showEdit');
+ }
+
+ $enabledIdp = [];
+ foreach($this->idpList as $idp) {
+ $name = $idp[0];
+ if ($form->getData('chck_'.$name) == 1) {
+ $enabledIdp[] = $name;
+ }
+ }
+ $sessionIdp = jAuthentication::session()->getIdentityProviderId();
+ if (!in_array($sessionIdp, $enabledIdp)) {
+ $form->setErrorOn('chck_'.$name, jLocale::get('default.form.error.session.idp.disabling.forbidden'));
+ return $this->redirect('authadmin~idpadmin:showEdit');
+ }
+ $modif->setValues(['idp' => $enabledIdp], 'authentication');
+ $modif->save();
+ jForms::destroy('authadmin~idp');
+
+ return $this->redirect('authadmin~idpadmin:index');
+ }
+
+ protected function buildForm(jFormsBase $form)
+ {
+ foreach($this->idpList as $idpInfo) {
+ $name = $idpInfo[0];
+ $ctrlStatus = new jFormsControlCheckbox('chck_'.$name);
+ $ctrlStatus->label = $name;
+ $ctrlStatus->valueLabelOnCheck = jLocale::get('jelix~ui.buttons.enabled');
+ $ctrlStatus->valueLabelOnUncheck = jLocale::get('jelix~ui.buttons.disabled');
+ $form->addControl($ctrlStatus);
+ }
+ }
+}
diff --git a/modules/authadmin/events.xml b/modules/authadmin/events.xml
new file mode 100644
index 0000000..18cfa82
--- /dev/null
+++ b/modules/authadmin/events.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/modules/authadmin/forms/idp.form.xml b/modules/authadmin/forms/idp.form.xml
new file mode 100644
index 0000000..8bcbf97
--- /dev/null
+++ b/modules/authadmin/forms/idp.form.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/modules/authadmin/install/install.php b/modules/authadmin/install/install.php
new file mode 100644
index 0000000..02087f8
--- /dev/null
+++ b/modules/authadmin/install/install.php
@@ -0,0 +1,19 @@
+ 'onAdminUILoading',
+ );
+
+ /**
+ * @param jEvent $event
+ */
+ public function onAdminUILoading($event)
+ {
+ if(jAcl2::check('auth.idpadmin.view')) {
+ /** @var \Jelix\AdminUI\UIManager $uim */
+ $uim = $event->uiManager;
+
+ $adminMenu = new SubMenu('admin', 'Authentification', 10);
+ $adminMenu->addJelixLinkItem(jLocale::get('authadmin~default.navigation.menu.idp'), 'authadmin~idpadmin:index', array(), 'address-book');
+ $uim->sidebar()->addMenuItem($adminMenu);
+ }
+
+ }
+}
diff --git a/modules/authadmin/lib/IdpFinder.php b/modules/authadmin/lib/IdpFinder.php
new file mode 100644
index 0000000..b17ee97
--- /dev/null
+++ b/modules/authadmin/lib/IdpFinder.php
@@ -0,0 +1,30 @@
+getResponse();
+ $authManager = jAuthentication::manager();
+ $enabledIdps = $authManager->getIdpList();
+ $enabledIdpNames = array_map(function (IdentityProviderInterface $idp) {return $idp->getId();}, $enabledIdps);
+ $allIdpName = [];
+ foreach($allIdpResponse as $idpInfo) {
+ if (array_key_exists('pluginName', $idpInfo)) {
+ $pluginName = $idpInfo['pluginName'];
+ $idpEnabled = (false !== array_search($pluginName, $enabledIdpNames));
+ $allIdpName[] = [$pluginName, $idpEnabled];
+ }
+
+ }
+
+ return $allIdpName;
+ }
+}
diff --git a/modules/authadmin/locales/en_US/default.UTF-8.properties b/modules/authadmin/locales/en_US/default.UTF-8.properties
new file mode 100644
index 0000000..aff4794
--- /dev/null
+++ b/modules/authadmin/locales/en_US/default.UTF-8.properties
@@ -0,0 +1,9 @@
+rights.group.name=Identity providers
+idp.view=View Identity providers
+idp.edit=Edit Identity providers
+navigation.menu.idp=Identity providers
+idp.list.page.title=Installed identity providers
+idp.edit.page.title=Edit identity providers
+form.error.session.idp.disabling.forbidden=You can't disable the idp uses by current session
+table.th.name=Nom
+table.th.status=Status
diff --git a/modules/authadmin/locales/fr_FR/default.UTF-8.properties b/modules/authadmin/locales/fr_FR/default.UTF-8.properties
new file mode 100644
index 0000000..db25043
--- /dev/null
+++ b/modules/authadmin/locales/fr_FR/default.UTF-8.properties
@@ -0,0 +1,9 @@
+rights.group.name=Fournisseurs d'identité
+idp.view=Voir les fournisseurs d'identité
+idp.edit=Modifier les fournisseurs d'identité
+navigation.menu.idp=Fournisseurs d'identité
+idp.list.page.title=Fournisseurs d'identité installés
+idp.edit.page.title=Modifier les fournisseurs d'identité
+form.error.session.idp.disabling.forbidden=Vous ne pouvez pas désactiver le fournisseur utilisé par la session en cours
+table.th.name=Nom
+table.th.status=Status
diff --git a/modules/authadmin/module.xml b/modules/authadmin/module.xml
new file mode 100644
index 0000000..ce87f88
--- /dev/null
+++ b/modules/authadmin/module.xml
@@ -0,0 +1,19 @@
+
+
+
+ 0.0.1
+
+ Module adding administration page for IDP
+ MIT
+ 2019-2025 Laurent Jouanneau
+
+ https://jelix.org
+
+
+
+
+
+
+
+
+
diff --git a/modules/authadmin/templates/idp.edit.tpl b/modules/authadmin/templates/idp.edit.tpl
new file mode 100644
index 0000000..7936534
--- /dev/null
+++ b/modules/authadmin/templates/idp.edit.tpl
@@ -0,0 +1,37 @@
+{@authadmin~default.idp.edit.page.title@}
+
+
+
+{form $form, 'authadmin~idpadmin:save', [], 'adminlte'}
+
+{formcontrols}
+
+
+
+ | {@authadmin~default.table.th.name@} |
+ {@authadmin~default.table.th.status@} |
+
+
+
+ {foreach $idps as $idp}
+ {assign $ctlName = 'chck_'.$idp[0]}
+
+ |
+ {$idp[0]}
+ |
+
+ {ctrl_control $ctlName}
+ |
+
+ {/foreach}
+
+
+
+{/formcontrols}
+
+
+{/form}
+
+
diff --git a/modules/authadmin/templates/idp.list.tpl b/modules/authadmin/templates/idp.list.tpl
new file mode 100644
index 0000000..88b96a4
--- /dev/null
+++ b/modules/authadmin/templates/idp.list.tpl
@@ -0,0 +1,36 @@
+
+{@authadmin~default.idp.list.page.title@}
+
+
+
+{formcontrols $form}
+
+
+
+
+ | {@authadmin~default.table.th.name@} |
+ {@authadmin~default.table.th.status@} |
+
+
+
+
+ {foreach $idps as $idp}
+ {assign $ctlName = 'chck_'.$idp[0]}
+
+ |
+ {$idp[0]}
+ |
+
+ {ctrl_value $ctlName}
+ |
+
+ {/foreach}
+
+
+
+{/formcontrols}
+{ifacl2 'auth.idpadmin.edit'}
+
{@jelix~ui.buttons.update@}
+{/ifacl2}
+
+
diff --git a/modules/authadmin/urls.xml b/modules/authadmin/urls.xml
new file mode 100644
index 0000000..7270065
--- /dev/null
+++ b/modules/authadmin/urls.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/modules/authloginpass/events.xml b/modules/authloginpass/events.xml
new file mode 100644
index 0000000..d287d04
--- /dev/null
+++ b/modules/authloginpass/events.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/modules/authloginpass/lib/AuthCoreEventListener.php b/modules/authloginpass/lib/AuthCoreEventListener.php
new file mode 100644
index 0000000..58d73ec
--- /dev/null
+++ b/modules/authloginpass/lib/AuthCoreEventListener.php
@@ -0,0 +1,16 @@
+add(['pluginName' => 'loginpass']);
+ }
+}
diff --git a/test/appctl b/test/appctl
index 7335902..ea5259b 100755
--- a/test/appctl
+++ b/test/appctl
@@ -5,7 +5,7 @@ shift
if [ "$COMMAND" == "" ]; then
echo "Error: command is missing"
- echo "Possible commands: clean_tmp, reset, install, rights, composer-install, composer-update"
+ echo "Possible commands: clean_tmp, reset, install, rights, composer-install, composer-update, install-admin"
echo " unit-tests, shell, shellroot"
echo " ldapreset, ldapusers"
exit 1;
@@ -45,6 +45,15 @@ case $COMMAND in
ldapshell)
docker exec -it ${CONTAINER_PREFIX}_ldap /bin/bash -l
;;
+ install-admin)
+ docker exec -t -i ${CONTAINER_PREFIX}_php /bin/bash -c 'php test/testapp/console.php account:create admin admin@example.com'
+ docker exec -t -i ${CONTAINER_PREFIX}_php /bin/bash -c 'php test/testapp/console.php account:login:create -b daotablesqlite admin -p adminpass'
+ docker exec -t -i ${CONTAINER_PREFIX}_php /bin/bash -c 'php test/testapp/console.php acl2user:register admin'
+ docker exec -t -i ${CONTAINER_PREFIX}_php /bin/bash -c 'php test/testapp/console.php acl2user:addgroup admin admins'
+ docker exec -t -i ${CONTAINER_PREFIX}_php /bin/bash -c 'php test/testapp/console.php acl2:add admins auth.idpadmin.view'
+ docker exec -t -i ${CONTAINER_PREFIX}_php /bin/bash -c 'php test/testapp/console.php acl2:add admins auth.idpadmin.edit'
+ echo "admin account created, login admin, password adminpass"
+ ;;
*)
echo "wrong command"
exit 2
diff --git a/test/testapp/app/system/mainconfig.ini.php b/test/testapp/app/system/mainconfig.ini.php
index 24ef93a..f7cbf45 100644
--- a/test/testapp/app/system/mainconfig.ini.php
+++ b/test/testapp/app/system/mainconfig.ini.php
@@ -32,6 +32,7 @@
account.enabled=on
accountadmin.enabled=on
+authadmin.enabled=on
[coordplugins]
sessionauth=on
jacl2=1
diff --git a/test/testapp/app/system/urls.xml b/test/testapp/app/system/urls.xml
index 20d8f56..f54893e 100644
--- a/test/testapp/app/system/urls.xml
+++ b/test/testapp/app/system/urls.xml
@@ -7,6 +7,7 @@
+
diff --git a/test/testapp/modules/test/events.xml b/test/testapp/modules/test/events.xml
index af674e3..17e8e3d 100644
--- a/test/testapp/modules/test/events.xml
+++ b/test/testapp/modules/test/events.xml
@@ -9,4 +9,7 @@
+
+
+
diff --git a/test/testapp/modules/test/lib/AuthCoreEventListener.php b/test/testapp/modules/test/lib/AuthCoreEventListener.php
new file mode 100644
index 0000000..f6e790b
--- /dev/null
+++ b/test/testapp/modules/test/lib/AuthCoreEventListener.php
@@ -0,0 +1,16 @@
+add(['pluginName' => 'alwaysyes']);
+ }
+}