From 2a04dd89c006169b19e1061bcf0a6c05644dd637 Mon Sep 17 00:00:00 2001 From: James Amner Date: Tue, 11 Feb 2025 16:45:02 +0000 Subject: [PATCH] WIP --- composer.json | 1 + composer.lock | 157 +++++++++++++++++++++++++++- wp-content/mu-plugins/boxuk-sso.php | 137 ++++++++++++++++++++++++ 3 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 wp-content/mu-plugins/boxuk-sso.php diff --git a/composer.json b/composer.json index be05296..e6cb720 100644 --- a/composer.json +++ b/composer.json @@ -43,6 +43,7 @@ "require": { "boxuk/wp-editor-tools": "^0.0.10", "boxuk/wp-feature-flags": "^0.0.10", + "humanmade/wp-simple-saml": "^0.5.1", "inpsyde/wp-translation-downloader": "^2.5", "oomphinc/composer-installers-extender": "^2", "roots/bedrock-autoloader": "^1.0", diff --git a/composer.lock b/composer.lock index 22dcd9f..de38f9c 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": "1903a3ad027ce130103886e832967537", + "content-hash": "e613c93a9bca4246b12c1a27e59760d5", "packages": [ { "name": "boxuk/wp-editor-tools", @@ -228,6 +228,54 @@ ], "time": "2024-06-24T20:46:46+00:00" }, + { + "name": "humanmade/wp-simple-saml", + "version": "0.5.1", + "source": { + "type": "git", + "url": "https://github.com/humanmade/wp-simple-saml.git", + "reference": "87d1d1e48c717aaba4196fcd688fb856d5494189" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/humanmade/wp-simple-saml/zipball/87d1d1e48c717aaba4196fcd688fb856d5494189", + "reference": "87d1d1e48c717aaba4196fcd688fb856d5494189", + "shasum": "" + }, + "require": { + "onelogin/php-saml": "^3.0" + }, + "require-dev": { + "humanmade/coding-standards": "dev-master" + }, + "type": "wordpress-plugin", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-3.0-or-later" + ], + "authors": [ + { + "name": "Shady Sharaf", + "email": "shady@humanmade.com", + "homepage": "http://sharaf.me", + "role": "Developer" + } + ], + "description": "WordPress Simple SAML plugin", + "homepage": "https://github.com/humanmade/wp-simple-saml", + "keywords": [ + "SSO", + "onelogin", + "saml", + "single-sign-on", + "wordpress" + ], + "support": { + "issues": "https://github.com/humanmade/wp-simple-saml/issues", + "source": "https://github.com/humanmade/wp-simple-saml/tree/0.5.1" + }, + "time": "2024-04-03T11:00:01+00:00" + }, { "name": "inpsyde/wp-translation-downloader", "version": "2.5", @@ -334,6 +382,69 @@ }, "time": "2022-08-23T13:07:01+00:00" }, + { + "name": "onelogin/php-saml", + "version": "3.7.0", + "source": { + "type": "git", + "url": "https://github.com/SAML-Toolkits/php-saml.git", + "reference": "91c1a3b3e2390aba9facc64ba81b407a50962ebb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SAML-Toolkits/php-saml/zipball/91c1a3b3e2390aba9facc64ba81b407a50962ebb", + "reference": "91c1a3b3e2390aba9facc64ba81b407a50962ebb", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "robrichards/xmlseclibs": ">=3.1.1" + }, + "require-dev": { + "pdepend/pdepend": "^2.5.0", + "php-coveralls/php-coveralls": "^1.0.2 || ^2.0", + "phploc/phploc": "^2.1 || ^3.0 || ^4.0", + "phpunit/phpunit": "<7.5.18", + "sebastian/phpcpd": "^2.0 || ^3.0 || ^4.0", + "squizlabs/php_codesniffer": "^3.1.1" + }, + "suggest": { + "ext-curl": "Install curl lib to be able to use the IdPMetadataParser for parsing remote XMLs", + "ext-gettext": "Install gettext and php5-gettext libs to handle translations", + "ext-openssl": "Install openssl lib in order to handle with x509 certs (require to support sign and encryption)" + }, + "type": "library", + "autoload": { + "psr-4": { + "OneLogin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP SAML Toolkit", + "homepage": "https://github.com/SAML-Toolkits/php-saml", + "keywords": [ + "Federation", + "SAML2", + "SSO", + "identity", + "saml" + ], + "support": { + "email": "sixto.martin.garcia@gmail.com", + "issues": "https://github.com/onelogin/SAML-Toolkits/issues", + "source": "https://github.com/onelogin/SAML-Toolkits/" + }, + "funding": [ + { + "url": "https://github.com/SAML-Toolkits", + "type": "github" + } + ], + "time": "2024-05-30T15:14:26+00:00" + }, { "name": "oomphinc/composer-installers-extender", "version": "2.0.1", @@ -391,6 +502,48 @@ }, "time": "2021-12-15T12:32:42+00:00" }, + { + "name": "robrichards/xmlseclibs", + "version": "3.1.3", + "source": { + "type": "git", + "url": "https://github.com/robrichards/xmlseclibs.git", + "reference": "2bdfd742624d739dfadbd415f00181b4a77aaf07" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/2bdfd742624d739dfadbd415f00181b4a77aaf07", + "reference": "2bdfd742624d739dfadbd415f00181b4a77aaf07", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">= 5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "RobRichards\\XMLSecLibs\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "A PHP library for XML Security", + "homepage": "https://github.com/robrichards/xmlseclibs", + "keywords": [ + "security", + "signature", + "xml", + "xmldsig" + ], + "support": { + "issues": "https://github.com/robrichards/xmlseclibs/issues", + "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.3" + }, + "time": "2024-11-20T21:13:56+00:00" + }, { "name": "roots/bedrock-autoloader", "version": "1.0.4", @@ -4537,5 +4690,5 @@ "ext-mbstring": "1", "ext-intl": "1" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/wp-content/mu-plugins/boxuk-sso.php b/wp-content/mu-plugins/boxuk-sso.php new file mode 100644 index 0000000..7ae2701 --- /dev/null +++ b/wp-content/mu-plugins/boxuk-sso.php @@ -0,0 +1,137 @@ + + * Author URI: https://boxuk.com + * + * @package BoxUK\User_Authentication + */ + +declare( strict_types = 1 ); + +namespace BoxUK\User_Authentication; + +use WP_Error; +use WP_User; +use function HumanMade\SimpleSaml\map_user_roles; + +add_filter( + 'wpsimplesaml_idp_metadata_xml_path', + fn () => WP_CONTENT_DIR . '/private/sso/sso.boxuk.com-idp-metadata.xml' +); + +add_filter( + 'option_sso_sp_base', + fn () => 'https://sso.boxuk.com' +); +add_filter( + 'option_sso_enabled', + fn () => 'force' +); + +add_filter( + 'option_sso_role_management', + fn () => 'forced' +); + +add_filter( 'wpcom_vip_enable_two_factor', '__return_false' ); +add_filter( 'wpcom_vip_is_two_factor_forced', '__return_false' ); +add_filter( 'wpcom_vip_two_factor_prep_hide_admin_notice', '__return_true' ); + +add_filter( 'wpsimplesaml_config', __NAMESPACE__ . '\change_saml_config', 12 ); +add_filter( 'wpsimplesaml_map_role', __NAMESPACE__ . '\map_user_group_to_wp_role', 10, 2 ); +add_filter( 'wpsimplesaml_match_user', __NAMESPACE__ . '\maybe_update_role', 10, 3 ); + +add_action( + 'admin_head', + function () { + global $wp_settings_sections; + // Hide the SSO settings section. + unset( $wp_settings_sections['general']['sso_settings'] ); + // This is the best we can do because no other filters are available for this... + // We're forcing all the settings above to our configuration so having the settings section is redundant. + } +); + + +add_filter( + 'wpsimplesaml_attribute_mapping', + fn () => [ + 'first_name' => 'user-first_name', + 'last_name' => 'user-last_name', + 'user_login' => 'user-email', + ] +); + +/** + * Hook user matching to check whether a user is found and their role has changed. + * Match by email, then remap their role from the SAML attributes + * + * @param WP_User|null $user Found user. + * @param string $email Email from SAMLResponse. + * @param array $attributes SAML Attributes parsed from SAMLResponse. + * + * @return false|WP_User User object or false if not found + */ +function maybe_update_role( $user, string $email, array $attributes ): false|\WP_User { + + if ( null === $user ) { + $user = get_user_by( 'email', $email ); + } + + if ( ! empty( $user ) ) { + map_user_roles( $user, $attributes ); + } + + return $user; +} + +/** + * Map Active Directory user group membership to WordPress roles. + * + * @param string|array $default_role Default user role. + * @param array $attributes SAML attributes. + * + * @return string|array Updated user role. + */ +function map_user_group_to_wp_role( string|array $default_role, array $attributes ): string|array { + + $role_key = 'user_role'; + + if ( empty( $attributes[ $role_key ] ) ) { + return $default_role; + } + + switch ( $attributes[ $role_key ][0] ) { + case 'BoxUK-WP_Admin': + return 'administrator'; + case 'BoxUK-WP_Editor': + return 'editor'; + case 'BoxUK-WP_Author': + return 'author'; + case 'BoxUK-WP_Contributor': + return 'contributor'; + case 'BoxUK-WP_Subscriber': + return 'subscriber'; + default: + return $default_role; + } +} + +/** + * Change SAML configuration settings. + * + * @param array|WP_Error $settings SAML configuration settings, or an error object. + * + * @return array|WP_Error SAML configuration settings, or an error object. + */ +function change_saml_config( $settings ) { + if ( is_wp_error( $settings ) ) { + return $settings; + } + + // modify any necessary settings.... + return $settings; +}