Quellcode durchsuchen

add default authent, authent without popup possible, split domain, authorized domains (#24)

Co-authored-by: bosquig <gregory.bosquier@consort-group.com>
BOSQUIER Gregory vor 3 Jahren
Ursprung
Commit
517a829faf
8 geänderte Dateien mit 349 neuen und 42 gelöschten Zeilen
  1. 41 6
      hook.php
  2. 74 25
      inc/provider.class.php
  3. 11 5
      inc/toolbox.class.php
  4. 20 5
      locales/en_GB.po
  5. 180 0
      locales/fr_FR.po
  6. 16 0
      locales/singlesignon.pot
  7. 6 0
      providers.json
  8. 1 1
      setup.php

+ 41 - 6
hook.php

@@ -21,6 +21,11 @@ function plugin_singlesignon_display_login() {
       }
 
       $url = PluginSinglesignonToolbox::getCallbackUrl($row, $query);
+      $isDefault = PluginSinglesignonToolbox::isDefault($row);
+      if ($isDefault && !isset($_GET["noAUTO"])) {
+         Html::redirect($url);
+         return;
+      }
       $html[] = PluginSinglesignonToolbox::renderButton($url, $row);
    }
 
@@ -45,15 +50,15 @@ function plugin_singlesignon_display_login() {
          }
 
          #boxlogin .singlesignon-box .vsubmit {
-            width: 100%;
-            height: 30px;
+            display: flex;
+            justify-content: center;
+            align-items: center;
             font-size: 1.3em !important;
             text-align: center;
             box-sizing: border-box;
          }
          #boxlogin .singlesignon-box .vsubmit img {
-            max-height: 20px;
-            max-width: 100px;
+
             vertical-align: sub;
          }
       </style>
