From 056aec606a5e917ed7c1e35c6bafd4bf3d3bd5f2 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Tue, 1 Feb 2022 15:06:55 +1300 Subject: [PATCH 01/32] Don't use cookie --- README.md | 10 ---- lib/Auth/Source/External.php | 97 +++++++++++++----------------------- lib/ConfigHelper.php | 75 ++++------------------------ www/resume.php | 2 +- 4 files changed, 48 insertions(+), 136 deletions(-) diff --git a/README.md b/README.md index ca6ec8a..3bce9ae 100644 --- a/README.md +++ b/README.md @@ -71,11 +71,6 @@ Configure the authentication source by putting following code into `simplesamlph // Whether to turn on debug 'debug' => true, - // Cookie name. Set this to use a cache-busting cookie pattern - // (e.g. 'SESSdrupalauth4ssp') if hosted on Pantheon so that the cookie - // is is not stripped away by Varnish. See https://pantheon.io/docs/cookies#cache-busting-cookies . - 'cookie_name' => 'drupalauth4ssp', - // Which attributes should be retrieved from the Drupal site. 'attributes' => array( array('field_name' => 'uid', 'attribute_name' => 'uid'), @@ -108,11 +103,6 @@ Configure the authentication source by putting following code into `simplesamlph // Whether to turn on debug 'debug' => true, - // Cookie name. Set this to use a cache-busting cookie pattern - // (e.g. 'SESSdrupalauth4ssp') if hosted on Pantheon so that the cookie - // is is not stripped away by Varnish. See https://pantheon.io/docs/cookies#cache-busting-cookies . - 'cookie_name' => 'drupalauth4ssp', - // the URL of the Drupal logout page 'drupal_logout_url' => 'https://www.example.com/drupal/user/logout', diff --git a/lib/Auth/Source/External.php b/lib/Auth/Source/External.php index 6be7226..131c8f3 100755 --- a/lib/Auth/Source/External.php +++ b/lib/Auth/Source/External.php @@ -46,9 +46,6 @@ * // Whether to turn on debug * 'debug' => true, * - * // Cookie name. - * 'cookie_name' => 'drupalauth4ssp' - * * // URL of the Drupal logout page. * 'drupal_logout_url' => 'https://www.example.com/drupal7/user/logout', * @@ -78,7 +75,22 @@ class External extends Source { - /** + /** + * The string used to identify Drupal user ID. + */ + const DRUPALAUTH_EXTERNAL_USER_ID = 'drupalauth:External:UserID'; + + /** + * The string used to identify authentication source. + */ + const DRUPALAUTH_AUTH_ID = 'drupalauth:AuthID'; + + /** + * The string used to identify our states. + */ + const DRUPALAUTH_EXTERNAL = 'drupalauth:External'; + + /** * Configuration object. * * @var \SimpleSAML\Module\drupalauth\ConfigHelper @@ -114,46 +126,14 @@ public function __construct($info, $config) * * @return array|NULL The user's attributes, or NULL if the user isn't authenticated. */ - private function getUser() + private function getUser($drupaluid) { - - $drupaluid = null; - - // Pull the Drupal UID out of the cookie. - $cookie_name = $this->config->getCookieName(); - if (isset($_COOKIE[$cookie_name]) && $_COOKIE[$cookie_name]) { - $strCookie = $_COOKIE[$cookie_name]; - list($cookie_hash, $uid) = explode(':', $strCookie); - - // make sure the hash matches - // make sure the UID is passed - if ((isset($cookie_hash) && !empty($cookie_hash)) && (isset($uid) && !empty($uid))) { - $drupalHelper = new DrupalHelper(); - $drupalHelper->bootDrupal($this->config->getDrupalroot()); - - // Make sure no one manipulated the hash or the uid in the cookie before we trust the uid - $hash = Crypt::hmacBase64( - $uid, - $this->config->getCookieSalt() . \Drupal::service('private_key')->get() - ); - if (!hash_equals($hash, $cookie_hash)) { - throw new Exception( - 'Cookie hash invalid. This indicates either tampering or an out of date drupal4ssp module.' - ); - } - $drupaluid = $uid; - } - } - - - // Delete the cookie, we don't need it anymore - if (isset($_COOKIE[$cookie_name])) { - setcookie($cookie_name, "", time() - 3600, $this->config->getCookiePath()); - } - if (!empty($drupaluid)) { - // Load the user object from Drupal. - $drupaluser = User::load($uid); + $drupalHelper = new DrupalHelper(); + $drupalHelper->bootDrupal($this->config->getDrupalroot()); + + // Load the user object from Drupal. + $drupaluser = User::load($drupaluid); if ($drupaluser->isBlocked()) { throw new Error('NOACCESS'); } @@ -173,7 +153,7 @@ public function authenticate(&$state) { assert(is_array($state)); - $attributes = $this->getUser(); + $attributes = $this->getUser($state[self::DRUPALAUTH_EXTERNAL_USER_ID]); if ($attributes !== null) { /* * The user is already authenticated. @@ -194,7 +174,7 @@ public function authenticate(&$state) * First we add the identifier of this authentication source * to the state array, so that we know where to resume. */ - $state['drupalauth:AuthID'] = $this->getAuthId(); + $state[self::DRUPALAUTH_AUTH_ID] = $this->getAuthId(); /* * We need to save the $state-array, so that we can resume the @@ -209,7 +189,7 @@ public function authenticate(&$state) * and restores it in another location, and thus bypasses steps in * the authentication process. */ - $stateId = State::saveState($state, 'drupalauth:External'); + $stateId = State::saveState($state, self::DRUPALAUTH_EXTERNAL); /* * Now we generate a URL the user should return to after authentication. @@ -253,13 +233,13 @@ public function authenticate(&$state) * * @param array &$state The authentication state. */ - public static function resume() + public static function resume($stateID) { /* * First we need to restore the $state-array. We should have the identifier for * it in the 'State' request parameter. */ - if (!isset($_REQUEST['State'])) { + if (!isset($stateID)) { throw new BadRequest('Missing "State" parameter.'); } @@ -267,19 +247,19 @@ public static function resume() * Once again, note the second parameter to the loadState function. This must * match the string we used in the saveState-call above. */ - $state = State::loadState($_REQUEST['State'], 'drupalauth:External'); + $state = State::loadState($stateID, self::DRUPALAUTH_EXTERNAL); /* * Now we have the $state-array, and can use it to locate the authentication * source. */ - $source = Source::getById($state['drupalauth:AuthID']); + $source = Source::getById($state[self::DRUPALAUTH_AUTH_ID]); if ($source === null) { /* * The only way this should fail is if we remove or rename the authentication source * while the user is at the login page. */ - throw new Exception('Could not find authentication source with ID: ' . $state['drupalauth:AuthID']); + throw new Exception('Could not find authentication source with ID: ' . $state[self::DRUPALAUTH_AUTH_ID]); } /* @@ -291,12 +271,12 @@ public static function resume() throw new Exception('Authentication source type changed.'); } - /* - * OK, now we know that our current state is sane. Time to actually log the user in. - * - * First we check that the user is acutally logged in, and didn't simply skip the login page. - */ - $attributes = $source->getUser(); + /* + * OK, now we know that our current state is sane. Time to actually log the user in. + * + * First we check that the user is acutally logged in, and didn't simply skip the login page. + */ + $attributes = $source->getUser($state[self::DRUPALAUTH_EXTERNAL_USER_ID]); if ($attributes === null) { /* * The user isn't authenticated. @@ -336,11 +316,6 @@ public function logout(&$state) session_start(); } - // Added armor plating, just in case. - if (isset($_COOKIE[$this->config->getCookieName()])) { - setcookie($this->config->getCookieName(), "", time() - 3600, $this->config->getCookiePath()); - } - $logout_url = $this->config->getDrupalLogoutURL(); $parameters = []; if (!empty($state['ReturnTo'])) { diff --git a/lib/ConfigHelper.php b/lib/ConfigHelper.php index 0b72c0c..d67650f 100644 --- a/lib/ConfigHelper.php +++ b/lib/ConfigHelper.php @@ -39,24 +39,6 @@ class ConfigHelper private $attributes; - /** - * The name of the cookie - */ - private $cookie_name; - - - /** - * Cookie path. - */ - private $cookie_path; - - - /** - * Cookie salt. - */ - private $cookie_salt; - - /** * The Drupal logout URL */ @@ -75,28 +57,22 @@ class ConfigHelper * @param array $config Configuration. * @param string $location The location of this configuration. Used for error reporting. */ - public function __construct($config, $location) - { - assert(is_array($config)); - assert(is_string($location)); - - $this->location = $location; + public function __construct($config, $location) { + assert(is_array($config)); + assert(is_string($location)); - /* Get authsource configuration. */ - $config = Configuration::loadFromArray($config, $location); + $this->location = $location; - $this->drupalroot = $config->getString('drupalroot'); - $this->debug = $config->getBoolean('debug', false); - $this->attributes = $config->getArray('attributes', []); - $this->cookie_name = $config->getString('cookie_name', 'drupalauth4ssp'); - $this->drupal_logout_url = $config->getString('drupal_logout_url', null); - $this->drupal_login_url = $config->getString('drupal_login_url', null); + /* Get authsource configuration. */ + $config = Configuration::loadFromArray($config, $location); - $this->cookie_path = Configuration::getInstance()->getBasePath(); - $this->cookie_salt = Config::getSecretSalt(); + $this->drupalroot = $config->getString('drupalroot'); + $this->debug = $config->getBoolean('debug', FALSE); + $this->attributes = $config->getArray('attributes', []); + $this->drupal_logout_url = $config->getString('drupal_logout_url', NULL); + $this->drupal_login_url = $config->getString('drupal_login_url', NULL); } - /** * Returns debug mode. * @@ -127,35 +103,6 @@ public function getAttributes() return $this->attributes; } - /** - * Returns cookie name. - * - * @return string - */ - public function getCookieName() - { - return $this->cookie_name; - } - - /** - * Returns cookie path. - * - * @return string - */ - public function getCookiePath() - { - return $this->cookie_path; - } - - /** - * Returns cookie salt. - * - * @return string - */ - public function getCookieSalt() - { - return $this->cookie_salt; - } /** * Returns Drupal logout URL. diff --git a/www/resume.php b/www/resume.php index 7bc7456..6901749 100644 --- a/www/resume.php +++ b/www/resume.php @@ -9,4 +9,4 @@ use SimpleSAML\Module\drupalauth\Auth\Source\External; -External::resume(); +External::resume($_REQUEST['State']); From 5e646761f0efba5b338da89e60eeeb5af289ef1a Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Tue, 7 Nov 2023 06:58:43 +1300 Subject: [PATCH 02/32] Fix branch alias --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f812457..bb846a7 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.8.x-dev" + "dev-master": "1.9.x-dev" } } } From 44afc5e1ee2c5aa0e8bf9c1786b3190dd6e31fa1 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Tue, 7 Nov 2023 07:15:32 +1300 Subject: [PATCH 03/32] Check ID first --- lib/Auth/Source/External.php | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/lib/Auth/Source/External.php b/lib/Auth/Source/External.php index 131c8f3..b335105 100755 --- a/lib/Auth/Source/External.php +++ b/lib/Auth/Source/External.php @@ -153,16 +153,15 @@ public function authenticate(&$state) { assert(is_array($state)); - $attributes = $this->getUser($state[self::DRUPALAUTH_EXTERNAL_USER_ID]); - if ($attributes !== null) { - /* - * The user is already authenticated. - * - * Add the users attributes to the $state-array, and return control - * to the authentication process. - */ - $state['Attributes'] = $attributes; - return; + /* + * The user is already authenticated. + * + * Add the users attributes to the $state-array, and return control + * to the authentication process. + */ + if (!empty($state[self::DRUPALAUTH_EXTERNAL_USER_ID])) { + $state['Attributes'] = $this->getUser($state[self::DRUPALAUTH_EXTERNAL_USER_ID]); + return; } /* @@ -271,11 +270,16 @@ public static function resume($stateID) throw new Exception('Authentication source type changed.'); } - /* - * OK, now we know that our current state is sane. Time to actually log the user in. - * - * First we check that the user is acutally logged in, and didn't simply skip the login page. - */ + /* + * First we check that the user is acutally logged in, and didn't simply skip the login page. + */ + if (empty($state[self::DRUPALAUTH_EXTERNAL_USER_ID])) { + throw new Exception('User ID is missing.'); + } + + /* + * OK, now we know that our current state is sane. Time to actually log the user in. + */ $attributes = $source->getUser($state[self::DRUPALAUTH_EXTERNAL_USER_ID]); if ($attributes === null) { /* From 207057ced2bbac6a239c352e240f9b60f0ab0803 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Tue, 7 Nov 2023 08:24:23 +1300 Subject: [PATCH 04/32] Allow simplesamlphp/composer-module-installer to run --- composer.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/composer.json b/composer.json index bb846a7..714af83 100644 --- a/composer.json +++ b/composer.json @@ -36,5 +36,10 @@ "branch-alias": { "dev-master": "1.9.x-dev" } + }, + "config": { + "allow-plugins": { + "simplesamlphp/composer-module-installer": true + } } } From 5d1261debd453e0d50c2b926030aa5b0519086e2 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Thu, 2 Nov 2023 19:28:55 +1300 Subject: [PATCH 05/32] Start of version 2 compatibility --- README.md | 7 ++++--- composer.json | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3bce9ae..b5b6ca8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Introduction -[![Build Status](https://travis-ci.com/drupalauth/simplesamlphp-module-drupalauth.svg?branch=master)](https://travis-ci.com/drupalauth/simplesamlphp-module-drupalauth) +[![Build Status](https://travis-ci.com/drupalauth/simplesamlphp-module-drupalauth.svg?branch=main)](https://travis-ci.com/drupalauth/simplesamlphp-module-drupalauth) Drupal + SimpleSAMLphp + drupalauth = Complete SAML Identity Provider (IdP) @@ -32,9 +32,10 @@ So in a X.Y.Z version: - Y - major Drupal version - Z - inthis module incremental version -Example: for SimpleSAMLphp version 1.15.4 with Drupal version 8.5.6 and this module version 1 we will have tag 1.8.1. Same thing for Drupal 7 will be 1.7.1. +Example: for SimpleSAMLphp version 1.15.4 with Drupal version 8.5.6 and this module version 1 we will have tag 1.8.1. +Same thing for Drupal 7 will be 1.7.1. -`master` at the moment corresponds to 1.8.*. Branch `1.7` is respectfully for Drupal 7 (not composer integration yet). +`main` at the moment corresponds to `2.10.*`. Branch `1.7` is respectfully for Drupal 7 (no Composer integration). ## Note on Drupal configuration diff --git a/composer.json b/composer.json index 714af83..6d4d588 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ ], "require": { "php": "^5.6.0|^7.0|^8.0", - "simplesamlphp/simplesamlphp": "~1.0", + "simplesamlphp/simplesamlphp": "~2.0", "simplesamlphp/composer-module-installer": "~1.0" }, "require-dev": { @@ -34,7 +34,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.9.x-dev" + "dev-main": "2.10.x-dev" } }, "config": { From ba158fa380a6e3b55872ec63b5fe5aa8e54719af Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Thu, 2 Nov 2023 23:00:37 +1300 Subject: [PATCH 06/32] Extend bug template --- .github/ISSUE_TEMPLATE/bug_report.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 6eba880..dc5dc53 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -29,6 +29,9 @@ If applicable, add screenshots to help explain your problem. - Drupal core version - SimpleSAMLphp version - webserver version and configuration +- drupalauth/simplesamlphp-module-drupalauth version +- authentication source plugin used +- drupalauth4ssp module version, if used **Additional context** Add any other context about the problem here. From 84494d268e82d8d521931ae00dc5ce6efa78f558 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Fri, 3 Nov 2023 08:08:08 +1300 Subject: [PATCH 07/32] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b5b6ca8..f4d6d69 100644 --- a/README.md +++ b/README.md @@ -48,9 +48,9 @@ See this issue '/var/www/drupal-8.0', + 'drupalroot' => '/var/www/drupal', // Whether to turn on debug 'debug' => true, From 0f6abd7951af4651f9536592097127ba2c346874 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Fri, 3 Nov 2023 08:08:33 +1300 Subject: [PATCH 08/32] Modules must be explicitly enabled --- default-enable | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 default-enable diff --git a/default-enable b/default-enable deleted file mode 100644 index 25615cb..0000000 --- a/default-enable +++ /dev/null @@ -1,3 +0,0 @@ -This file indicates that the default state of this module -is enabled. To disable, create a file named disable in the -same directory as this file. From b8388d0438b5bb1c56353a5a6fa087b7432cf355 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Fri, 3 Nov 2023 15:10:33 +1300 Subject: [PATCH 09/32] www => public --- {www => public}/resume.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {www => public}/resume.php (100%) diff --git a/www/resume.php b/public/resume.php similarity index 100% rename from www/resume.php rename to public/resume.php From 7122782bceeddcaaf68a993baea6765cc73fe22e Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Fri, 3 Nov 2023 15:11:05 +1300 Subject: [PATCH 10/32] lib => src --- composer.json | 2 +- {lib => src}/Auth/Source/External.php | 0 {lib => src}/Auth/Source/UserPass.php | 0 {lib => src}/ConfigHelper.php | 0 {lib => src}/DrupalHelper.php | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename {lib => src}/Auth/Source/External.php (100%) rename {lib => src}/Auth/Source/UserPass.php (100%) rename {lib => src}/ConfigHelper.php (100%) rename {lib => src}/DrupalHelper.php (100%) diff --git a/composer.json b/composer.json index 6d4d588..319b7f9 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "squizlabs/php_codesniffer": "^2.0.0|^3.0.0" }, "autoload-dev": { - "classmap": ["lib/", "tests/lib/"] + "classmap": ["src/", "tests/lib/"] }, "extra": { "branch-alias": { diff --git a/lib/Auth/Source/External.php b/src/Auth/Source/External.php similarity index 100% rename from lib/Auth/Source/External.php rename to src/Auth/Source/External.php diff --git a/lib/Auth/Source/UserPass.php b/src/Auth/Source/UserPass.php similarity index 100% rename from lib/Auth/Source/UserPass.php rename to src/Auth/Source/UserPass.php diff --git a/lib/ConfigHelper.php b/src/ConfigHelper.php similarity index 100% rename from lib/ConfigHelper.php rename to src/ConfigHelper.php diff --git a/lib/DrupalHelper.php b/src/DrupalHelper.php similarity index 100% rename from lib/DrupalHelper.php rename to src/DrupalHelper.php From 59ffb9f8bfff9fdd4a807f46ec7a8ad88474a3a2 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Fri, 3 Nov 2023 17:20:31 +1300 Subject: [PATCH 11/32] Add editor config --- .editorconfig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..5599209 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +# Editor configuration normalization +# @see http://editorconfig.org/ + +# This is the top-most .editorconfig file; do not search in parent directories. +root = true + +# All files. +[*] +end_of_line = LF +indent_style = space +indent_size = 4 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[{*.yml,*yaml}] +indent_size = 2 From 6e95f4a79c2441fc6c5592f8f1b1dbe004be4f24 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Fri, 3 Nov 2023 17:21:17 +1300 Subject: [PATCH 12/32] Check new style in new locations --- phpcs.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpcs.xml b/phpcs.xml index b0ede41..bd16e4e 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -2,7 +2,7 @@ The coding standard for drupalauth. - - ./lib - ./www + + ./src + ./public From aa4fed811679637d907a964b4bebb417a612afc7 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Fri, 3 Nov 2023 17:21:59 +1300 Subject: [PATCH 13/32] Bump supported PHP versions --- .travis.yml | 5 ++--- composer.json | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3549c0b..a8c2510 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,9 @@ language: php php: - - '7.1' - - '7.2' - - '7.3' - '7.4' - '8.0' + - '8.1' + - '8.2' before_script: composer install script: diff --git a/composer.json b/composer.json index 319b7f9..a4f7dc8 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ } ], "require": { - "php": "^5.6.0|^7.0|^8.0", + "php": "^7.4|^8.0", "simplesamlphp/simplesamlphp": "~2.0", "simplesamlphp/composer-module-installer": "~1.0" }, From 4098af10808beba17f2ec1d495e6202f7b90b5b7 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Fri, 3 Nov 2023 17:22:56 +1300 Subject: [PATCH 14/32] Add Lando config --- .gitignore | 1 + .lando.env | 10 ++++++++ .lando.yml | 58 +++++++++++++++++++++++++++++++++++++++++++ scripts/phpunit.sh | 7 ++++++ scripts/style-fix.sh | 6 +++++ scripts/style-lint.sh | 13 ++++++++++ 6 files changed, 95 insertions(+) create mode 100644 .lando.env create mode 100644 .lando.yml create mode 100755 scripts/phpunit.sh create mode 100755 scripts/style-fix.sh create mode 100755 scripts/style-lint.sh diff --git a/.gitignore b/.gitignore index e26f45e..8f84364 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ composer.phar /vendor/ composer.lock +.bash_history diff --git a/.lando.env b/.lando.env new file mode 100644 index 0000000..36dddbc --- /dev/null +++ b/.lando.env @@ -0,0 +1,10 @@ +# Lando specific - uses user home directory to store Composer cache and other stuff +# Helps to re-use Composer cache between projects. +COMPOSER_HOME=/user/.composer +# https://xdebug.org/docs/step_debug +# https://xdebug.org/docs/step_debug#client_host +# https://docs.lando.dev/config/php.html#configuration +PHP_IDE_CONFIG=serverName=drupalauth.lndo.site +# Ignore commands starting with space and duplicates. +HISTCONTROL=ignoreboth +HOME=/app diff --git a/.lando.yml b/.lando.yml new file mode 100644 index 0000000..dcc6124 --- /dev/null +++ b/.lando.yml @@ -0,0 +1,58 @@ +name: drupalauth + +services: + php74: + type: php:7.4 + via: cli + xdebug: "off" + composer_version: 2 + php80: + type: php:8.0 + via: cli + xdebug: "off" + composer_version: 2 + php81: + type: php:8.1 + via: cli + xdebug: "off" + composer_version: 2 + php82: + type: php:8.2 + via: cli + xdebug: "off" + composer_version: 2 + + + + +env_file: + - .lando.env + +tooling: + style-lint: + cmd: ./scripts/style-lint.sh + service: :service + options: + service: + default: php74 + describe: Run phpcs in different service + alias: + - s + style-fix: + cmd: ./scripts/style-fix.sh + service: :service + options: + service: + default: php74 + describe: Run phpcs in different service + alias: + - s + phpunit: + cmd: ./scripts/phpunit.sh + service: :service + options: + service: + default: php74 + describe: Run phpunit in different service + alias: + - s diff --git a/scripts/phpunit.sh b/scripts/phpunit.sh new file mode 100755 index 0000000..4d300d5 --- /dev/null +++ b/scripts/phpunit.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +php -v +rm -rf ./vendor composer.lock +composer install + +./vendor/bin/phpunit diff --git a/scripts/style-fix.sh b/scripts/style-fix.sh new file mode 100755 index 0000000..133e82c --- /dev/null +++ b/scripts/style-fix.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +rm -rf ./vendor composer.lock +composer install + +./vendor/bin/phpcbf diff --git a/scripts/style-lint.sh b/scripts/style-lint.sh new file mode 100755 index 0000000..af2acab --- /dev/null +++ b/scripts/style-lint.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +rm -rf ./vendor composer.lock +composer install + +./vendor/bin/phpcs + +#lando phpunit -s php80 +#lando style-lint -s php80 +#lando phpunit -s php81 +#lando style-lint -s php81 +#lando phpunit -s php82 +#lando style-lint -s php82 From 8ac013b226c7a2cac136528e1754301727b2301c Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Fri, 3 Nov 2023 17:26:08 +1300 Subject: [PATCH 15/32] Typehint code --- .gitignore | 1 + src/Auth/Source/External.php | 10 ++++----- src/Auth/Source/UserPass.php | 6 +++--- src/ConfigHelper.php | 37 +++++++++++++++++----------------- src/DrupalHelper.php | 9 ++++----- tests/lib/DrupalHelperTest.php | 10 ++++----- tests/lib/Field.php | 6 +++--- tests/lib/FieldList.php | 4 ++-- tests/lib/User.php | 6 +++--- 9 files changed, 44 insertions(+), 45 deletions(-) diff --git a/.gitignore b/.gitignore index 8f84364..f8d51f0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ composer.phar /vendor/ composer.lock .bash_history +/.phpunit.result.cache diff --git a/src/Auth/Source/External.php b/src/Auth/Source/External.php index b335105..11ded47 100755 --- a/src/Auth/Source/External.php +++ b/src/Auth/Source/External.php @@ -95,7 +95,7 @@ class External extends Source * * @var \SimpleSAML\Module\drupalauth\ConfigHelper */ - private $config; + private ConfigHelper $config; /** * Constructor for this authentication source. @@ -103,7 +103,7 @@ class External extends Source * @param array $info Information about this authentication source. * @param array $config Configuration. */ - public function __construct($info, $config) + public function __construct(array $info, array $config) { assert(is_array($info)); assert(is_array($config)); @@ -126,7 +126,7 @@ public function __construct($info, $config) * * @return array|NULL The user's attributes, or NULL if the user isn't authenticated. */ - private function getUser($drupaluid) + private function getUser($drupaluid): ?array { if (!empty($drupaluid)) { $drupalHelper = new DrupalHelper(); @@ -149,7 +149,7 @@ private function getUser($drupaluid) * * @param array &$state Information about the current authentication. */ - public function authenticate(&$state) + public function authenticate(array &$state): void { assert(is_array($state)); @@ -311,7 +311,7 @@ public static function resume($stateID) * * @param array &$state The logout state array. */ - public function logout(&$state) + public function logout(array &$state): void { assert(is_array($state)); diff --git a/src/Auth/Source/UserPass.php b/src/Auth/Source/UserPass.php index fbadab3..4c3e061 100644 --- a/src/Auth/Source/UserPass.php +++ b/src/Auth/Source/UserPass.php @@ -62,7 +62,7 @@ class UserPass extends UserPassBase * * @var \SimpleSAML\Module\drupalauth\ConfigHelper */ - private $config; + private ConfigHelper $config; /** * Constructor for this authentication source. @@ -70,7 +70,7 @@ class UserPass extends UserPassBase * @param array $info Information about this authentication source. * @param array $config Configuration. */ - public function __construct($info, $config) + public function __construct(array $info, array $config) { assert(is_array($info)); assert(is_array($config)); @@ -101,7 +101,7 @@ public function __construct($info, $config) * @param string $password The password the user wrote. * @return array Associative array with the users attributes. */ - protected function login($username, $password) + protected function login(string $username, string $password): array { assert(is_string($username)); assert(is_string($password)); diff --git a/src/ConfigHelper.php b/src/ConfigHelper.php index d67650f..9145bb4 100644 --- a/src/ConfigHelper.php +++ b/src/ConfigHelper.php @@ -3,7 +3,6 @@ namespace SimpleSAML\Module\drupalauth; use SimpleSAML\Configuration; -use SimpleSAML\Utils\Config; /** * Drupal authentication source configuration parser. @@ -16,13 +15,13 @@ class ConfigHelper * String with the location of this configuration. * Used for error reporting. */ - private $location; + private string $location; /** * The filesystem path to the Drupal directory */ - private $drupalroot; + private string $drupalroot; /** @@ -30,25 +29,25 @@ class ConfigHelper * * @var bool */ - private $debug; + private bool $debug; /** * The attributes we should fetch. Can be NULL in which case we will fetch all attributes. */ - private $attributes; + private ?array $attributes; /** * The Drupal logout URL */ - private $drupal_logout_url; + private string $drupal_logout_url; /** * The Drupal login URL */ - private $drupal_login_url; + private string $drupal_login_url; /** @@ -57,7 +56,7 @@ class ConfigHelper * @param array $config Configuration. * @param string $location The location of this configuration. Used for error reporting. */ - public function __construct($config, $location) { + public function __construct(array $config, string $location) { assert(is_array($config)); assert(is_string($location)); @@ -66,19 +65,19 @@ public function __construct($config, $location) { /* Get authsource configuration. */ $config = Configuration::loadFromArray($config, $location); - $this->drupalroot = $config->getString('drupalroot'); - $this->debug = $config->getBoolean('debug', FALSE); - $this->attributes = $config->getArray('attributes', []); - $this->drupal_logout_url = $config->getString('drupal_logout_url', NULL); - $this->drupal_login_url = $config->getString('drupal_login_url', NULL); + $this->drupalroot = $config->getString('drupalroot'); + $this->debug = $config->getOptionalBoolean('debug', false); + $this->attributes = $config->getOptionalArray('attributes', null); + $this->drupal_logout_url = $config->getString('drupal_logout_url'); + $this->drupal_login_url = $config->getString('drupal_login_url'); } /** * Returns debug mode. * - * @return boolean + * @return bool */ - public function getDebug() + public function getDebug(): bool { return $this->debug; } @@ -88,7 +87,7 @@ public function getDebug() * * @return string */ - public function getDrupalroot() + public function getDrupalroot(): string { return $this->drupalroot; } @@ -98,7 +97,7 @@ public function getDrupalroot() * * @return array */ - public function getAttributes() + public function getAttributes(): ?array { return $this->attributes; } @@ -109,7 +108,7 @@ public function getAttributes() * * @return string */ - public function getDrupalLogoutURL() + public function getDrupalLogoutURL(): string { return $this->drupal_logout_url; } @@ -119,7 +118,7 @@ public function getDrupalLogoutURL() * * @return string */ - public function getDrupalLoginURL() + public function getDrupalLoginURL(): string { return $this->drupal_login_url; } diff --git a/src/DrupalHelper.php b/src/DrupalHelper.php index 40f6bbe..dfc8c1c 100644 --- a/src/DrupalHelper.php +++ b/src/DrupalHelper.php @@ -8,15 +8,14 @@ class DrupalHelper { - - private $forbiddenAttributes = ['pass', 'status']; + private array $forbiddenAttributes = ['pass', 'status']; /** * Boot Drupal. * * @param string $drupalRoot Path to Drupal root. */ - public function bootDrupal($drupalRoot) + public function bootDrupal(string $drupalRoot) { $autoloader = require_once $drupalRoot . '/autoload.php'; $request = Request::createFromGlobals(); @@ -34,7 +33,7 @@ public function bootDrupal($drupalRoot) * @param $forbiddenAttributes * @return array */ - public function getAttributes($drupaluser, $requested_attributes) + public function getAttributes($drupaluser, $requested_attributes): array { $attributes = []; $forbiddenAttributes = $this->forbiddenAttributes; @@ -89,7 +88,7 @@ public function getAttributes($drupaluser, $requested_attributes) * @param $forbiddenAttributes * @return array */ - protected function getAllAttributes($drupaluser, $forbiddenAttributes) + protected function getAllAttributes($drupaluser, $forbiddenAttributes): array { $attributes = []; foreach ($drupaluser as $field_name => $field) { diff --git a/tests/lib/DrupalHelperTest.php b/tests/lib/DrupalHelperTest.php index 26c9d97..d58fc07 100644 --- a/tests/lib/DrupalHelperTest.php +++ b/tests/lib/DrupalHelperTest.php @@ -14,7 +14,7 @@ class DrupalHelperTest extends TestCase /** * @var ReflectionClass */ - protected $class; + protected ReflectionClass $class; protected function setUp(): void { @@ -24,7 +24,7 @@ protected function setUp(): void } - public function getPropertyNameProvider() + public function getPropertyNameProvider(): array { return [ [[], 'value'], @@ -46,7 +46,7 @@ public function testGetPropertyName($attribute_definition, $expected_property_na } - public function getAttributeNameProvider() + public function getAttributeNameProvider(): array { return [ [['field_name' => 'some_field'], 'some_field:value'], @@ -73,7 +73,7 @@ public function testGetAttributeName($attribute_definition, $expected_attribute_ $this->assertEquals($expected_attribute_name, $attribute_name, 'Expected attribute name returned'); } - public function getAllAttributesDataProvider() + public function getAllAttributesDataProvider(): array { return [ // Set #0. @@ -180,7 +180,7 @@ public function testGetAllAttributes($values, $forbidden_attributes, $expected_a $this->assertEquals($expected_attributes, $attributes, 'Expected attributes returned'); } - public function getAttributesDataProvider() + public function getAttributesDataProvider(): array { $field_values = [ 'field_name' => [ diff --git a/tests/lib/Field.php b/tests/lib/Field.php index 85a4697..a7afa9f 100644 --- a/tests/lib/Field.php +++ b/tests/lib/Field.php @@ -9,7 +9,7 @@ class Field { - protected $properties = []; + protected array $properties = []; public function __set($name, $value) { @@ -18,11 +18,11 @@ public function __set($name, $value) public function __get($name) { - return isset($this->properties[$name]) ? $this->properties[$name] : null; + return $this->properties[$name] ?? null; } - public function getProperties() + public function getProperties(): array { return array_keys($this->properties); } diff --git a/tests/lib/FieldList.php b/tests/lib/FieldList.php index 2cc13fa..7409bfe 100644 --- a/tests/lib/FieldList.php +++ b/tests/lib/FieldList.php @@ -8,7 +8,7 @@ class FieldList { - protected $list = []; + protected array $list = []; public function get($index) { @@ -16,7 +16,7 @@ public function get($index) throw new \InvalidArgumentException('Unable to get a value with a non-numeric delta in a list.'); } - return isset($this->list[$index]) ? $this->list[$index] : null; + return $this->list[$index] ?? null; } public function set($index, $properties) diff --git a/tests/lib/User.php b/tests/lib/User.php index 0c8e7f5..caa4ab1 100644 --- a/tests/lib/User.php +++ b/tests/lib/User.php @@ -2,7 +2,7 @@ class User implements IteratorAggregate { - protected $fields = []; + protected array $fields = []; /** * User constructor. @@ -11,7 +11,7 @@ class User implements IteratorAggregate * Each key corresponds to field name. Each value either scalar or array. Scalar would would be treated as index 0 * value of 'value' property. In case of array */ - public function __construct($values) + public function __construct(array $values) { foreach ($values as $field_name => $field_value) { $this->fields[$field_name] = new FieldList(); @@ -37,6 +37,6 @@ public function hasField($field_name) public function __get($field_name) { - return isset($this->fields[$field_name]) ? $this->fields[$field_name] : null; + return $this->fields[$field_name] ?? null; } } From 5c939075183a52652bcbec6c3d93bfaa500df9e1 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Fri, 3 Nov 2023 17:26:56 +1300 Subject: [PATCH 16/32] Fix code style --- src/Auth/Source/External.php | 55 ++++++++++++++++++------------------ src/Auth/Source/UserPass.php | 9 +++--- src/ConfigHelper.php | 13 ++++----- src/DrupalHelper.php | 1 - 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/Auth/Source/External.php b/src/Auth/Source/External.php index 11ded47..feb6d5c 100755 --- a/src/Auth/Source/External.php +++ b/src/Auth/Source/External.php @@ -74,23 +74,22 @@ */ class External extends Source { + /** + * The string used to identify Drupal user ID. + */ + public const DRUPALAUTH_EXTERNAL_USER_ID = 'drupalauth:External:UserID'; - /** - * The string used to identify Drupal user ID. - */ - const DRUPALAUTH_EXTERNAL_USER_ID = 'drupalauth:External:UserID'; - - /** - * The string used to identify authentication source. - */ - const DRUPALAUTH_AUTH_ID = 'drupalauth:AuthID'; + /** + * The string used to identify authentication source. + */ + public const DRUPALAUTH_AUTH_ID = 'drupalauth:AuthID'; - /** - * The string used to identify our states. - */ - const DRUPALAUTH_EXTERNAL = 'drupalauth:External'; + /** + * The string used to identify our states. + */ + public const DRUPALAUTH_EXTERNAL = 'drupalauth:External'; - /** + /** * Configuration object. * * @var \SimpleSAML\Module\drupalauth\ConfigHelper @@ -120,11 +119,11 @@ public function __construct(array $info, array $config) $this->config = $drupalAuthConfig; } - /** * Retrieve attributes for the user. * - * @return array|NULL The user's attributes, or NULL if the user isn't authenticated. + * @return array|NULL The user's attributes, or NULL if the user isn't + * authenticated. */ private function getUser($drupaluid): ?array { @@ -132,7 +131,7 @@ private function getUser($drupaluid): ?array $drupalHelper = new DrupalHelper(); $drupalHelper->bootDrupal($this->config->getDrupalroot()); - // Load the user object from Drupal. + // Load the user object from Drupal. $drupaluser = User::load($drupaluid); if ($drupaluser->isBlocked()) { throw new Error('NOACCESS'); @@ -142,26 +141,28 @@ private function getUser($drupaluid): ?array return $drupalHelper->getAttributes($drupaluser, $requested_attributes); } + + return null; } /** * Log in using an external authentication helper. * - * @param array &$state Information about the current authentication. + * @param array &$state Information about the current authentication. */ public function authenticate(array &$state): void { assert(is_array($state)); - /* + /* * The user is already authenticated. * * Add the users attributes to the $state-array, and return control * to the authentication process. */ - if (!empty($state[self::DRUPALAUTH_EXTERNAL_USER_ID])) { - $state['Attributes'] = $this->getUser($state[self::DRUPALAUTH_EXTERNAL_USER_ID]); - return; + if (!empty($state[self::DRUPALAUTH_EXTERNAL_USER_ID])) { + $state['Attributes'] = $this->getUser($state[self::DRUPALAUTH_EXTERNAL_USER_ID]); + return; } /* @@ -230,7 +231,7 @@ public function authenticate(array &$state): void * This function resumes the authentication process after the user has * entered his or her credentials. * - * @param array &$state The authentication state. + * @param array &$state The authentication state. */ public static function resume($stateID) { @@ -274,7 +275,7 @@ public static function resume($stateID) * First we check that the user is acutally logged in, and didn't simply skip the login page. */ if (empty($state[self::DRUPALAUTH_EXTERNAL_USER_ID])) { - throw new Exception('User ID is missing.'); + throw new Exception('User ID is missing.'); } /* @@ -306,10 +307,10 @@ public static function resume($stateID) } /** - * This function is called when the user start a logout operation, for example - * by logging out of a SP that supports single logout. + * This function is called when the user start a logout operation, for + * example by logging out of a SP that supports single logout. * - * @param array &$state The logout state array. + * @param array &$state The logout state array. */ public function logout(array &$state): void { diff --git a/src/Auth/Source/UserPass.php b/src/Auth/Source/UserPass.php index 4c3e061..e5a55cd 100644 --- a/src/Auth/Source/UserPass.php +++ b/src/Auth/Source/UserPass.php @@ -56,7 +56,6 @@ */ class UserPass extends UserPassBase { - /** * Configuration object. * @@ -91,14 +90,16 @@ public function __construct(array $info, array $config) /** * Attempt to log in using the given username and password. * - * On a successful login, this function should return the users attributes. On failure, - * it should throw an exception. If the error was caused by the user entering the wrong - * username or password, a SimpleSAML_Error_Error('WRONGUSERPASS') should be thrown. + * On a successful login, this function should return the users attributes. + * On failure, it should throw an exception. If the error was caused by the + * user entering the wrong username or password, a + * SimpleSAML_Error_Error('WRONGUSERPASS') should be thrown. * * Note that both the username and the password are UTF-8 encoded. * * @param string $username The username the user wrote. * @param string $password The password the user wrote. + * * @return array Associative array with the users attributes. */ protected function login(string $username, string $password): array diff --git a/src/ConfigHelper.php b/src/ConfigHelper.php index 9145bb4..dcaebb3 100644 --- a/src/ConfigHelper.php +++ b/src/ConfigHelper.php @@ -9,8 +9,6 @@ */ class ConfigHelper { - - /** * String with the location of this configuration. * Used for error reporting. @@ -56,14 +54,15 @@ class ConfigHelper * @param array $config Configuration. * @param string $location The location of this configuration. Used for error reporting. */ - public function __construct(array $config, string $location) { - assert(is_array($config)); - assert(is_string($location)); + public function __construct(array $config, string $location) + { + assert(is_array($config)); + assert(is_string($location)); - $this->location = $location; + $this->location = $location; /* Get authsource configuration. */ - $config = Configuration::loadFromArray($config, $location); + $config = Configuration::loadFromArray($config, $location); $this->drupalroot = $config->getString('drupalroot'); $this->debug = $config->getOptionalBoolean('debug', false); diff --git a/src/DrupalHelper.php b/src/DrupalHelper.php index dfc8c1c..8488c55 100644 --- a/src/DrupalHelper.php +++ b/src/DrupalHelper.php @@ -1,6 +1,5 @@ Date: Fri, 3 Nov 2023 17:39:10 +1300 Subject: [PATCH 17/32] Move tests to match PSR4 project structure --- composer.json | 2 +- tests/{lib => }/DrupalHelperTest.php | 0 tests/{lib => }/Field.php | 0 tests/{lib => }/FieldList.php | 0 tests/{lib => }/FieldListTest.php | 0 tests/{lib => }/FieldTest.php | 0 tests/{lib => }/PropertyDefinition.php | 0 tests/{lib => }/PropertyDefinitionTest.php | 0 tests/{lib => }/User.php | 0 tests/{lib => }/UserTest.php | 0 10 files changed, 1 insertion(+), 1 deletion(-) rename tests/{lib => }/DrupalHelperTest.php (100%) rename tests/{lib => }/Field.php (100%) rename tests/{lib => }/FieldList.php (100%) rename tests/{lib => }/FieldListTest.php (100%) rename tests/{lib => }/FieldTest.php (100%) rename tests/{lib => }/PropertyDefinition.php (100%) rename tests/{lib => }/PropertyDefinitionTest.php (100%) rename tests/{lib => }/User.php (100%) rename tests/{lib => }/UserTest.php (100%) diff --git a/composer.json b/composer.json index a4f7dc8..0d97c08 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "squizlabs/php_codesniffer": "^2.0.0|^3.0.0" }, "autoload-dev": { - "classmap": ["src/", "tests/lib/"] + "classmap": ["src/", "tests/"] }, "extra": { "branch-alias": { diff --git a/tests/lib/DrupalHelperTest.php b/tests/DrupalHelperTest.php similarity index 100% rename from tests/lib/DrupalHelperTest.php rename to tests/DrupalHelperTest.php diff --git a/tests/lib/Field.php b/tests/Field.php similarity index 100% rename from tests/lib/Field.php rename to tests/Field.php diff --git a/tests/lib/FieldList.php b/tests/FieldList.php similarity index 100% rename from tests/lib/FieldList.php rename to tests/FieldList.php diff --git a/tests/lib/FieldListTest.php b/tests/FieldListTest.php similarity index 100% rename from tests/lib/FieldListTest.php rename to tests/FieldListTest.php diff --git a/tests/lib/FieldTest.php b/tests/FieldTest.php similarity index 100% rename from tests/lib/FieldTest.php rename to tests/FieldTest.php diff --git a/tests/lib/PropertyDefinition.php b/tests/PropertyDefinition.php similarity index 100% rename from tests/lib/PropertyDefinition.php rename to tests/PropertyDefinition.php diff --git a/tests/lib/PropertyDefinitionTest.php b/tests/PropertyDefinitionTest.php similarity index 100% rename from tests/lib/PropertyDefinitionTest.php rename to tests/PropertyDefinitionTest.php diff --git a/tests/lib/User.php b/tests/User.php similarity index 100% rename from tests/lib/User.php rename to tests/User.php diff --git a/tests/lib/UserTest.php b/tests/UserTest.php similarity index 100% rename from tests/lib/UserTest.php rename to tests/UserTest.php From 00a1a571d1a4fdb499ae29ace964b6bab4a2b995 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Fri, 3 Nov 2023 17:56:13 +1300 Subject: [PATCH 18/32] HTTP helper is not static anymore --- src/Auth/Source/External.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Auth/Source/External.php b/src/Auth/Source/External.php index feb6d5c..b8642a2 100755 --- a/src/Auth/Source/External.php +++ b/src/Auth/Source/External.php @@ -215,7 +215,8 @@ public function authenticate(array &$state): void * Note the 'ReturnTo' parameter. This must most likely be replaced with * the real name of the parameter for the login page. */ - HTTP::redirectTrustedURL($authPage, [ + $HTTP = new HTTP(); + $HTTP->redirectTrustedURL($authPage, [ 'ReturnTo' => $returnTo, ]); @@ -327,6 +328,7 @@ public function logout(array &$state): void $parameters['ReturnTo'] = $state['ReturnTo']; } - HTTP::redirectTrustedURL($logout_url, $parameters); + $HTTP = new HTTP(); + $HTTP->redirectTrustedURL($logout_url, $parameters); } } From 30f058929b482bdb109f8b32cfd60c7e681bcfc0 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Fri, 3 Nov 2023 18:05:39 +1300 Subject: [PATCH 19/32] Drupal 10 is only compatible with SimpleSAMLphp >= 2.1 --- .lando.yml | 11 +++-------- .travis.yml | 1 - composer.json | 8 ++++---- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/.lando.yml b/.lando.yml index dcc6124..655c9e0 100644 --- a/.lando.yml +++ b/.lando.yml @@ -1,11 +1,6 @@ name: drupalauth services: - php74: - type: php:7.4 - via: cli - xdebug: "off" - composer_version: 2 php80: type: php:8.0 via: cli @@ -34,7 +29,7 @@ tooling: service: :service options: service: - default: php74 + default: php80 describe: Run phpcs in different service alias: - s @@ -43,7 +38,7 @@ tooling: service: :service options: service: - default: php74 + default: php80 describe: Run phpcs in different service alias: - s @@ -52,7 +47,7 @@ tooling: service: :service options: service: - default: php74 + default: php80 describe: Run phpunit in different service alias: - s diff --git a/.travis.yml b/.travis.yml index a8c2510..1802780 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: php php: - - '7.4' - '8.0' - '8.1' - '8.2' diff --git a/composer.json b/composer.json index 0d97c08..6f516a6 100644 --- a/composer.json +++ b/composer.json @@ -21,13 +21,13 @@ } ], "require": { - "php": "^7.4|^8.0", - "simplesamlphp/simplesamlphp": "~2.0", + "php": "^8.0", + "simplesamlphp/simplesamlphp": "^2.1", "simplesamlphp/composer-module-installer": "~1.0" }, "require-dev": { - "phpunit/phpunit": "^5|^6|^7|^8|^9", - "squizlabs/php_codesniffer": "^2.0.0|^3.0.0" + "phpunit/phpunit": "^9.0", + "squizlabs/php_codesniffer": "^3.0" }, "autoload-dev": { "classmap": ["src/", "tests/"] From 635c6386eba9dd811f2635587d994d562589d97d Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Mon, 6 Nov 2023 07:26:20 +1300 Subject: [PATCH 20/32] Make PHPUnit 10 compatible --- composer.json | 2 +- tests/DrupalHelperTest.php | 8 ++++---- tests/UserTest.php | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 6f516a6..95b3153 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "simplesamlphp/composer-module-installer": "~1.0" }, "require-dev": { - "phpunit/phpunit": "^9.0", + "phpunit/phpunit": "^9.0 | ^10.0", "squizlabs/php_codesniffer": "^3.0" }, "autoload-dev": { diff --git a/tests/DrupalHelperTest.php b/tests/DrupalHelperTest.php index d58fc07..3fa3c84 100644 --- a/tests/DrupalHelperTest.php +++ b/tests/DrupalHelperTest.php @@ -24,7 +24,7 @@ protected function setUp(): void } - public function getPropertyNameProvider(): array + public static function getPropertyNameProvider(): array { return [ [[], 'value'], @@ -46,7 +46,7 @@ public function testGetPropertyName($attribute_definition, $expected_property_na } - public function getAttributeNameProvider(): array + public static function getAttributeNameProvider(): array { return [ [['field_name' => 'some_field'], 'some_field:value'], @@ -73,7 +73,7 @@ public function testGetAttributeName($attribute_definition, $expected_attribute_ $this->assertEquals($expected_attribute_name, $attribute_name, 'Expected attribute name returned'); } - public function getAllAttributesDataProvider(): array + public static function getAllAttributesDataProvider(): array { return [ // Set #0. @@ -180,7 +180,7 @@ public function testGetAllAttributes($values, $forbidden_attributes, $expected_a $this->assertEquals($expected_attributes, $attributes, 'Expected attributes returned'); } - public function getAttributesDataProvider(): array + public static function getAttributesDataProvider(): array { $field_values = [ 'field_name' => [ diff --git a/tests/UserTest.php b/tests/UserTest.php index 60b4f27..dabaa48 100644 --- a/tests/UserTest.php +++ b/tests/UserTest.php @@ -11,7 +11,7 @@ class UserTest extends TestCase { - public function userDataProvider() + public static function userDataProvider() { return [ [ @@ -58,7 +58,7 @@ public function testUser($values, $count) $this->assertEquals($count, count($user->getIterator()), 'Returned expected quantity of fields'); } - public function userHasFieldDataProvider() + public static function userHasFieldDataProvider() { return [ [ From 30644cf3046579fdeb0145c3b49edc005b37c568 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Mon, 6 Nov 2023 11:54:39 +1300 Subject: [PATCH 21/32] Use latest OS --- .travis.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1802780..e89dadf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,13 @@ +os: linux language: php -php: - - '8.0' - - '8.1' - - '8.2' +jobs: + include: + - php: '8.0' + dist: focal + - php: '8.1' + dist: jammy + - php: '8.2' + dist: jammy before_script: composer install script: From e71efd18d1775a6a9d8a8e65531b6edfb6b075b2 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Mon, 6 Nov 2023 15:52:50 +1300 Subject: [PATCH 22/32] Use consistent nameing --- src/Auth/Source/External.php | 26 +++++++++++++------------- src/Auth/Source/UserPass.php | 10 +++++----- src/ConfigHelper.php | 24 ++++++++++++------------ 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Auth/Source/External.php b/src/Auth/Source/External.php index b8642a2..b231fe5 100755 --- a/src/Auth/Source/External.php +++ b/src/Auth/Source/External.php @@ -125,21 +125,21 @@ public function __construct(array $info, array $config) * @return array|NULL The user's attributes, or NULL if the user isn't * authenticated. */ - private function getUser($drupaluid): ?array + private function getUser($drupalUid): ?array { - if (!empty($drupaluid)) { + if (!empty($drupalUid)) { $drupalHelper = new DrupalHelper(); - $drupalHelper->bootDrupal($this->config->getDrupalroot()); + $drupalHelper->bootDrupal($this->config->getDrupalRoot()); // Load the user object from Drupal. - $drupaluser = User::load($drupaluid); - if ($drupaluser->isBlocked()) { + $drupalUser = User::load($drupalUid); + if ($drupalUser->isBlocked()) { throw new Error('NOACCESS'); } - $requested_attributes = $this->config->getAttributes(); + $requestedAttributes = $this->config->getAttributes(); - return $drupalHelper->getAttributes($drupaluser, $requested_attributes); + return $drupalHelper->getAttributes($drupalUser, $requestedAttributes); } return null; @@ -207,7 +207,7 @@ public function authenticate(array &$state): void * is also part of this module, but in a real example, this would likely be * the absolute URL of the login page for the site. */ - $authPage = $this->config->getDrupalLoginURL(); + $authPage = $this->config->getDrupalLoginUrl(); /* * The redirect to the authentication page. @@ -215,8 +215,8 @@ public function authenticate(array &$state): void * Note the 'ReturnTo' parameter. This must most likely be replaced with * the real name of the parameter for the login page. */ - $HTTP = new HTTP(); - $HTTP->redirectTrustedURL($authPage, [ + $http = new HTTP(); + $http->redirectTrustedURL($authPage, [ 'ReturnTo' => $returnTo, ]); @@ -322,13 +322,13 @@ public function logout(array &$state): void session_start(); } - $logout_url = $this->config->getDrupalLogoutURL(); + $logoutUrl = $this->config->getDrupalLogoutUrl(); $parameters = []; if (!empty($state['ReturnTo'])) { $parameters['ReturnTo'] = $state['ReturnTo']; } - $HTTP = new HTTP(); - $HTTP->redirectTrustedURL($logout_url, $parameters); + $http = new HTTP(); + $http->redirectTrustedURL($logoutUrl, $parameters); } } diff --git a/src/Auth/Source/UserPass.php b/src/Auth/Source/UserPass.php index e5a55cd..badbe42 100644 --- a/src/Auth/Source/UserPass.php +++ b/src/Auth/Source/UserPass.php @@ -108,7 +108,7 @@ protected function login(string $username, string $password): array assert(is_string($password)); $drupalHelper = new DrupalHelper(); - $drupalHelper->bootDrupal($this->config->getDrupalroot()); + $drupalHelper->bootDrupal($this->config->getDrupalRoot()); /* @value \Drupal\user\UserAuth $userAuth */ $userAuth = \Drupal::service('user.auth'); @@ -120,13 +120,13 @@ protected function login(string $username, string $password): array } // Load the user object from Drupal. - $drupaluser = User::load($uid); - if ($drupaluser->isBlocked()) { + $drupalUser = User::load($uid); + if ($drupalUser->isBlocked()) { throw new Error('NOACCESS'); } - $requested_attributes = $this->config->getAttributes(); + $requestedAttributes = $this->config->getAttributes(); - return $drupalHelper->getAttributes($drupaluser, $requested_attributes); + return $drupalHelper->getAttributes($drupalUser, $requestedAttributes); } } diff --git a/src/ConfigHelper.php b/src/ConfigHelper.php index dcaebb3..b9b0d5d 100644 --- a/src/ConfigHelper.php +++ b/src/ConfigHelper.php @@ -19,7 +19,7 @@ class ConfigHelper /** * The filesystem path to the Drupal directory */ - private string $drupalroot; + private string $drupalRoot; /** @@ -39,13 +39,13 @@ class ConfigHelper /** * The Drupal logout URL */ - private string $drupal_logout_url; + private string $drupalLogoutUrl; /** * The Drupal login URL */ - private string $drupal_login_url; + private string $drupalLoginUrl; /** @@ -64,11 +64,11 @@ public function __construct(array $config, string $location) /* Get authsource configuration. */ $config = Configuration::loadFromArray($config, $location); - $this->drupalroot = $config->getString('drupalroot'); + $this->drupalRoot = $config->getString('drupalroot'); $this->debug = $config->getOptionalBoolean('debug', false); $this->attributes = $config->getOptionalArray('attributes', null); - $this->drupal_logout_url = $config->getString('drupal_logout_url'); - $this->drupal_login_url = $config->getString('drupal_login_url'); + $this->drupalLogoutUrl = $config->getString('drupal_logout_url'); + $this->drupalLoginUrl = $config->getString('drupal_login_url'); } /** @@ -86,9 +86,9 @@ public function getDebug(): bool * * @return string */ - public function getDrupalroot(): string + public function getDrupalRoot(): string { - return $this->drupalroot; + return $this->drupalRoot; } /** @@ -107,9 +107,9 @@ public function getAttributes(): ?array * * @return string */ - public function getDrupalLogoutURL(): string + public function getDrupalLogoutUrl(): string { - return $this->drupal_logout_url; + return $this->drupalLogoutUrl; } /** @@ -117,8 +117,8 @@ public function getDrupalLogoutURL(): string * * @return string */ - public function getDrupalLoginURL(): string + public function getDrupalLoginUrl(): string { - return $this->drupal_login_url; + return $this->drupalLoginUrl; } } From 900fddc37242cdce8b82b7eae80806475255e6ab Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Mon, 6 Nov 2023 15:53:35 +1300 Subject: [PATCH 23/32] Avoid unnecessary function calls --- src/Auth/Source/External.php | 2 +- src/Auth/Source/UserPass.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Auth/Source/External.php b/src/Auth/Source/External.php index b231fe5..bdaf802 100755 --- a/src/Auth/Source/External.php +++ b/src/Auth/Source/External.php @@ -113,7 +113,7 @@ public function __construct(array $info, array $config) /* Get the configuration for this module */ $drupalAuthConfig = new ConfigHelper( $config, - 'Authentication source ' . var_export($this->getAuthId(), true) + 'Authentication source ' . $this->getAuthId() ); $this->config = $drupalAuthConfig; diff --git a/src/Auth/Source/UserPass.php b/src/Auth/Source/UserPass.php index badbe42..89f5573 100644 --- a/src/Auth/Source/UserPass.php +++ b/src/Auth/Source/UserPass.php @@ -3,6 +3,7 @@ namespace SimpleSAML\Module\drupalauth\Auth\Source; use Drupal\user\Entity\User; +use SimpleSAML\Assert\Assert; use SimpleSAML\Error\Error; use SimpleSAML\Module\core\Auth\UserPassBase; use SimpleSAML\Module\drupalauth\ConfigHelper; @@ -80,7 +81,7 @@ public function __construct(array $info, array $config) /* Get the configuration for this module */ $drupalAuthConfig = new ConfigHelper( $config, - 'Authentication source ' . var_export($this->getAuthId(), true) + 'Authentication source ' . $this->getAuthId() ); $this->config = $drupalAuthConfig; From c975009ea5193730ed8a2798d672cc39d80d7221 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Tue, 7 Nov 2023 08:50:15 +1300 Subject: [PATCH 24/32] Improve configuration handling --- src/ConfigHelper.php | 62 ++++++-------------------------------------- 1 file changed, 8 insertions(+), 54 deletions(-) diff --git a/src/ConfigHelper.php b/src/ConfigHelper.php index b9b0d5d..4a9457a 100644 --- a/src/ConfigHelper.php +++ b/src/ConfigHelper.php @@ -10,43 +10,9 @@ class ConfigHelper { /** - * String with the location of this configuration. - * Used for error reporting. + * @var \SimpleSAML\Configuration */ - private string $location; - - - /** - * The filesystem path to the Drupal directory - */ - private string $drupalRoot; - - - /** - * Whether debug output is enabled. - * - * @var bool - */ - private bool $debug; - - - /** - * The attributes we should fetch. Can be NULL in which case we will fetch all attributes. - */ - private ?array $attributes; - - - /** - * The Drupal logout URL - */ - private string $drupalLogoutUrl; - - - /** - * The Drupal login URL - */ - private string $drupalLoginUrl; - + private Configuration $config; /** * Constructor for this configuration parser. @@ -56,19 +22,7 @@ class ConfigHelper */ public function __construct(array $config, string $location) { - assert(is_array($config)); - assert(is_string($location)); - - $this->location = $location; - - /* Get authsource configuration. */ - $config = Configuration::loadFromArray($config, $location); - - $this->drupalRoot = $config->getString('drupalroot'); - $this->debug = $config->getOptionalBoolean('debug', false); - $this->attributes = $config->getOptionalArray('attributes', null); - $this->drupalLogoutUrl = $config->getString('drupal_logout_url'); - $this->drupalLoginUrl = $config->getString('drupal_login_url'); + $this->config = Configuration::loadFromArray($config, $location); } /** @@ -78,7 +32,7 @@ public function __construct(array $config, string $location) */ public function getDebug(): bool { - return $this->debug; + return $this->config->getOptionalBoolean('debug', false); } /** @@ -88,7 +42,7 @@ public function getDebug(): bool */ public function getDrupalRoot(): string { - return $this->drupalRoot; + return $this->config->getString('drupalroot'); } /** @@ -98,7 +52,7 @@ public function getDrupalRoot(): string */ public function getAttributes(): ?array { - return $this->attributes; + return $this->config->getOptionalArray('attributes', null); } @@ -109,7 +63,7 @@ public function getAttributes(): ?array */ public function getDrupalLogoutUrl(): string { - return $this->drupalLogoutUrl; + return $this->config->getString('drupal_logout_url'); } /** @@ -119,6 +73,6 @@ public function getDrupalLogoutUrl(): string */ public function getDrupalLoginUrl(): string { - return $this->drupalLoginUrl; + return $this->config->getString('drupal_login_url'); } } From dc92f112b9158bbdcd4fddf3c5684886f769a27c Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Wed, 8 Nov 2023 10:29:50 +1300 Subject: [PATCH 25/32] Update build status badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f4d6d69..44a9696 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Introduction -[![Build Status](https://travis-ci.com/drupalauth/simplesamlphp-module-drupalauth.svg?branch=main)](https://travis-ci.com/drupalauth/simplesamlphp-module-drupalauth) +[![Build Status](https://app.travis-ci.com/drupalauth/simplesamlphp-module-drupalauth.svg?branch=main)](https://app.travis-ci.com/drupalauth/simplesamlphp-module-drupalauth) Drupal + SimpleSAMLphp + drupalauth = Complete SAML Identity Provider (IdP) From f70ce52a9078c83485317122c5010fb12ad9a4f1 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Tue, 8 Oct 2024 15:39:43 +1300 Subject: [PATCH 26/32] Allow required plugins --- composer.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 95b3153..a6d58b6 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,10 @@ }, "config": { "allow-plugins": { - "simplesamlphp/composer-module-installer": true + "simplesamlphp/composer-module-installer": true, + "composer/installers": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "simplesamlphp/composer-xmlprovider-installer": true } } } From 92f8b6b9a68f67c60e10fa75906b49c46f23d686 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Tue, 8 Oct 2024 15:47:08 +1300 Subject: [PATCH 27/32] Test on 8.3 --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index e89dadf..3c0445b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,8 @@ jobs: dist: jammy - php: '8.2' dist: jammy + - php: '8.3' + dist: jammy before_script: composer install script: From 465045c051fbf5965f9d4592c41d1ee8ea41cedb Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Mon, 16 Jun 2025 12:03:02 +1200 Subject: [PATCH 28/32] Restore SimpleSAMLphp exception handler (#100) --- CHANGELOG | 9 --------- CHANGELOG.md | 16 ++++++++++++++++ src/DrupalHelper.php | 2 ++ 3 files changed, 18 insertions(+), 9 deletions(-) delete mode 100644 CHANGELOG create mode 100644 CHANGELOG.md diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index 577c9de..0000000 --- a/CHANGELOG +++ /dev/null @@ -1,9 +0,0 @@ -20131210 Steve Moitozo - - Resolved security issue (defect #9 - identified by alanabarrett0). - - Expanded the use of the salted hash to ensure that an attacker cannot change the uid of the authenticated Drupal user by manipulating the value of a cookie. - - Modified files: - drupal_module/drupalauth4ssp/drupalauth4ssp.module - concatenate uid with salt before hashing - lib/Auth/Source/External.php - concatenate uid with salt before hashing and minor adjustments diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..aeea622 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). + +See the main [README.md](./README.md#branch-and-version-naming) for the details about version naming. + + +## [Unreleased] + +### Fixed +- Restored SimpleSAMLphp exception handler (#29, #35) + + +## [2.10.0-rc.1] diff --git a/src/DrupalHelper.php b/src/DrupalHelper.php index 8488c55..1cfb36b 100644 --- a/src/DrupalHelper.php +++ b/src/DrupalHelper.php @@ -24,6 +24,8 @@ public function bootDrupal(string $drupalRoot) $kernel->boot(); $kernel->loadLegacyIncludes(); chdir($originalDir); + \restore_exception_handler(); + \restore_error_handler(); } /** From 6ad28dda12a6f3b978eaefd7ff8ad1ab77f8d8bd Mon Sep 17 00:00:00 2001 From: Dave Long Date: Mon, 15 Apr 2024 10:42:54 +0100 Subject: [PATCH 29/32] Fix Drupal bootstrap. --- src/DrupalHelper.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/DrupalHelper.php b/src/DrupalHelper.php index 1cfb36b..a6ccb36 100644 --- a/src/DrupalHelper.php +++ b/src/DrupalHelper.php @@ -3,7 +3,9 @@ namespace SimpleSAML\Module\drupalauth; use Drupal\Core\DrupalKernel; +use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Route; class DrupalHelper { @@ -13,6 +15,8 @@ class DrupalHelper * Boot Drupal. * * @param string $drupalRoot Path to Drupal root. + * + * @see \Drupal\Core\Test\FunctionalTestSetupTrait::initKernel() */ public function bootDrupal(string $drupalRoot) { @@ -21,8 +25,11 @@ public function bootDrupal(string $drupalRoot) $originalDir = getcwd(); chdir($drupalRoot); $kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod', true, $drupalRoot); + $kernel->invalidateContainer(); $kernel->boot(); - $kernel->loadLegacyIncludes(); + $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('')); + $request->attributes->set(RouteObjectInterface::ROUTE_NAME, ''); + $kernel->preHandle($request); chdir($originalDir); \restore_exception_handler(); \restore_error_handler(); From 3b8ded0954d040556760ba2379d6f40aa50c05b8 Mon Sep 17 00:00:00 2001 From: Dave Long Date: Mon, 15 Apr 2024 12:50:16 +0100 Subject: [PATCH 30/32] Do not invalidate container. --- src/DrupalHelper.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/DrupalHelper.php b/src/DrupalHelper.php index a6ccb36..a704637 100644 --- a/src/DrupalHelper.php +++ b/src/DrupalHelper.php @@ -25,7 +25,6 @@ public function bootDrupal(string $drupalRoot) $originalDir = getcwd(); chdir($drupalRoot); $kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod', true, $drupalRoot); - $kernel->invalidateContainer(); $kernel->boot(); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('')); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, ''); From 598c20d4ddf7ce40c875a02e79d9d4d6b66bbdcf Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Mon, 16 Jun 2025 12:45:51 +1200 Subject: [PATCH 31/32] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aeea622..f3482bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ See the main [README.md](./README.md#branch-and-version-naming) for the details ### Fixed - Restored SimpleSAMLphp exception handler (#29, #35) +- Bootstrap Drupal correctly from inside SimpleSAMLphp (#75, #98) ## [2.10.0-rc.1] From 9ced070ad50e7706f109af0e2a95d144d9c9c9a3 Mon Sep 17 00:00:00 2001 From: Kirill Roskolii Date: Mon, 16 Jun 2025 12:50:53 +1200 Subject: [PATCH 32/32] New version --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3482bd..4b4b33a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ See the main [README.md](./README.md#branch-and-version-naming) for the details ## [Unreleased] + +## [2.10.0] ### Fixed - Restored SimpleSAMLphp exception handler (#29, #35) - Bootstrap Drupal correctly from inside SimpleSAMLphp (#75, #98)