aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Noack <noack@data-quest.de>2021-12-21 11:08:51 +0000
committerAndré Noack <noack@data-quest.de>2021-12-21 11:08:51 +0000
commit7660820a38d539ab06eafdfbf757014169baac40 (patch)
treea5981bc26f0a474de0b07218625c1d924c531cb6
parentb0a1a7adf5203efa32661b96ecb023fef74c5d2d (diff)
Resolve "OpenID Connect als SSO AuthPlugin"
-rw-r--r--composer.json3
-rw-r--r--composer.lock44
-rw-r--r--config/config_defaults.inc.php20
-rw-r--r--lib/classes/auth_plugins/StudipAuthAbstract.class.php422
-rw-r--r--lib/classes/auth_plugins/StudipAuthCAS.class.php70
-rw-r--r--lib/classes/auth_plugins/StudipAuthLdap.class.php146
-rw-r--r--lib/classes/auth_plugins/StudipAuthLdapReadAndBind.class.php64
-rw-r--r--lib/classes/auth_plugins/StudipAuthOIDC.class.php112
-rw-r--r--lib/classes/auth_plugins/StudipAuthSSO.class.php10
-rw-r--r--lib/classes/auth_plugins/StudipAuthShib.class.php64
-rw-r--r--lib/classes/auth_plugins/StudipAuthStandard.class.php26
-rw-r--r--lib/navigation/LoginNavigation.php16
12 files changed, 578 insertions, 419 deletions
diff --git a/composer.json b/composer.json
index ba9f55e..569f700 100644
--- a/composer.json
+++ b/composer.json
@@ -47,6 +47,7 @@
"slim/slim": "4.7.1",
"php-di/php-di": "6.3.4",
"symfony/console": "5.3.6",
- "symfony/process": "^5.4"
+ "symfony/process": "^5.4",
+ "jumbojett/openid-connect-php": "^0.9.2"
}
}
diff --git a/composer.lock b/composer.lock
index 83fc9e5..3ec6357 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "59006c71d43d6f32f0445636c803208d",
+ "content-hash": "2fa6a856bbe442274874aeabe26f054b",
"packages": [
{
"name": "algo26-matthias/idna-convert",
@@ -546,6 +546,48 @@
"time": "2019-08-18T20:01:55+00:00"
},
{
+ "name": "jumbojett/openid-connect-php",
+ "version": "v0.9.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/jumbojett/OpenID-Connect-PHP.git",
+ "reference": "14991f706675b13dd1f72291bfd779f144454d64"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/jumbojett/OpenID-Connect-PHP/zipball/14991f706675b13dd1f72291bfd779f144454d64",
+ "reference": "14991f706675b13dd1f72291bfd779f144454d64",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "ext-json": "*",
+ "paragonie/random_compat": ">=2",
+ "php": ">=5.4",
+ "phpseclib/phpseclib": "~2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8",
+ "roave/security-advisories": "dev-master"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "description": "Bare-bones OpenID Connect client",
+ "support": {
+ "issues": "https://github.com/jumbojett/OpenID-Connect-PHP/issues",
+ "source": "https://github.com/jumbojett/OpenID-Connect-PHP/tree/v0.9.5"
+ },
+ "time": "2021-11-24T16:11:49+00:00"
+ },
+ {
"name": "kub-at/php-simple-html-dom-parser",
"version": "1.9.1",
"source": {
diff --git a/config/config_defaults.inc.php b/config/config_defaults.inc.php
index 14c1757..2b6f2ca 100644
--- a/config/config_defaults.inc.php
+++ b/config/config_defaults.inc.php
@@ -326,6 +326,26 @@ $STUDIP_AUTH_CONFIG_CAS = array("host" => "cas.studip.de",
"auth_user_md5.Email" => array("callback" => "getUserData", "map_args" => "email"),
"auth_user_md5.perms" => array("callback" => "getUserData", "map_args" => "status")));
+//example of OpenID Connect
+$STUDIP_AUTH_CONFIG_GOOGLE = [
+ 'provider_url' => 'https://accounts.google.com',
+ 'client_id' => '',
+ 'client_secret' => '',
+ 'plugin_class' => 'StudipAuthOIDC',
+ 'plugin_name' => 'google',
+ 'domain' => 'google',
+ 'plugin_fullname' => 'Google',
+ 'login_description' => 'Login with Google',
+ 'ssl_options' => ['certPath' => null, 'verifyPeer' => true, 'verifyHost' => true],
+ 'user_data_mapping' =>
+ ['auth_user_md5.username' => ['callback' => 'dummy', 'map_args' => ''],
+ 'auth_user_md5.password' => ['callback' => 'dummy', 'map_args' => ''],
+ 'auth_user_md5.Email' => ['callback' => 'getUserData', 'map_args' => 'email'],
+ 'auth_user_md5.Nachname' => ['callback' => 'getUserData', 'map_args' => 'family_name'],
+ 'auth_user_md5.Vorname' => ['callback' => 'getUserData', 'map_args' => 'given_name']
+ ]
+ ];
+
$STUDIP_AUTH_CONFIG_LTI = [
'consumer_keys' => [
// 'domain' is optional, default is value of consumer_key
diff --git a/lib/classes/auth_plugins/StudipAuthAbstract.class.php b/lib/classes/auth_plugins/StudipAuthAbstract.class.php
index 3af55c5..008ed87 100644
--- a/lib/classes/auth_plugins/StudipAuthAbstract.class.php
+++ b/lib/classes/auth_plugins/StudipAuthAbstract.class.php
@@ -1,8 +1,4 @@
<?php
-# Lifter003: TEST
-# Lifter007: TODO
-# Lifter010: DONE - no html
-
// +---------------------------------------------------------------------------+
// This file is part of Stud.IP
// StudipAuthAbstract.class.php
@@ -26,39 +22,37 @@
// +---------------------------------------------------------------------------+
/**
-* abstract base class for authentication plugins
-*
-* abstract base class for authentication plugins
-* to write your own authentication plugin, derive it from this class and
-* implement the following abstract methods: isUsedUsername($username) and
-* isAuthenticated($username, $password, $jscript)
-* don't forget to call the parents constructor if you implement your own, php
-* won't do that for you !
-*
-* @abstract
-* @access public
-* @author André Noack <noack@data-quest.de>
-* @package
-*/
-class StudipAuthAbstract {
+ * abstract base class for authentication plugins
+ *
+ * abstract base class for authentication plugins
+ * to write your own authentication plugin, derive it from this class and
+ * implement the following abstract methods: isUsedUsername($username) and
+ * isAuthenticated($username, $password, $jscript)
+ * don't forget to call the parents constructor if you implement your own, php
+ * won't do that for you !
+ *
+ * @abstract
+ * @author André Noack <noack@data-quest.de>
+ * @package
+ */
+class StudipAuthAbstract
+{
/**
- * contains error message, if authentication fails
- *
- *
- * @access public
- * @var string
- */
- var $error_msg;
+ * contains error message, if authentication fails
+ *
+ *
+ * @var string $error_msg
+ */
+ public $error_msg;
/**
- * indicates whether the authenticated user logs in for the first time
- *
- *
- * @access public
- * @var bool
- */
- var $is_new_user = false;
+ * indicates whether the authenticated user logs in for the first time
+ *
+ *
+ * @var bool $is_new_user
+ */
+ public $is_new_user = false;
/**
* array of user domains to assign to each user, can be set in local.inc
@@ -66,76 +60,75 @@ class StudipAuthAbstract {
* @access public
* @var array $user_domains
*/
- var $user_domains;
+ public $user_domains;
/**
- * associative array with mapping for database fields
- *
- * associative array with mapping for database fields,
- * should be set in local.inc
- * structure :
- * array("<table name>.<field name>" => array( "callback" => "<name of callback method used for data retrieval>",
- * "map_args" => "<arguments passed to callback method>"))
- * @access public
- * @var array $user_data_mapping
- */
- var $user_data_mapping = null;
+ * associative array with mapping for database fields
+ *
+ * associative array with mapping for database fields,
+ * should be set in local.inc
+ * structure :
+ * array('<table name>.<field name>' => array( 'callback' => '<name of callback method used for data retrieval>',
+ * 'map_args' => '<arguments passed to callback method>'))
+ * @var array $user_data_mapping
+ */
+ public $user_data_mapping = null;
/**
- * name of the plugin
- *
- * name of the plugin (last part of class name) is set in the constructor
- * @access public
- * @var string
- */
- var $plugin_name;
+ * name of the plugin
+ *
+ * name of the plugin (last part of class name) is set in the constructor
+ * @var string $plugin_name
+ */
+ public $plugin_name;
/**
- * text, which precedes error message for the plugin
- *
- *
- * @access public
- * @var string
- */
- var $error_head;
+ * text, which precedes error message for the plugin
+ *
+ *
+ * @var string $error_head
+ */
+ public $error_head;
+ /**
+ * @var $plugin_instances
+ */
private static $plugin_instances;
/**
- * static method to instantiate and retrieve a reference to an object (singleton)
- *
- * use always this method to instantiate a plugin object, it will ensure that only one object of each
- * plugin will exist
- * @access public
- * @static
- * @param string name of plugin, if omitted an array with all plugin objects will be returned
- * @return mixed either a reference to the plugin with the passed name, or an array with references to all plugins
- */
- static function getInstance($plugin_name = false)
+ * static method to instantiate and retrieve a reference to an object (singleton)
+ *
+ * always use this method to instantiate a plugin object, it will ensure that only one object of each
+ * plugin will exist
+ * @param string $plugin_name name of plugin, if omitted an array with all plugin objects will be returned
+ * @return mixed either a reference to the plugin with the passed name, or an array with references to all plugins
+ */
+ public static function getInstance($plugin_name = false)
{
if (!is_array(self::$plugin_instances)) {
- foreach($GLOBALS['STUDIP_AUTH_PLUGIN'] as $plugin) {
- $plugin = "StudipAuth" . $plugin;
- include_once "lib/classes/auth_plugins/" . $plugin . ".class.php";
- self::$plugin_instances[mb_strtoupper($plugin)] = new $plugin;
+ foreach ($GLOBALS['STUDIP_AUTH_PLUGIN'] as $plugin) {
+ $config = $GLOBALS['STUDIP_AUTH_CONFIG_' . strtoupper($plugin)];
+ $plugin_class = $config['plugin_class'] ?? 'StudipAuth' . $plugin;
+ if (empty($config['plugin_name'])) {
+ $config['plugin_name'] = strtolower($plugin);
+ }
+ self::$plugin_instances[strtoupper($plugin)] = new $plugin_class($config);
}
}
- return ($plugin_name) ? self::$plugin_instances[mb_strtoupper("StudipAuth" . $plugin_name)] : self::$plugin_instances;
+ return ($plugin_name) ? self::$plugin_instances[strtoupper($plugin_name)] : self::$plugin_instances;
}
/**
- * static method to check authentication in all plugins
- *
- * if authentication fails in one plugin, the error message is stored and the next plugin is used
- * if authentication succeeds, the uid element in the returned array will contain the Stud.IP user id
- *
- * @access public
- * @static
- * @param string the username to check
- * @param string the password to check
- * @return array structure: array('uid'=>'string <Stud.IP user id>','error'=>'string <error message>','is_new_user'=>'bool')
- */
- static function CheckAuthentication($username, $password)
+ * static method to check authentication in all plugins
+ *
+ * if authentication fails in one plugin, the error message is stored and the next plugin is used
+ * if authentication succeeds, the uid element in the returned array will contain the Stud.IP user id
+ *
+ * @param string $username the username to check
+ * @param string $password the password to check
+ * @return array structure: array('uid'=>'string <Stud.IP user id>','error'=>'string <error message>','is_new_user'=>'bool')
+ */
+ public static function CheckAuthentication($username, $password)
{
$plugins = StudipAuthAbstract::GetInstance();
@@ -157,63 +150,60 @@ class StudipAuthAbstract {
$exp_d = UserConfig::get($user['user_id'])->EXPIRATION_DATE;
if ($exp_d > 0 && $exp_d < time()) {
- $error .= _("Dieses Benutzerkonto ist abgelaufen.<br> Wenden Sie sich bitte an die Administration.") . "<BR>";
+ $error .= _('Dieses Benutzerkonto ist abgelaufen.<br> Wenden Sie sich bitte an die Administration.') . '<BR>';
return ['uid' => false, 'error' => $error];
- } else if ($locked == "1") {
- $error .= _("Dieser Benutzer ist gesperrt! Wenden Sie sich bitte an die Administration.") . "<BR>";
+ } else if ($locked) {
+ $error .= _('Dieser Benutzer ist gesperrt! Wenden Sie sich bitte an die Administration.') . '<BR>';
return ['uid' => false, 'error' => $error];
} else if ($key != '') {
return ['uid' => $uid, 'user' => $user, 'error' => $error, 'need_email_activation' => $uid];
} else if ($checkIPRange && !self::CheckIPRange()) {
- $error .= _("Der Login in Ihren Account ist aus diesem Netzwerk nicht erlaubt.") . "<BR>";
+ $error .= _('Der Login in Ihren Account ist aus diesem Netzwerk nicht erlaubt.') . '<BR>';
return ['uid' => false, 'error' => $error];
}
}
return ['uid' => $uid, 'user' => $user, 'error' => $error, 'is_new_user' => $object->is_new_user];
} else {
- $error .= (($object->error_head) ? ("<b>" . $object->error_head . ":</b> ") : "") . $object->error_msg . "<br>";
+ $error .= (($object->error_head) ? ('<b>' . $object->error_head . ':</b> ') : '') . $object->error_msg . '<br>';
}
}
return ['uid' => $uid, 'error' => $error];
}
/**
- * static method to check if passed username is used in external data sources
- *
- * all plugins are checked, the error messages are stored and returned
- *
- * @access public
- * @static
- * @param string the username
- * @return array
- */
- static function CheckUsername($username)
+ * static method to check if passed username is used in external data sources
+ *
+ * all plugins are checked, the error messages are stored and returned
+ *
+ * @param string $username the username
+ * @return array
+ */
+ public static function CheckUsername($username)
{
$plugins = StudipAuthAbstract::GetInstance();
$error = false;
$found = false;
foreach ($plugins as $object) {
if ($found = $object->isUsedUsername($username)) {
- return ['found' => $found,'error' => $error];
+ return ['found' => $found, 'error' => $error];
} else {
- $error .= (($object->error_head) ? ("<b>" . $object->error_head . ":</b> ") : "") . $object->error_msg . "<br>";
+ $error .= (($object->error_head) ? ('<b>' . $object->error_head . ':</b> ') : '') . $object->error_msg . '<br>';
}
}
- return ['found' => $found,'error' => $error];
+ return ['found' => $found, 'error' => $error];
}
+
/**
- * static method to check for a mapped field
- *
- * this method checks in the plugin with the passed name, if the passed
- * Stud.IP DB field is mapped to an external data source
- *
- * @access public
- * @static
- * @param string the name of the db field must be in form '<table name>.<field name>'
- * @param string the name of the plugin to check
- * @return bool true if the field is mapped, else false
- */
- static function CheckField($field_name,$plugin_name)
+ * static method to check for a mapped field
+ *
+ * this method checks in the plugin with the passed name, if the passed
+ * Stud.IP DB field is mapped to an external data source
+ *
+ * @param string the name of the db field must be in form '<table name>.<field name>'
+ * @param string the name of the plugin to check
+ * @return bool true if the field is mapped, else false
+ */
+ public static function CheckField($field_name, $plugin_name)
{
if (!$plugin_name) {
return false;
@@ -230,7 +220,7 @@ class StudipAuthAbstract {
public static function CheckIPRange()
{
$ip = $_SERVER['REMOTE_ADDR'];
- $version = mb_substr_count($ip, ':') > 1 ? 'V6' : 'V4'; // valid ip v6 addresses have atleast two colons
+ $version = substr_count($ip, ':') > 1 ? 'V6' : 'V4'; // valid ip v6 addresses have atleast two colons
$method = 'CheckIPRange' . $version;
if (is_array($GLOBALS['LOGIN_IP_RANGES'][$version])) {
foreach ($GLOBALS['LOGIN_IP_RANGES'][$version] as $range) {
@@ -275,53 +265,51 @@ class StudipAuthAbstract {
$start = inet_pton($range['start']);
$end = inet_pton($range['end']);
- return mb_strlen($ipv6) === mb_strlen($start)
- && $ipv6 >= $start && $ipv6 <= $end;
+ return strlen($ipv6) === strlen($start)
+ && $ipv6 >= $start && $ipv6 <= $end;
}
/**
- * Constructor
- *
- * the constructor is private, you should use StudipAuthAbstract::GetInstance($plugin_name)
- * to get a reference to a plugin object. Make sure the constructor in the base class is called
- * when deriving your own plugin class, it assigns the settings from local.inc as members of the plugin
- * each key of the $STUDIP_AUTH_CONFIG_<plugin name> array will become a member of the object
- *
- * @access private
- *
- */
- function __construct()
+ * Constructor
+ *
+ * you should use StudipAuthAbstract::GetInstance($plugin_name)
+ * to get a reference to a plugin object. Make sure the constructor in the base class is called
+ * when deriving your own plugin class, it assigns the settings from local.inc as members of the plugin
+ * each key of the $STUDIP_AUTH_CONFIG_<plugin name> array will become a member of the object
+ *
+ * @param array $config
+ */
+ public function __construct($config = [])
{
- $this->plugin_name = mb_strtolower(mb_substr(get_class($this),10));
//get configuration array set in local inc
- $config_var = $GLOBALS["STUDIP_AUTH_CONFIG_" . mb_strtoupper($this->plugin_name)];
+ if (empty($config)) {
+ $this->plugin_name = strtolower(substr(get_class($this), 10));
+ $config = $GLOBALS['STUDIP_AUTH_CONFIG_' . strtoupper($this->plugin_name)];
+ }
//assign each key in the config array as a member of the plugin object
- if (isset($config_var)) {
- foreach ($config_var as $key => $value) {
- $this->$key = $value;
- }
+ foreach ($config as $key => $value) {
+ $this->$key = $value;
}
}
/**
- * authentication method
- *
- * this method authenticates the passed username, it is used by StudipAuthAbstract::CheckAuthentication()
- * if authentication succeeds it calls StudipAuthAbstract::doDataMapping() to map data fields
- * if the authenticated user logs in for the first time it calls StudipAuthAbstract::doNewUserInit() to
- * initialize the new user
- * @access private
- * @param string the username to check
- * @param string the password to check
- * @return string if authentication succeeds the Stud.IP user , else false
- */
- function authenticateUser($username, $password)
+ * authentication method
+ *
+ * this method authenticates the passed username, it is used by StudipAuthAbstract::CheckAuthentication()
+ * if authentication succeeds it calls StudipAuthAbstract::doDataMapping() to map data fields
+ * if the authenticated user logs in for the first time it calls StudipAuthAbstract::doNewUserInit() to
+ * initialize the new user
+ * @param string $username the username to check
+ * @param string $password the password to check
+ * @return string if authentication succeeds the Stud.IP user , else false
+ */
+ public function authenticateUser($username, $password)
{
$username = $this->verifyUsername($username);
if ($this->isAuthenticated($username, $password)) {
if ($user = $this->getStudipUser($username)) {
$this->doDataMapping($user);
- if ($this->is_new_user){
+ if ($this->is_new_user) {
$this->doNewUserInit($user);
}
$this->setUserDomains($user);
@@ -333,24 +321,24 @@ class StudipAuthAbstract {
}
/**
- * method to retrieve the Stud.IP user id to a given username
- *
- *
- * @access private
- * @param string the username
- * @return User the Stud.IP or false if an error occurs
- */
+ * method to retrieve the Stud.IP user id to a given username
+ *
+ *
+ * @access private
+ * @param string the username
+ * @return User the Stud.IP or false if an error occurs
+ */
function getStudipUser($username)
{
$user = User::findByUsername($username);
if ($user) {
$auth_plugin = $user->auth_plugin;
if ($auth_plugin === null) {
- $this->error_msg = _("Dies ist ein vorläufiger Benutzer.") . "<br>";
+ $this->error_msg = _('Dies ist ein vorläufiger Benutzer.') . '<br>';
return false;
}
- if ($auth_plugin != $this->plugin_name){
- $this->error_msg = sprintf(_("Dieser Benutzername wird bereits über %s authentifiziert!"),$auth_plugin) . "<br>";
+ if ($auth_plugin != $this->plugin_name) {
+ $this->error_msg = sprintf(_('Dieser Benutzername wird bereits über %s authentifiziert!'), $auth_plugin) . '<br>';
return false;
}
return $user;
@@ -387,9 +375,10 @@ class StudipAuthAbstract {
* This method sets the user domains for the current user.
*
* @access private
- * @param User the user object
+ * @param User the user object
*/
- function setUserDomains ($user) {
+ function setUserDomains($user)
+ {
$user_domains = $this->getUserDomains();
$uid = $user->id;
if (isset($user_domains)) {
@@ -419,37 +408,43 @@ class StudipAuthAbstract {
/**
* Get the user domains to assign to the current user.
*/
- function getUserDomains ()
+ function getUserDomains()
{
return $this->user_domains;
}
/**
- * this method handles the data mapping
- *
- * for each entry in $this->user_data_mapping the according callback will be invoked
- * the return value of the callback method is then written to the db field, which is specified
- * in the key of the array
- *
- * @access private
- * @param User the user object
- * @return bool
- */
+ * this method handles the data mapping
+ *
+ * for each entry in $this->user_data_mapping the according callback will be invoked
+ * the return value of the callback method is then written to the db field, which is specified
+ * in the key of the array
+ *
+ * @access private
+ * @param User the user object
+ * @return bool
+ */
function doDataMapping($user)
{
if ($user && is_array($this->user_data_mapping)) {
- foreach($this->user_data_mapping as $key => $value){
+ foreach ($this->user_data_mapping as $key => $value) {
+ $callback = null;
if (method_exists($this, $value['callback'])) {
- $split = explode(".",$key);
+ $callback = [$this, $value['callback']];
+ } else if (is_callable($value['callback'])) {
+ $callback = $value['callback'];
+ }
+ if ($callback) {
+ $split = explode('.', $key);
$table = $split[0];
$field = $split[1];
- if ($table == 'auth_user_md5' || $table == 'user_info') {
- $mapped_value = call_user_func([$this, $value['callback']],$value['map_args']);
+ if ($table === 'auth_user_md5' || $table === 'user_info') {
+ $mapped_value = call_user_func($callback, $value['map_args']);
if (isset($mapped_value)) {
$user->setValue($field, $mapped_value);
}
} else {
- call_user_func([$this, $value['callback']],[$table,$field,$user,$value['map_args']]);
+ call_user_func($callback, [$table, $field, $user, $value['map_args']]);
}
}
}
@@ -459,30 +454,30 @@ class StudipAuthAbstract {
}
/**
- * method to check, if a given db field is mapped by the plugin
- *
- *
- * @access private
- * @param string the name of the db field (<table_name>.<field_name>)
- * @return bool true if the field is mapped
- */
+ * method to check, if a given db field is mapped by the plugin
+ *
+ *
+ * @access private
+ * @param string the name of the db field (<table_name>.<field_name>)
+ * @return bool true if the field is mapped
+ */
function isMappedField($name)
{
return isset($this->user_data_mapping[$name]);
}
/**
- * method to eliminate bad characters in the given username
- *
- *
- * @access private
- * @param string the username
- * @return string the username
- */
+ * method to eliminate bad characters in the given username
+ *
+ *
+ * @access private
+ * @param string the username
+ * @return string the username
+ */
function verifyUsername($username)
{
- if($this->username_case_insensitiv) $username = mb_strtolower($username);
- if ($this->bad_char_regex){
+ if ($this->username_case_insensitiv) $username = mb_strtolower($username);
+ if ($this->bad_char_regex) {
return preg_replace($this->bad_char_regex, '', $username);
} else {
return trim($username);
@@ -490,32 +485,33 @@ class StudipAuthAbstract {
}
/**
- * method to check, if username is used
- *
- * abstract MUST be realized
- *
- * @access private
- * @param string the username
- * @return bool true if the username exists
- */
+ * method to check, if username is used
+ *
+ * abstract MUST be realized
+ *
+ * @access private
+ * @param string the username
+ * @return bool true if the username exists
+ */
function isUsedUsername($username)
{
- $this->error_msg = sprintf(_("Methode %s nicht implementiert!"),get_class($this) . "::isUsedUsername()");
+ $this->error_msg = sprintf(_('Methode %s nicht implementiert!'), get_class($this) . '::isUsedUsername()');
return false;
}
/**
- * method to check the authentication of a given username and a given password
- *
- * abstract, MUST be realized
- *
- * @access private
- * @param string the username
- * @param string the password
- * @return bool true if authentication succeeds
- */
- function isAuthenticated($username, $password) {
- $this->error = sprintf(_("Methode %s nicht implementiert!"),get_class($this) . "::isAuthenticated()");
+ * method to check the authentication of a given username and a given password
+ *
+ * abstract, MUST be realized
+ *
+ * @access private
+ * @param string the username
+ * @param string the password
+ * @return bool true if authentication succeeds
+ */
+ function isAuthenticated($username, $password)
+ {
+ $this->error = sprintf(_('Methode %s nicht implementiert!'), get_class($this) . '::isAuthenticated()');
return false;
}
}
diff --git a/lib/classes/auth_plugins/StudipAuthCAS.class.php b/lib/classes/auth_plugins/StudipAuthCAS.class.php
index d28cc3e..620f12e 100644
--- a/lib/classes/auth_plugins/StudipAuthCAS.class.php
+++ b/lib/classes/auth_plugins/StudipAuthCAS.class.php
@@ -3,37 +3,43 @@
# Lifter003: TODO
# Lifter010: TODO
/**
-* Stud.IP authentication against CAS Server
-*
-* @access public
-* @author Dennis Reil <dennis.reil@offis.de>
-* @package
-*/
+ * Stud.IP authentication against CAS Server
+ *
+ * @access public
+ * @author Dennis Reil <dennis.reil@offis.de>
+ * @package
+ */
require_once 'composer/jasig/phpcas/CAS.php';
require_once 'lib/classes/cas/CAS_PGTStorage_Cache.php';
-class StudipAuthCAS extends StudipAuthSSO {
+class StudipAuthCAS extends StudipAuthSSO
+{
- var $host;
- var $port;
- var $uri;
- var $cacert;
+ public $host;
+ public $port;
+ public $uri;
+ public $cacert;
- var $cas;
- var $userdata;
+ public $cas;
+ public $userdata;
/**
- * Constructor
- *
- *
- * @access public
- *
- */
- function __construct() {
- parent::__construct();
-
- if (Request::option('sso')) {
+ * Constructor
+ *
+ *
+ *
+ */
+ public function __construct($config = [])
+ {
+ parent::__construct($config);
+ if (!isset($this->plugin_fullname)) {
+ $this->plugin_fullname = _('CAS');
+ }
+ if (!isset($this->login_description)) {
+ $this->login_description = _('für Single Sign On mit CAS');
+ }
+ if (Request::get('sso') === $this->plugin_name) {
$this->cas = new CAS_Client(CAS_VERSION_2_0, $this->proxy, $this->host, $this->port, $this->uri, false);
if ($this->proxy) {
@@ -68,22 +74,22 @@ class StudipAuthCAS extends StudipAuthSSO {
return $this->getUser();
}
- function getUserData($key){
- $userdataclassname = $GLOBALS["STUDIP_AUTH_CONFIG_CAS"]["user_data_mapping_class"];
- if (empty($userdataclassname)){
- echo ("ERROR: no userdataclassname specified.");
+ function getUserData($key)
+ {
+ $userdataclassname = $this->user_data_mapping_class;
+ if (!class_exists($userdataclassname)) {
+ Log::ERROR($this->plugin_name . ': no userdataclassname specified or found.');
return;
}
- require_once($userdataclassname . ".class.php");
// get the userdata
- if (empty($this->userdata)){
+ if (empty($this->userdata)) {
$this->userdata = new $userdataclassname();
}
- $result = $this->userdata->getUserData($key, $this->cas->getUser());
- return $result;
+ return $this->userdata->getUserData($key, $this->cas->getUser());
}
- function logout(){
+ function logout()
+ {
// do a global cas logout
$this->cas = new CAS_Client(CAS_VERSION_2_0, false, $this->host, $this->port, $this->uri, false);
$this->cas->logout();
diff --git a/lib/classes/auth_plugins/StudipAuthLdap.class.php b/lib/classes/auth_plugins/StudipAuthLdap.class.php
index 3958560..5721cf4 100644
--- a/lib/classes/auth_plugins/StudipAuthLdap.class.php
+++ b/lib/classes/auth_plugins/StudipAuthLdap.class.php
@@ -1,7 +1,4 @@
<?php
-# Lifter007: TODO
-# Lifter003: TODO
-# Lifter010: TODO
// +---------------------------------------------------------------------------+
// This file is part of Stud.IP
// StudipAuthLdap.class.php
@@ -25,39 +22,27 @@
// +---------------------------------------------------------------------------+
/**
-* Stud.IP authentication against LDAP Server
-*
-* Stud.IP authentication against LDAP Server
-*
-* @access public
-* @author André Noack <noack@data-quest.de>
-* @package
-*/
-class StudipAuthLdap extends StudipAuthAbstract {
-
- var $anonymous_bind = true;
-
- var $host;
- var $base_dn;
- var $username_attribute = 'uid';
- var $ldap_filter;
- var $bad_char_regex = '/[^0-9_a-zA-Z]/';
-
- var $conn = null;
- var $user_data = null;
+ * Stud.IP authentication against LDAP Server
+ *
+ * Stud.IP authentication against LDAP Server
+ *
+ * @access public
+ * @author André Noack <noack@data-quest.de>
+ * @package
+ */
+class StudipAuthLdap extends StudipAuthAbstract
+{
- /**
- * Constructor
- *
- *
- * @access public
- *
- */
- function __construct()
- {
- //calling the baseclass constructor
- parent::__construct();
- }
+ public $anonymous_bind = true;
+
+ public $host;
+ public $base_dn;
+ public $username_attribute = 'uid';
+ public $ldap_filter;
+ public $bad_char_regex = '/[^0-9_a-zA-Z]/';
+
+ public $conn = null;
+ public $user_data = null;
function getLdapFilter($username)
@@ -76,16 +61,16 @@ class StudipAuthLdap extends StudipAuthAbstract {
function doLdapConnect()
{
if (!($this->conn = ldap_connect($this->host))) {
- $this->error_msg = _("Keine Verbindung zum LDAP Server möglich.");
+ $this->error_msg = _('Keine Verbindung zum LDAP Server möglich.');
return false;
}
- if (!($r = ldap_set_option($this->conn, LDAP_OPT_PROTOCOL_VERSION, 3))){
- $this->error_msg = _("Setzen der LDAP Protokolversion fehlgeschlagen.");
+ if (!($r = ldap_set_option($this->conn, LDAP_OPT_PROTOCOL_VERSION, 3))) {
+ $this->error_msg = _('Setzen der LDAP Protokolversion fehlgeschlagen.');
return false;
}
if ($this->start_tls) {
if (!ldap_start_tls($this->conn)) {
- $this->error_msg = _("\"Start TLS\" fehlgeschlagen.");
+ $this->error_msg = _('"Start TLS" fehlgeschlagen.');
return false;
}
}
@@ -94,60 +79,60 @@ class StudipAuthLdap extends StudipAuthAbstract {
function getUserDn($username)
{
- $user_dn = "";
+ $user_dn = '';
- if ($this->anonymous_bind){
- if (!($r = @ldap_bind($this->conn))){
- $this->error_msg =_("Anonymer Bind fehlgeschlagen.") . $this->getLdapError();
+ if ($this->anonymous_bind) {
+ if (!($r = @ldap_bind($this->conn))) {
+ $this->error_msg = _('Anonymer Bind fehlgeschlagen.') . $this->getLdapError();
return false;
}
- if (!($result = @ldap_search($this->conn, $this->base_dn, $this->getLdapFilter($username), ['dn']))){
- $this->error_msg = _("Anonymes Durchsuchen des LDAP Baumes fehlgeschlagen.") .$this->getLdapError();
+ if (!($result = @ldap_search($this->conn, $this->base_dn, $this->getLdapFilter($username), ['dn']))) {
+ $this->error_msg = _('Anonymes Durchsuchen des LDAP Baumes fehlgeschlagen.') . $this->getLdapError();
return false;
}
- if (!ldap_count_entries($this->conn, $result)){
- $this->error_msg = sprintf(_("%s wurde nicht unterhalb von %s gefunden."), $username, $this->base_dn);
+ if (!ldap_count_entries($this->conn, $result)) {
+ $this->error_msg = sprintf(_('%s wurde nicht unterhalb von %s gefunden.'), $username, $this->base_dn);
return false;
}
- if (!($entry = @ldap_first_entry($this->conn, $result))){
+ if (!($entry = @ldap_first_entry($this->conn, $result))) {
$this->error_msg = $this->getLdapError();
return false;
}
- if (!($user_dn = @ldap_get_dn($this->conn, $entry))){
+ if (!($user_dn = @ldap_get_dn($this->conn, $entry))) {
$this->error_msg = $this->getLdapError();
return false;
}
} else {
- $user_dn = $this->username_attribute . "=" . $username . "," . $this->base_dn;
+ $user_dn = $this->username_attribute . '=' . $username . ',' . $this->base_dn;
}
return $user_dn;
}
function doLdapBind($username, $password)
{
- if (!$this->doLdapConnect()){
+ if (!$this->doLdapConnect()) {
return false;
}
- if (!($user_dn = $this->getUserDn($username))){
+ if (!($user_dn = $this->getUserDn($username))) {
return false;
}
- if (!$password){
- $this->error_msg = _("Kein Passwort eingegeben."); //some ldap servers seem to allow binding with a user dn and without a password, if anonymous bind is enabled
+ if (!$password) {
+ $this->error_msg = _('Kein Passwort eingegeben.'); //some ldap servers seem to allow binding with a user dn and without a password, if anonymous bind is enabled
return false;
}
- if (!($r = @ldap_bind($this->conn, $user_dn, $password))){
- if(ldap_errno($this->conn) == 49) {
- $this->error_msg = _("Bitte überprüfen Sie ihre Zugangsdaten.");
+ if (!($r = @ldap_bind($this->conn, $user_dn, $password))) {
+ if (ldap_errno($this->conn) == 49) {
+ $this->error_msg = _('Bitte überprüfen Sie ihre Zugangsdaten.');
}
- $this->error_msg = _("Anmeldung fehlgeschlagen.") . $this->getLdapError();
+ $this->error_msg = _('Anmeldung fehlgeschlagen.') . $this->getLdapError();
return false;
}
- if (!($result = @ldap_search($this->conn, $user_dn, "objectclass=*"))){
- $this->error_msg = _("Abholen der Benutzer Attribute fehlgeschlagen.") .$this->getLdapError();
+ if (!($result = @ldap_search($this->conn, $user_dn, 'objectclass=*'))) {
+ $this->error_msg = _('Abholen der Benutzer Attribute fehlgeschlagen.') . $this->getLdapError();
return false;
}
- if (@ldap_count_entries($this->conn, $result)){
- if (!($info = @ldap_get_entries($this->conn, $result))){
+ if (@ldap_count_entries($this->conn, $result)) {
+ if (!($info = @ldap_get_entries($this->conn, $result))) {
$this->error_msg = $this->getLdapError();
return false;
}
@@ -157,15 +142,15 @@ class StudipAuthLdap extends StudipAuthAbstract {
}
/**
- *
- *
- *
- * @access private
- *
- */
+ *
+ *
+ *
+ * @access private
+ *
+ */
function isAuthenticated($username, $password)
{
- if (!$this->doLdapBind($username,$password)){
+ if (!$this->doLdapBind($username, $password)) {
ldap_unbind($this->conn);
return false;
}
@@ -174,12 +159,11 @@ class StudipAuthLdap extends StudipAuthAbstract {
}
-
function doLdapMap($map_params)
{
if (isset($this->user_data[$map_params][0])) {
$ret = $this->user_data[$map_params][0];
- if ($ret[0] == ':') {
+ if ($ret[0] === ':') {
$ret = base64_decode($ret);
}
}
@@ -202,23 +186,23 @@ class StudipAuthLdap extends StudipAuthAbstract {
function isUsedUsername($username)
{
- if (!$this->anonymous_bind){
- $this->error = _("Kann den Benutzernamen nicht überprüfen, anonymous_bind ist ausgeschaltet!");
+ if (!$this->anonymous_bind) {
+ $this->error = _('Kann den Benutzernamen nicht überprüfen, anonymous_bind ist ausgeschaltet!');
return false;
}
- if (!$this->doLdapConnect()){
+ if (!$this->doLdapConnect()) {
return false;
}
- if (!($r = @ldap_bind($this->conn))){
- $this->error = _("Anonymer Bind fehlgeschlagen.") . $this->getLdapError();
+ if (!($r = @ldap_bind($this->conn))) {
+ $this->error = _('Anonymer Bind fehlgeschlagen.') . $this->getLdapError();
return false;
}
- if (!($result = @ldap_search($this->conn, $this->base_dn, $this->getLdapFilter($username), ['dn']))){
- $this->error = _("Anonymes Durchsuchen des LDAP Baumes fehlgeschlagen.") .$this->getLdapError();
+ if (!($result = @ldap_search($this->conn, $this->base_dn, $this->getLdapFilter($username), ['dn']))) {
+ $this->error = _('Anonymes Durchsuchen des LDAP Baumes fehlgeschlagen.') . $this->getLdapError();
return false;
}
- if (!ldap_count_entries($this->conn, $result)){
- $this->error_msg = _("Der Benutzername wurde nicht gefunden.");
+ if (!ldap_count_entries($this->conn, $result)) {
+ $this->error_msg = _('Der Benutzername wurde nicht gefunden.');
return false;
}
return true;
@@ -226,6 +210,6 @@ class StudipAuthLdap extends StudipAuthAbstract {
function getLdapError()
{
- return _("<br>LDAP Fehler: ") . ldap_error($this->conn) ." (#" . ldap_errno($this->conn) . ")";
+ return _('<br>LDAP Fehler: ') . ldap_error($this->conn) . ' (#' . ldap_errno($this->conn) . ')';
}
}
diff --git a/lib/classes/auth_plugins/StudipAuthLdapReadAndBind.class.php b/lib/classes/auth_plugins/StudipAuthLdapReadAndBind.class.php
index 25e8739..742f0cb 100644
--- a/lib/classes/auth_plugins/StudipAuthLdapReadAndBind.class.php
+++ b/lib/classes/auth_plugins/StudipAuthLdapReadAndBind.class.php
@@ -26,61 +26,51 @@
// +---------------------------------------------------------------------------+
/**
-* Stud.IP authentication against LDAP Server
-*
-* Stud.IP authentication against LDAP Server using read-only account and
-* following user bind
-*
-* @access public
-* @author André Noack <noack@data-quest.de>
-* @package
-*/
-class StudipAuthLdapReadAndBind extends StudipAuthLdap {
+ * Stud.IP authentication against LDAP Server
+ *
+ * Stud.IP authentication against LDAP Server using read-only account and
+ * following user bind
+ *
+ * @access public
+ * @author André Noack <noack@data-quest.de>
+ * @package
+ */
+class StudipAuthLdapReadAndBind extends StudipAuthLdap
+{
- var $anonymous_bind = false;
+ public $anonymous_bind = false;
- var $reader_dn;
- var $reader_password;
+ public $reader_dn;
+ public $reader_password;
- /**
- * Constructor
- *
- *
- * @access public
- *
- */
- function __construct() {
- //calling the baseclass constructor
- parent::__construct();
- }
-
-
- function getUserDn($username){
- $user_dn = "";
- if (!($r = @ldap_bind($this->conn, $this->reader_dn, $this->reader_password))){
- $this->error_msg = sprintf(_("Anmeldung von %s fehlgeschlagen."),$this->reader_dn) . $this->getLdapError();
+ function getUserDn($username)
+ {
+ $user_dn = '';
+ if (!($r = @ldap_bind($this->conn, $this->reader_dn, $this->reader_password))) {
+ $this->error_msg = sprintf(_('Anmeldung von %s fehlgeschlagen.'), $this->reader_dn) . $this->getLdapError();
return false;
}
- if (!($result = @ldap_search($this->conn, $this->base_dn, $this->getLdapFilter($username), ['dn']))){
- $this->error_msg = _("Durchsuchen des LDAP Baumes fehlgeschlagen.") .$this->getLdapError();
+ if (!($result = @ldap_search($this->conn, $this->base_dn, $this->getLdapFilter($username), ['dn']))) {
+ $this->error_msg = _('Durchsuchen des LDAP Baumes fehlgeschlagen.') . $this->getLdapError();
return false;
}
- if (!ldap_count_entries($this->conn, $result)){
- $this->error_msg = sprintf(_("%s wurde nicht unterhalb von %s gefunden."), $username, $this->base_dn);
+ if (!ldap_count_entries($this->conn, $result)) {
+ $this->error_msg = sprintf(_('%s wurde nicht unterhalb von %s gefunden.'), $username, $this->base_dn);
return false;
}
- if (!($entry = @ldap_first_entry($this->conn, $result))){
+ if (!($entry = @ldap_first_entry($this->conn, $result))) {
$this->error_msg = $this->getLdapError();
return false;
}
- if (!($user_dn = @ldap_get_dn($this->conn, $entry))){
+ if (!($user_dn = @ldap_get_dn($this->conn, $entry))) {
$this->error_msg = $this->getLdapError();
return false;
}
return $user_dn;
}
- function isUsedUsername($username){
+ function isUsedUsername($username)
+ {
if (!$this->doLdapConnect()) {
return false;
}
diff --git a/lib/classes/auth_plugins/StudipAuthOIDC.class.php b/lib/classes/auth_plugins/StudipAuthOIDC.class.php
new file mode 100644
index 0000000..adfe9c9
--- /dev/null
+++ b/lib/classes/auth_plugins/StudipAuthOIDC.class.php
@@ -0,0 +1,112 @@
+<?php
+/*
+ * StudipAuthOpenID.class.php - Stud.IP authentication using OpenID Connect
+ * Copyright (c) 2021 André Noack <noack@data-quest.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+use Jumbojett\OpenIDConnectClient;
+use Jumbojett\OpenIDConnectClientException;
+
+class StudipAuthOIDC extends StudipAuthSSO
+{
+ /**
+ * @var OpenIDConnectClient
+ */
+ private $oidc;
+
+ /**
+ * @var string
+ */
+ public $provider_url;
+ /**
+ * @var string
+ */
+ public $client_id;
+ /**
+ * @var string
+ */
+ public $client_secret;
+
+
+ /**
+ * @param array $config
+ */
+ public function __construct($config = [])
+ {
+ parent::__construct($config);
+ if (Request::get('sso') === $this->plugin_name) {
+ $this->oidc = new OpenIDConnectClient($this->provider_url, $this->client_id, $this->client_secret);
+ if (isset($this->ssl_options)) {
+ foreach ($this->ssl_options as $option_key => $option_value) {
+ if (isset($option_value)) {
+ $this->oidc->{'set' . $option_key}($option_value);
+ }
+ }
+ if (Config::get()->HTTP_PROXY) {
+ $this->oidc->setHttpProxy(Config::get()->HTTP_PROXY);
+ }
+ $return_url = URLHelper::getScriptURL($GLOBALS['ABSOLUTE_URI_STUDIP'] . 'index.php', ['sso' => $this->plugin_name, 'again' => 'yes']);
+ $this->oidc->setRedirectURL($return_url);
+ $this->oidc->addScope(['openid', 'email', 'profile']);
+ }
+ }
+ }
+
+ /**
+ * Validate the username passed to the auth plugin.
+ *
+ * @param string $username
+ *
+ * @return string username openid attribute user_id@domain
+ *
+ * @throws OpenIDConnectClientException
+ */
+ public function verifyUsername($username)
+ {
+
+ $this->oidc->authenticate();
+ $this->userdata = (array)$this->oidc->requestUserInfo();
+ if (isset($this->userdata['sub'])) {
+ return $this->userdata['username'] = $this->userdata['sub'] . '@' . $this->domain;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Return the current username of the pending authentication request.
+ */
+ public function getUser()
+ {
+ return $this->userdata['username'];
+ }
+
+ /**
+ * Get the user domains to assign to the current user (if any).
+ *
+ * @return array array of user domain names
+ */
+ public function getUserDomains()
+ {
+ return $this->domain ? [$this->domain] : null;
+ }
+
+ /**
+ * Callback that can be used in user_data_mapping array.
+ *
+ * @see https://openid.net/specs/openid-connect-basic-1_0.html#StandardClaims
+ *
+ * @param string key
+ *
+ * @return string parameter value (null if not set)
+ */
+ public function getUserData($key)
+ {
+ return $this->userdata[$key];
+ }
+}
diff --git a/lib/classes/auth_plugins/StudipAuthSSO.class.php b/lib/classes/auth_plugins/StudipAuthSSO.class.php
index 65e8cd1..752fa59 100644
--- a/lib/classes/auth_plugins/StudipAuthSSO.class.php
+++ b/lib/classes/auth_plugins/StudipAuthSSO.class.php
@@ -18,6 +18,16 @@
abstract class StudipAuthSSO extends StudipAuthAbstract
{
/**
+ * @var string the descriptive name of the authentication plugin
+ */
+ public $plugin_fullname;
+
+ /**
+ * @var string a short description, when present it is shown on the login page
+ */
+ public $login_description;
+
+ /**
* Return the current username.
*/
abstract function getUser ();
diff --git a/lib/classes/auth_plugins/StudipAuthShib.class.php b/lib/classes/auth_plugins/StudipAuthShib.class.php
index 5ac00ed..8f31eef 100644
--- a/lib/classes/auth_plugins/StudipAuthShib.class.php
+++ b/lib/classes/auth_plugins/StudipAuthShib.class.php
@@ -14,28 +14,39 @@
class StudipAuthShib extends StudipAuthSSO
{
- var $env_remote_user = 'HTTP_REMOTE_USER';
- var $local_domain;
- var $session_initiator;
- var $validate_url;
- var $userdata;
+ public $env_remote_user = 'HTTP_REMOTE_USER';
+ public $local_domain;
+ public $session_initiator;
+ public $validate_url;
+ public $userdata;
+ public $username_attribute = 'username';
/**
* Constructor: read auth information from remote SP.
*/
- function __construct()
+ public function __construct($config = [])
{
- parent::__construct();
+ parent::__construct($config);
- if (Request::option('sso') && isset($this->validate_url) && isset($_REQUEST['token'])) {
+ if (!isset($this->plugin_fullname)) {
+ $this->plugin_fullname = _('Shibboleth');
+ }
+ if (!isset($this->login_description)) {
+ $this->login_description = _('für Single Sign On mit Shibboleth');
+ }
+
+ if (Request::get('sso') === $this->plugin_name && isset($this->validate_url) && isset($_REQUEST['token'])) {
$context = get_default_http_stream_context($this->validate_url);
- $auth = file_get_contents($this->validate_url.'/'.$_REQUEST['token'], false, $context);
+ $auth = file_get_contents($this->validate_url . '/' . $_REQUEST['token'], false, $context);
$this->userdata = json_decode($auth, true);
+ if ($this->username_attribute !== 'username') {
+ $this->userdata['username'] = $this->userdata[$this->username_attribute];
+ }
if (isset($this->local_domain)) {
$this->userdata['username'] =
- str_replace('@'.$this->local_domain, '', $this->userdata['username']);
+ str_replace('@' . $this->local_domain, '', $this->userdata['username']);
}
}
}
@@ -43,7 +54,7 @@ class StudipAuthShib extends StudipAuthSSO
/**
* Return the current username.
*/
- function getUser ()
+ function getUser()
{
return $this->userdata['username'];
}
@@ -51,7 +62,7 @@ class StudipAuthShib extends StudipAuthSSO
/**
* Return the current URL (including parameters).
*/
- function getURL ()
+ function getURL()
{
$url = $_SERVER['HTTPS'] == 'on' ? 'https' : 'http';
$url .= '://';
@@ -64,7 +75,7 @@ class StudipAuthShib extends StudipAuthSSO
if ($_SERVER['HTTPS'] == 'on' && $_SERVER['SERVER_PORT'] != 443 ||
$_SERVER['HTTPS'] != 'on' && $_SERVER['SERVER_PORT'] != 80) {
- $url .= ':'.$_SERVER['SERVER_PORT'];
+ $url .= ':' . $_SERVER['SERVER_PORT'];
}
$url .= $_SERVER['REQUEST_URI'];
@@ -75,7 +86,7 @@ class StudipAuthShib extends StudipAuthSSO
* Validate the username passed to the auth plugin.
* Note: This triggers authentication if needed.
*/
- function verifyUsername ($username)
+ function verifyUsername($username)
{
if (isset($this->userdata)) {
// use cached user information
@@ -89,15 +100,15 @@ class StudipAuthShib extends StudipAuthSSO
}
if (empty($remote_user) || isset($this->validate_url)) {
- if ($_REQUEST['sso'] == 'shib') {
+ if (Request::get('sso') === $this->plugin_name) {
// force Shibboleth authentication (lazy session)
$shib_url = $this->session_initiator;
- $shib_url .= mb_strpos($shib_url, '?') === false ? '?' : '&';
- $shib_url .= 'target='.urlencode($this->getURL());
+ $shib_url .= strpos($shib_url, '?') === false ? '?' : '&';
+ $shib_url .= 'target=' . urlencode($this->getURL());
// break redirection loop in case of misconfiguration
- if (mb_strstr($_SERVER['HTTP_REFERER'], 'target=') == false) {
- header('Location: '.$shib_url);
+ if (strstr($_SERVER['HTTP_REFERER'], 'target=') === false) {
+ header('Location: ' . $shib_url);
echo '<html></html>';
exit();
}
@@ -107,10 +118,6 @@ class StudipAuthShib extends StudipAuthSSO
return NULL;
}
- if (isset($this->local_domain)) {
- $remote_user = str_replace('@'.$this->local_domain, '', $remote_user);
- }
-
// import authentication information
$this->userdata['username'] = $remote_user;
@@ -121,13 +128,20 @@ class StudipAuthShib extends StudipAuthSSO
}
}
+ if ($this->username_attribute !== 'username') {
+ $this->userdata['username'] = $this->userdata[$this->username_attribute];
+ }
+ if (isset($this->local_domain)) {
+ $this->userdata['username'] =
+ str_replace('@' . $this->local_domain, '', $this->userdata['username']);
+ }
return $this->getUser();
}
/**
* Get the user domains to assign to the current user.
*/
- function getUserDomains ()
+ function getUserDomains()
{
$user = $this->getUser();
$pos = mb_strpos($user, '@');
@@ -142,7 +156,7 @@ class StudipAuthShib extends StudipAuthSSO
/**
* Callback that can be used in user_data_mapping array.
*/
- function getUserData ($key)
+ function getUserData($key)
{
$data = explode(';', $this->userdata[$key]);
diff --git a/lib/classes/auth_plugins/StudipAuthStandard.class.php b/lib/classes/auth_plugins/StudipAuthStandard.class.php
index c195053..1a2c2ba 100644
--- a/lib/classes/auth_plugins/StudipAuthStandard.class.php
+++ b/lib/classes/auth_plugins/StudipAuthStandard.class.php
@@ -39,18 +39,6 @@ class StudipAuthStandard extends StudipAuthAbstract
var $bad_char_regex = false;
/**
- * Constructor
- *
- *
- * @access public
- *
- */
- function __construct()
- {
- parent::__construct();
- }
-
- /**
*
*
*
@@ -61,19 +49,19 @@ class StudipAuthStandard extends StudipAuthAbstract
{
$user = User::findByUsername($username);
if (!$user || !$password || mb_strlen($password) > 72) {
- $this->error_msg= _("Ungültige Benutzername/Passwort-Kombination!") ;
+ $this->error_msg= _('Ungültige Benutzername/Passwort-Kombination!') ;
return false;
- } elseif ($user->username != $username) {
- $this->error_msg = _("Bitte achten Sie auf korrekte Gro&szlig;-Kleinschreibung beim Username!");
+ } elseif ($user->username !== $username) {
+ $this->error_msg = _('Bitte achten Sie auf korrekte Groß-Kleinschreibung beim Username!');
return false;
- } elseif (!is_null($user->auth_plugin) && $user->auth_plugin != "standard") {
- $this->error_msg = sprintf(_("Dieser Benutzername wird bereits über %s authentifiziert!"),$user->auth_plugin) ;
+ } elseif (!is_null($user->auth_plugin) && $user->auth_plugin !== 'standard') {
+ $this->error_msg = sprintf(_('Dieser Benutzername wird bereits über %s authentifiziert!'),$user->auth_plugin) ;
return false;
} else {
$pass = $user->password; // Password is stored as a md5 hash
}
$hasher = UserManagement::getPwdHasher();
- $old_style_check = (mb_strlen($pass) == 32 && md5($password) == $pass);
+ $old_style_check = (strlen($pass) === 32 && md5($password) === $pass);
$migrated_check = $hasher->CheckPassword(md5($password), $pass);
$check = $hasher->CheckPassword($password, $pass);
$old_encoding_check = $hasher->CheckPassword(legacy_studip_utf8decode($password), $pass);
@@ -85,7 +73,7 @@ class StudipAuthStandard extends StudipAuthAbstract
}
if (!($check || $migrated_check || $old_style_check || $old_encoding_check)) {
- $this->error_msg= _("Das Passwort ist falsch!");
+ $this->error_msg= _('Das Passwort ist falsch!');
return false;
} else {
return true;
diff --git a/lib/navigation/LoginNavigation.php b/lib/navigation/LoginNavigation.php
index cc6372b..db21236 100644
--- a/lib/navigation/LoginNavigation.php
+++ b/lib/navigation/LoginNavigation.php
@@ -27,16 +27,12 @@ class LoginNavigation extends Navigation
$navigation->setDescription(_('für registrierte NutzerInnen'));
$this->addSubNavigation('login', $navigation);
- if (in_array('CAS', $GLOBALS['STUDIP_AUTH_PLUGIN'])) {
- $navigation = new Navigation(_('Login'), 'index.php?again=yes&sso=cas');
- $navigation->setDescription(_('für Single Sign On mit CAS'));
- $this->addSubNavigation('login_cas', $navigation);
- }
-
- if (in_array('Shib', $GLOBALS['STUDIP_AUTH_PLUGIN'])) {
- $navigation = new Navigation(_('Shibboleth Login'), 'index.php?again=yes&sso=shib');
- $navigation->setDescription(_('für Single Sign On mit Shibboleth'));
- $this->addSubNavigation('login_shib', $navigation);
+ foreach (StudipAuthAbstract::getInstance() as $auth_plugin) {
+ if ($auth_plugin instanceof StudipAuthSSO && isset($auth_plugin->login_description)) {
+ $navigation = new Navigation($auth_plugin->plugin_fullname . ' ' . _('Login'), 'index.php?again=yes&sso=' . $auth_plugin->plugin_name);
+ $navigation->setDescription($auth_plugin->login_description);
+ $this->addSubNavigation('login_' . $auth_plugin->plugin_name, $navigation);
+ }
}
if (Config::get()->ENABLE_SELF_REGISTRATION) {