@@ -61,7 +66,7 @@ function plugin_singlesignon_display_login() {
          $(document).ready(function() {
 
             // On click, open a popup
-            $(document).on("click", ".singlesignon.oauth-login", function(e) {
+            $(document).on("click", ".singlesignon.oauth-login.popup", function(e) {
                e.preventDefault();
 
                var url = $(this).attr("href");
@@ -139,6 +144,10 @@ function plugin_singlesignon_install() {
    if (!sso_TableExists("glpi_plugin_singlesignon_providers")) {
       $query = "CREATE TABLE `glpi_plugin_singlesignon_providers` (
                   `id`                         int(11) NOT NULL auto_increment,
+                  `is_default`                 tinyint(1) NOT NULL DEFAULT '0',
+                  `popup`                      tinyint(1) NOT NULL DEFAULT '0',
+                  `split_domain`               tinyint(1) NOT NULL DEFAULT '0',
+                  `authorized_domains`         varchar(255) COLLATE utf8_unicode_ci NULL,
                   `type`                       varchar(255) COLLATE utf8_unicode_ci NOT NULL,
                   `name`                       varchar(255) COLLATE utf8_unicode_ci NOT NULL,
                   `client_id`                  varchar(255) COLLATE utf8_unicode_ci NOT NULL,
@@ -156,9 +165,35 @@ function plugin_singlesignon_install() {
                   PRIMARY KEY (`id`),
                   KEY `date_mod` (`date_mod`),
                   KEY `date_creation` (`date_creation`)
-               ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
+               ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
 
       $DB->query($query) or die("error creating glpi_plugin_singlesignon_providers " . $DB->error());
+   } else {
+		$query = "SHOW COLUMNS FROM glpi_plugin_singlesignon_providers LIKE 'is_default'";
+		$result = $DB->query($query) or die($DB->error());
+		if ($DB->numrows($result) != 1)
+		{
+			$DB->query("ALTER TABLE glpi_plugin_singlesignon_providers ADD is_default tinyint(1) NOT NULL DEFAULT '0'") or die ($DB->error());
+		}
+
+      $query = "SHOW COLUMNS FROM glpi_plugin_singlesignon_providers LIKE 'popup'";
+		$result = $DB->query($query) or die($DB->error());
+		if ($DB->numrows($result) != 1)
+		{
+			$DB->query("ALTER TABLE glpi_plugin_singlesignon_providers ADD popup tinyint(1) NOT NULL DEFAULT '0'") or die ($DB->error());
+		}
+      $query = "SHOW COLUMNS FROM glpi_plugin_singlesignon_providers LIKE 'split_domain'";
+		$result = $DB->query($query) or die($DB->error());
+		if ($DB->numrows($result) != 1)
+		{
+			$DB->query("ALTER TABLE glpi_plugin_singlesignon_providers ADD split_domain tinyint(1) NOT NULL DEFAULT '0'") or die ($DB->error());
+		}
+      $query = "SHOW COLUMNS FROM glpi_plugin_singlesignon_providers LIKE 'authorized_domains'";
+		$result = $DB->query($query) or die($DB->error());
+		if ($DB->numrows($result) != 1)
+		{
+			$DB->query("ALTER TABLE glpi_plugin_singlesignon_providers ADD authorized_domains varchar(255) COLLATE utf8_unicode_ci NULL") or die ($DB->error());
+		}
    }
 
    // add display preferences

+ 74 - 25
inc/provider.class.php

@@ -109,34 +109,54 @@ class PluginSinglesignonProvider extends CommonDBTM {
       echo "<td><input type='text' style='width:96%' name='client_secret' value='" . $this->fields["client_secret"] . "'></td>";
       echo "</tr>\n";
 
-      echo "<tr class='tab_bg_1'>";
-      echo "<td>" . __sso('Scope') . "</td>";
-      echo "<td><input type='text' style='width:96%' name='scope' value='" . $this->fields["scope"] . "'></td>";
-      echo "<td>" . __sso('Extra Options') . "</td>";
-      echo "<td><input type='text' style='width:96%' name='extra_options' value='" . $this->fields["extra_options"] . "'></td>";
-      echo "</tr>\n";
-
       $url_style = "";
 
       if ($this->fields["type"] != 'generic') {
          $url_style = 'style="display: none;"';
       }
 
+      echo "<tr class='tab_bg_1'>";
+      echo "<td>" . __sso('Scope') . "</td>";
+      echo "<td><input type='text' style='width:96%' name='scope' value='" . $this->getScope() . "'></td>";
+      echo "<td>" . __sso('Extra Options') . "</td>";
+      echo "<td><input type='text' style='width:96%' name='extra_options' value='" . $this->fields["extra_options"] . "'></td>";
+      echo "</tr>\n";
+
       echo "<tr class='tab_bg_1 sso_url' $url_style>";
       echo "<td>" . __sso('Authorize URL') . "</td>";
-      echo "<td colspan='3'><input type='text' style='width:96%' name='url_authorize' value='" . $this->fields["url_authorize"] . "'></td>";
+      echo "<td colspan='3'><input type='text' style='width:96%' name='url_authorize' value='" . $this->getAuthorizeUrl() . "'></td>";
       echo "</tr>\n";
 
       echo "<tr class='tab_bg_1 sso_url' $url_style>";
       echo "<td>" . __sso('Access Token URL') . "</td>";
-      echo "<td colspan='3'><input type='text' style='width:96%' name='url_access_token' value='" . $this->fields["url_access_token"] . "'></td>";
+      echo "<td colspan='3'><input type='text' style='width:96%' name='url_access_token' value='" . $this->getAccessTokenUrl() . "'></td>";
       echo "</tr>\n";
 
       echo "<tr class='tab_bg_1 sso_url' $url_style>";
       echo "<td>" . __sso('Resource Owner Details URL') . "</td>";
-      echo "<td colspan='3'><input type='text' style='width:96%' name='url_resource_owner_details' value='" . $this->fields["url_resource_owner_details"] . "'></td>";
+      echo "<td colspan='3'><input type='text' style='width:96%' name='url_resource_owner_details' value='" . $this->getResourceOwnerDetailsUrl() . "'></td>";
       echo "</tr>\n";
 
+      echo "<tr class='tab_bg_1'>";
+      echo "<td>" . __('IsDefault', 'singlesignon') . "</td><td>";
+      Dropdown::showYesNo("is_default", $this->fields["is_default"]);
+      echo "<td>" . __sso('PopupAuth') . "</td>";
+      echo "<td>";
+      Dropdown::showYesNo("popup", $this->fields["popup"]);
+      echo "</td></tr>\n";
+
+      echo "<tr class='tab_bg_1'>";
+      echo "<td>" . __sso('SplitDomain') . "</td>";
+      echo "<td>";
+      Dropdown::showYesNo("split_domain", $this->fields["split_domain"]);
+      echo "</td>";
+      echo "<td>" . __sso('AuthorizedDomains');
+      echo "&nbsp;";
+      Html::showToolTip(nl2br(__sso('AuthorizedDomainsTooltip')));
+      echo "</td>";
+      echo "<td><input type='text' style='width:96%' name='authorized_domains' value='" . $this->fields["authorized_domains"] . "'></td>";
+      echo "</td></tr>\n";
+
       echo "<tr class='tab_bg_1'>";
       echo "<th colspan='4'>" . __('Personalization') . "</th>";
       echo "</tr>\n";
@@ -528,6 +548,7 @@ class PluginSinglesignonProvider extends CommonDBTM {
    static function getTypes() {
 
       $options['generic'] = __sso('Generic');
+      $options['azure'] = __sso('Azure');
       $options['facebook'] = __sso('Facebook');
       $options['github'] = __sso('GitHub');
       $options['google'] = __sso('Google');
@@ -787,7 +808,7 @@ class PluginSinglesignonProvider extends CommonDBTM {
       return $fields['url_access_token'];
    }
 
-   public function getResourceOwnerDetailsUrl($access_token) {
+   public function getResourceOwnerDetailsUrl($access_token = null) {
       $type = $this->getClientType();
 
       $value = static::getDefault($type, "url_resource_owner_details", "");
@@ -1062,12 +1083,54 @@ class PluginSinglesignonProvider extends CommonDBTM {
          return $user;
       }
 
+      $split = $this->fields['split_domain'];
+      $login = false;
+      $login_fields = ['userPrincipalName','login', 'username', 'id'];
+
+      foreach ($login_fields as $field) {
+         if (isset($resource_array[$field]) && is_string($resource_array[$field])) {
+            $login = $resource_array[$field];
+            $isAuthorized = empty($authorizedDomains);
+            foreach ($authorizedDomains as $authorizedDomain) {
+              if(preg_match("/{$authorizedDomain}$/i", $login)) {
+                 $isAuthorized = true;
+              }
+            }
+            if (!$isAuthorized) return false;
+            if ($split) {
+               $loginSplit = explode("@", $login);
+               $login = $loginSplit[0];
+            }
+            break;
+         }
+      }
+
+      if ($login && $user->getFromDBbyName($login)) {
+         return $user;
+      }
+
       $email = false;
       $email_fields = ['email', 'e-mail', 'email-address', 'mail'];
+      $authorizedDomainsString = $this->fields['authorized_domains'];
+      $authorizedDomains = [];
+      if (isset($authorizedDomainsString)) {
+         $authorizedDomains = explode(',', $authorizedDomainsString);
+      }
 
       foreach ($email_fields as $field) {
          if (isset($resource_array[$field]) && is_string($resource_array[$field])) {
             $email = $resource_array[$field];
+            $isAuthorized = empty($authorizedDomains);
+            foreach ($authorizedDomains as $authorizedDomain) {
+              if(preg_match("/{$authorizedDomain}$/i", $email)) {
+                 $isAuthorized = true;
+              }
+            }
+            if (!$isAuthorized) return false;
+            if ($split) {
+               $emailSplit = explode("@", $email);
+               $email = $emailSplit[0];
+            }
             break;
          }
       }
@@ -1082,20 +1145,6 @@ class PluginSinglesignonProvider extends CommonDBTM {
          return $user;
       }
 
-      $login = false;
-      $login_fields = ['login', 'username', 'id'];
-
-      foreach ($login_fields as $field) {
-         if (isset($resource_array[$field]) && is_string($resource_array[$field])) {
-            $login = $resource_array[$field];
-            break;
-         }
-      }
-
-      if ($login && $user->getFromDBbyName($login)) {
-         return $user;
-      }
-
       return false;
    }
 

+ 11 - 5
inc/toolbox.class.php

@@ -16,15 +16,19 @@ class PluginSinglesignonToolbox {
 
       $url .= "/provider/".$row['id'];
 
-      if (!empty($query) && $row['type'] != 'google') {
-         $url .= "/q/" . base64_encode(http_build_query($query));
-      } else if (!empty($query) && $row['type'] == 'google') {
+      if (!empty($query)) {
          $_SESSION['redirect'] = $query['redirect'];
       }
 
       return $url;
    }
 
+   public static function isDefault($row, $query = []) {
+
+      if ($row['is_default'] == 1) return true;
+      return false;
+   }
+
    public static function getCallbackParameters($name = null) {
       $data = [];
 
@@ -129,7 +133,9 @@ class PluginSinglesignonToolbox {
    }
 
    public static function renderButton($url, $data, $class = 'oauth-login') {
-      $btn = '<span><a href="' . $url . '" class="singlesignon vsubmit ' . $class . '"';
+      $popupClass = "";
+      if (isset($data['popup']) && $data['popup'] == 1) $popupClass = "popup";
+      $btn = '<span><a href="' . $url . '" class="singlesignon vsubmit ' . $class . ' ' . $popupClass . '"';
 
       $style = '';
       if ((isset($data['bgcolor']) && $data['bgcolor'])) {
@@ -147,7 +153,7 @@ class PluginSinglesignonToolbox {
          $btn .= Html::image(
             static::getPictureUrl($data['picture']),
             [
-               'style' => 'max-height: 20px;',
+               'style' => 'max-height: 20px;margin-right: 4px',
             ]
          );
          $btn .= ' ';

+ 20 - 5
locales/en_GB.po

@@ -6,10 +6,9 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: singlesignon 1.3.1\n"
-"Report-Msgid-Bugs-To: https://github.com/edgardmessias/glpi-singlesignon/"
-"issues\n"
+"Report-Msgid-Bugs-To: https://github.com/edgardmessias/glpi-singlesignon/issues\n"
 "POT-Creation-Date: 2021-03-17 09:30-0300\n"
-"PO-Revision-Date: 2021-03-17 09:30-0300\n"
+"PO-Revision-Date: 2022-03-23 14:36+0100\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
 "Language: en_GB\n"
@@ -17,6 +16,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 3.0.1\n"
 
 #: front/callback.php:15
 msgid "Provider not defined."
@@ -31,8 +31,7 @@ msgid "Provider not active."
 msgstr "Provider not active."
 
 #: front/provider.form.php:61 front/provider.form.php:63 front/provider.php:8
-#: front/provider.php:10 inc/preference.class.php:64 inc/provider.class.php:57
-#: setup.php:40
+#: front/provider.php:10 inc/preference.class.php:64 inc/provider.class.php:57 setup.php:40
 msgid "Single Sign-on"
 msgstr "Single Sign-on"
 
@@ -162,3 +161,19 @@ msgstr "Please, rename the plugin folder \"%s\" to \"singlesignon\""
 #: setup.php:57
 msgid "This plugin requires GLPI >= 0.85"
 msgstr "This plugin requires GLPI >= 0.85"
+
+#: inc/provider.class.php:141
+msgid "IsDefault"
+msgstr "Default Authentication"
+
+msgid "PopupAuth"
+msgstr "Authentication through a Pop-up"
+
+msgid "SplitDomain"
+msgstr "Do not take into account the domain for the matching with the GLPI user identifier"
+
+msgid "AuthorizedDomains"
+msgstr "Authorized domains"
+
+msgid "AuthorizedDomainsTooltip"
+msgstr "Allowed domains separated by ','. Empty : all domains are allowed"

+ 180 - 0
locales/fr_FR.po

@@ -0,0 +1,180 @@
+# English translations for singlesignon package.
+# Copyright (C) 2021 THE singlesignon'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the singlesignon package.
+# Automatically generated, 2021.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: singlesignon 1.3.1\n"
+"Report-Msgid-Bugs-To: https://github.com/edgardmessias/glpi-singlesignon/issues\n"
+"POT-Creation-Date: 2021-03-17 09:30-0300\n"
+"PO-Revision-Date: 2022-03-23 14:35+0100\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: en_GB\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 3.0.1\n"
+
+#: front/callback.php:15
+msgid "Provider not defined."
+msgstr "Provider not defined."
+
+#: front/callback.php:21
+msgid "Provider not found."
+msgstr "Provider not found."
+
+#: front/callback.php:25
+msgid "Provider not active."
+msgstr "Provider not active."
+
+#: front/provider.form.php:61 front/provider.form.php:63 front/provider.php:8
+#: front/provider.php:10 inc/preference.class.php:64 inc/provider.class.php:57
+#: setup.php:40
+msgid "Single Sign-on"
+msgstr "Single Sign-on"
+
+#: inc/preference.class.php:147 inc/provider.class.php:50
+msgid "Single Sign-on Provider"
+msgstr "Single Sign-on Provider"
+
+#: inc/preference.class.php:172
+msgid "Linked accounts"
+msgstr "Linked accounts"
+
+#: inc/provider.class.php:98
+msgid "SSO Type"
+msgstr "SSO Type"
+
+#: inc/provider.class.php:106 inc/provider.class.php:423
+msgid "Client ID"
+msgstr "Client ID"
+
+#: inc/provider.class.php:108 inc/provider.class.php:431
+msgid "Client Secret"
+msgstr "Client Secret"
+
+#: inc/provider.class.php:113 inc/provider.class.php:439
+msgid "Scope"
+msgstr "Scope"
+
+#: inc/provider.class.php:115 inc/provider.class.php:447
+msgid "Extra Options"
+msgstr "Extra Options"
+
+#: inc/provider.class.php:126 inc/provider.class.php:455
+msgid "Authorize URL"
+msgstr "Authorize URL"
+
+#: inc/provider.class.php:131 inc/provider.class.php:463
+msgid "Access Token URL"
+msgstr "Access Token URL"
+
+#: inc/provider.class.php:136 inc/provider.class.php:471
+msgid "Resource Owner Details URL"
+msgstr "Resource Owner Details URL"
+
+#: inc/provider.class.php:224
+msgid "Callback URL"
+msgstr "Callback URL"
+
+#: inc/provider.class.php:228
+msgid "Test Single Sign-on"
+msgstr "Test Single Sign-on"
+
+#: inc/provider.class.php:286
+msgid "A Name is required"
+msgstr "A Name is required"
+
+#: inc/provider.class.php:292
+#, php-format
+msgid "The \"%s\" is a Invalid type"
+msgstr "The \"%s\" is a Invalid type"
+
+#: inc/provider.class.php:296
+msgid "A Client ID is required"
+msgstr "A Client ID is required"
+
+#: inc/provider.class.php:300
+msgid "A Client Secret is required"
+msgstr "A Client Secret is required"
+
+#: inc/provider.class.php:305
+msgid "An Authorize URL is required"
+msgstr "An Authorize URL is required"
+
+#: inc/provider.class.php:307
+msgid "The Authorize URL is invalid"
+msgstr "The Authorize URL is invalid"
+
+#: inc/provider.class.php:311
+msgid "An Access Token URL is required"
+msgstr "An Access Token URL is required"
+
+#: inc/provider.class.php:313
+msgid "The Access Token URL is invalid"
+msgstr "The Access Token URL is invalid"
+
+#: inc/provider.class.php:317
+msgid "A Resource Owner Details URL is required"
+msgstr "A Resource Owner Details URL is required"
+
+#: inc/provider.class.php:319
+msgid "The Resource Owner Details URL is invalid"
+msgstr "The Resource Owner Details URL is invalid"
+
+#: inc/provider.class.php:530
+msgid "Generic"
+msgstr "Generic"
+
+#: inc/provider.class.php:531
+msgid "Facebook"
+msgstr "Facebook"
+
+#: inc/provider.class.php:532
+msgid "GitHub"
+msgstr "GitHub"
+
+#: inc/provider.class.php:533
+msgid "Google"
+msgstr "Google"
+
+#: inc/provider.class.php:534
+msgid "Instagram"
+msgstr "Instagram"
+
+#: inc/provider.class.php:535
+msgid "LinkdeIn"
+msgstr "LinkdeIn"
+
+#: inc/toolbox.class.php:154
+#, php-format
+msgid "Login with %s"
+msgstr "Se connecter avec %s"
+
+#: setup.php:8
+#, php-format
+msgid "Please, rename the plugin folder \"%s\" to \"singlesignon\""
+msgstr "Please, rename the plugin folder \"%s\" to \"singlesignon\""
+
+#: setup.php:57
+msgid "This plugin requires GLPI >= 0.85"
+msgstr "This plugin requires GLPI >= 0.85"
+
+#: inc/provider.class.php:141
+msgid "IsDefault"
+msgstr "Authentification par défaut"
+
+msgid "PopupAuth"
+msgstr "Authentification via Pop-up"
+
+msgid "SplitDomain"
+msgstr "Ne pas prendre en compte le domaine pour la correspondance de l'identifiant GLPI"
+
+msgid "AuthorizedDomains"
+msgstr "Domaines autorisés"
+
+msgid "AuthorizedDomainsTooltip"
+msgstr "Domaines autorisés séparés par des ','. Vide : tous les domaines sont autorisés"

+ 16 - 0
locales/singlesignon.pot

@@ -162,3 +162,19 @@ msgstr ""
 #: setup.php:57
 msgid "This plugin requires GLPI >= 0.85"
 msgstr ""
+
+#: inc/provider.class.php:141
+msgid "IsDefault"
+msgstr ""
+
+msgid "PopupAuth"
+msgstr ""
+
+msgid "SplitDomain"
+msgstr ""
+
+msgid "AuthorizedDomains"
+msgstr ""
+
+msgid "AuthorizedDomainsTooltip"
+msgstr ""

+ 6 - 0
providers.json

@@ -1,4 +1,10 @@
 {
+   "azure": {
+      "url_authorize": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
+      "url_access_token": "https://login.microsoftonline.com/common/oauth2/v2.0/token",
+      "url_resource_owner_details": "https://graph.microsoft.com/v1.0/me",
+      "scope": "User.Read"
+   },
    "facebook": {
       "url_authorize": "https://www.facebook.com/v9.0/dialog/oauth",
       "url_access_token": "https://graph.facebook.com/v9.0/oauth/access_token",

+ 1 - 1
setup.php

@@ -1,6 +1,6 @@
 <?php
 
-define('PLUGIN_SINGLESIGNON_VERSION', '1.3.1');
+define('PLUGIN_SINGLESIGNON_VERSION', '1.3.2');
 
 $folder = basename(dirname(__FILE__));