From a4a86d2cf1536b62a527d367158fd3eec29f5686 Mon Sep 17 00:00:00 2001 From: Jonathan Champ Date: Tue, 4 Apr 2023 00:28:36 -0400 Subject: [PATCH 1/5] options: fix WCAG accessibility issues --- options-admin.php | 94 +++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 49 deletions(-) diff --git a/options-admin.php b/options-admin.php index 222b281..4fd3247 100644 --- a/options-admin.php +++ b/options-admin.php @@ -19,12 +19,12 @@ function shibboleth_admin_tabs( $current = 'general' ) { 'authorization' => 'Authorization', 'logging' => 'Logging', ); - echo ''; + echo ''; } /** @@ -232,7 +232,7 @@ function shibboleth_options_page() { $constant = $constant || $from_constant; ?> -

+

Note: Some options below are defined in the wp-config.php file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>

@@ -348,7 +348,7 @@ function shibboleth_options_page() { > - + /> @@ -365,7 +365,7 @@ function shibboleth_options_page() { - + /> @@ -383,7 +383,7 @@ function shibboleth_options_page() { - + /> @@ -402,7 +402,7 @@ function shibboleth_options_page() { - + /> @@ -491,7 +491,7 @@ function AttributeAccessMethod() {

Note: Some options below are defined in the wp-config.php file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>

-

+

" /> - /> + /> @@ -528,7 +528,7 @@ function AttributeAccessMethod() { /> - /> + /> @@ -537,7 +537,7 @@ function AttributeAccessMethod() { /> - /> + /> @@ -546,7 +546,7 @@ function AttributeAccessMethod() { /> - /> + /> @@ -555,7 +555,7 @@ function AttributeAccessMethod() { /> - /> + /> @@ -564,7 +564,7 @@ function AttributeAccessMethod() { /> - /> + /> @@ -585,7 +585,7 @@ function AttributeAccessMethod() { - + - +
/> @@ -628,7 +628,7 @@ function AttributeAccessMethod() {
- - - - + +
- - - - - - - - - - - - +

+
+ + + + + + + + + + + role_names as $key => $name ) { @@ -750,21 +747,20 @@ function AttributeAccessMethod() { $value = $shib_roles[ $key ]['value']; } echo ' - - - - - '; + + + + + '; } ?> - -
' . esc_html( $name ) . '
' . esc_html( $name ) . '
-
+ - + - +
/> @@ -834,7 +830,7 @@ function AttributeAccessMethod() { list( $shib_logging, $shib_logging_constant ) = shibboleth_getoption( 'shibboleth_logging', array(), true, true ); $constant = $constant || $shib_logging_constant; ?> -

+

Note: Some options below are defined in the wp-config.php file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>

@@ -842,28 +838,28 @@ function AttributeAccessMethod() { - + - + - + - +
/>
/>
/>
/> From 225cb5a36e60361d52ef9aaaf93fc864a59048ec Mon Sep 17 00:00:00 2001 From: Jonathan Champ Date: Mon, 27 Mar 2023 13:42:58 -0400 Subject: [PATCH 2/5] wpcs: Follow WordPress standard, not just WordPress-Core --- .github/workflows/wp-plugin-ci-full.yml | 2 +- .github/workflows/wp-plugin-ci.yml | 2 +- assets/js/shibboleth_login_form.js | 10 +- options-admin.php | 601 ++++++++++++------------ options-user.php | 36 +- shibboleth.php | 71 +-- 6 files changed, 360 insertions(+), 362 deletions(-) diff --git a/.github/workflows/wp-plugin-ci-full.yml b/.github/workflows/wp-plugin-ci-full.yml index b0118e8..36290f5 100644 --- a/.github/workflows/wp-plugin-ci-full.yml +++ b/.github/workflows/wp-plugin-ci-full.yml @@ -27,4 +27,4 @@ jobs: - name: Run PHPCS on all files run: | - vendor/bin/phpcs -q -n --ignore=vendor --runtime-set installed_paths vendor/wp-coding-standards/wpcs --standard=WordPress-Core --report=checkstyle $GITHUB_WORKSPACE | cs2pr + vendor/bin/phpcs -q -n --ignore=vendor --runtime-set installed_paths vendor/wp-coding-standards/wpcs --standard=WordPress --report=checkstyle $GITHUB_WORKSPACE | cs2pr diff --git a/.github/workflows/wp-plugin-ci.yml b/.github/workflows/wp-plugin-ci.yml index 622c8ed..35ab7aa 100644 --- a/.github/workflows/wp-plugin-ci.yml +++ b/.github/workflows/wp-plugin-ci.yml @@ -32,4 +32,4 @@ jobs: run: | touch $GITHUB_WORKSPACE/tmp.php export CHANGED_FILES=$(git diff --name-only --diff-filter=AM remotes/origin/${{ github.base_ref }} | tr '\n' ' ') - vendor/bin/phpcs -q -n --ignore=vendor --runtime-set installed_paths vendor/wp-coding-standards/wpcs --standard=WordPress-Core --report=checkstyle $GITHUB_WORKSPACE/tmp.php $(echo $CHANGED_FILES) | cs2pr + vendor/bin/phpcs -q -n --ignore=vendor --runtime-set installed_paths vendor/wp-coding-standards/wpcs --standard=WordPress --report=checkstyle $GITHUB_WORKSPACE/tmp.php $(echo $CHANGED_FILES) | cs2pr diff --git a/assets/js/shibboleth_login_form.js b/assets/js/shibboleth_login_form.js index 6b7690f..370a335 100644 --- a/assets/js/shibboleth_login_form.js +++ b/assets/js/shibboleth_login_form.js @@ -1,5 +1,9 @@ -// Originally from Automattic's Jetpack SSO module (v5.3) -// @see https://github.com/Automattic/jetpack/blob/5.3/modules/sso/jetpack-sso-login.js +/** + * Originally from Automattic's Jetpack SSO module (v5.3) + * + * @see https://github.com/Automattic/jetpack/blob/5.3/modules/sso/jetpack-sso-login.js. + * @package shibboleth + */ jQuery( document ).ready( function( $ ) { @@ -15,7 +19,7 @@ jQuery( document ).ready( // UI under the submit button. // // @TODO: Remove this approach once core ticket 28528 is in and we have more actions in wp-login.php. - // See - https://core.trac.wordpress.org/ticket/28528 + // See - https://core.trac.wordpress.org/ticket/28528. loginForm.append( overflow ); overflow.append( $( 'p.forgetmenot' ), $( 'p.submit' ) ); diff --git a/options-admin.php b/options-admin.php index 4fd3247..4b28462 100644 --- a/options-admin.php +++ b/options-admin.php @@ -59,43 +59,49 @@ function shibboleth_network_admin_panels() { */ function shibboleth_options_page() { global $wp_roles; + $message = null; $type = null; + $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'general'; + + $shib_header_fields = array( + 'username' => __( 'Username' ), + 'first_name' => __( 'First Name' ), + 'last_name' => __( 'Last Name' ), + 'nickname' => __( 'Nickname' ), + 'display_name' => __( 'Display name', 'shibboleth' ), + 'email' => __( 'Email' ), + ); + if ( isset( $_POST['submit'] ) ) { check_admin_referer( 'shibboleth_update_options' ); - if ( isset( $_GET['tab'] ) ) { - $tab = $_GET['tab']; - } else { - $tab = 'general'; - } - switch ( $tab ) { case 'general': - if ( ! defined( 'SHIBBOLETH_ATTRIBUTE_ACCESS_METHOD' ) ) { - update_site_option( 'shibboleth_attribute_access_method', $_POST['attribute_access'] ); + if ( ! defined( 'SHIBBOLETH_ATTRIBUTE_ACCESS_METHOD' ) && isset( $_POST['attribute_access'] ) ) { + update_site_option( 'shibboleth_attribute_access_method', sanitize_text_field( wp_unslash( $_POST['attribute_access'] ) ) ); } if ( ! defined( 'SHIBBOLETH_ATTRIBUTE_ACCESS_METHOD_FALLBACK' ) ) { - update_site_option( 'shibboleth_attribute_access_method_fallback', $_POST['attribute_access_fallback'] ); + update_site_option( 'shibboleth_attribute_access_method_fallback', ! empty( $_POST['attribute_access_fallback'] ) ); } - if ( ! defined( 'SHIBBOLETH_ATTRIBUTE_CUSTOM_ACCESS_METHOD' ) ) { - update_site_option( 'shibboleth_attribute_custom_access_method', $_POST['attribute_custom_access'] ); + if ( ! defined( 'SHIBBOLETH_ATTRIBUTE_CUSTOM_ACCESS_METHOD' ) && isset( $_POST['attribute_custom_access'] ) ) { + update_site_option( 'shibboleth_attribute_custom_access_method', sanitize_text_field( wp_unslash( $_POST['attribute_custom_access'] ) ) ); } - if ( ! defined( 'SHIBBOLETH_LOGIN_URL' ) ) { - update_site_option( 'shibboleth_login_url', $_POST['login_url'] ); + if ( ! defined( 'SHIBBOLETH_LOGIN_URL' ) && isset( $_POST['login_url'] ) ) { + update_site_option( 'shibboleth_login_url', sanitize_url( wp_unslash( $_POST['login_url'] ) ) ); } - if ( ! defined( 'SHIBBOLETH_LOGOUT_URL' ) ) { - update_site_option( 'shibboleth_logout_url', $_POST['logout_url'] ); + if ( ! defined( 'SHIBBOLETH_LOGOUT_URL' ) && isset( $_POST['logout_url'] ) ) { + update_site_option( 'shibboleth_logout_url', sanitize_url( wp_unslash( $_POST['logout_url'] ) ) ); } - if ( ! defined( 'SHIBBOLETH_SPOOF_KEY' ) ) { - update_site_option( 'shibboleth_spoof_key', $_POST['spoofkey'] ); + if ( ! defined( 'SHIBBOLETH_SPOOF_KEY' ) && isset( $_POST['spoofkey'] ) ) { + update_site_option( 'shibboleth_spoof_key', sanitize_text_field( wp_unslash( $_POST['spoofkey'] ) ) ); } - if ( ! defined( 'SHIBBOLETH_PASSWORD_CHANGE_URL' ) ) { - update_site_option( 'shibboleth_password_change_url', $_POST['password_change_url'] ); + if ( ! defined( 'SHIBBOLETH_PASSWORD_CHANGE_URL' ) && isset( $_POST['password_change_url'] ) ) { + update_site_option( 'shibboleth_password_change_url', sanitize_url( wp_unslash( $_POST['password_change_url'] ) ) ); } - if ( ! defined( 'SHIBBOLETH_PASSWORD_RESET_URL' ) ) { - update_site_option( 'shibboleth_password_reset_url', $_POST['password_reset_url'] ); + if ( ! defined( 'SHIBBOLETH_PASSWORD_RESET_URL' ) && isset( $_POST['password_reset_url'] ) ) { + update_site_option( 'shibboleth_password_reset_url', sanitize_url( wp_unslash( $_POST['password_reset_url'] ) ) ); } if ( ! defined( 'SHIBBOLETH_DEFAULT_TO_SHIB_LOGIN' ) ) { update_site_option( 'shibboleth_default_to_shib_login', ! empty( $_POST['default_login'] ) ); @@ -103,17 +109,24 @@ function shibboleth_options_page() { if ( ! defined( 'SHIBBOLETH_AUTO_LOGIN' ) ) { update_site_option( 'shibboleth_auto_login', ! empty( $_POST['auto_login'] ) ); } - if ( ! defined( 'SHIBBOLETH_BUTTON_TEXT' ) ) { - update_site_option( 'shibboleth_button_text', $_POST['button_text'] ); + if ( ! defined( 'SHIBBOLETH_BUTTON_TEXT' ) && isset( $_POST['button_text'] ) ) { + update_site_option( 'shibboleth_button_text', sanitize_text_field( wp_unslash( $_POST['button_text'] ) ) ); } if ( ! defined( 'SHIBBOLETH_DISABLE_LOCAL_AUTH' ) ) { update_site_option( 'shibboleth_disable_local_auth', ! empty( $_POST['disable_local_auth'] ) ); } break; + case 'user': - if ( ! defined( 'SHIBBOLETH_HEADERS' ) ) { + if ( ! defined( 'SHIBBOLETH_HEADERS' ) && isset( $_POST['headers'] ) ) { $shib_headers = (array) get_site_option( 'shibboleth_headers' ); - $shib_headers = array_merge( $shib_headers, $_POST['headers'] ); + $updated_headers = array(); + foreach ( $shib_header_fields as $header_field => $header_field_label ) { + if ( isset( $_POST['headers'][ $header_field ] ) ) { + $updated_headers[ $header_field ] = array_map( 'sanitize_text_field', wp_unslash( $_POST['headers'][ $header_field ] ) ); + } + } + $shib_headers = array_merge( $shib_headers, $updated_headers ); /** * Filter shibboleth_form_submit_headers * @@ -127,17 +140,24 @@ function shibboleth_options_page() { if ( ! defined( 'SHIBBOLETH_CREATE_ACCOUNTS' ) ) { update_site_option( 'shibboleth_create_accounts', ! empty( $_POST['create_accounts'] ) ); } - if ( ! defined( 'SHIBBOLETH_AUTO_COMBINE_ACCOUNTS' ) ) { - update_site_option( 'shibboleth_auto_combine_accounts', $_POST['auto_combine_accounts'] ); + if ( ! defined( 'SHIBBOLETH_AUTO_COMBINE_ACCOUNTS' ) && isset( $_POST['auto_combine_accounts'] ) ) { + update_site_option( 'shibboleth_auto_combine_accounts', sanitize_text_field( wp_unslash( $_POST['auto_combine_accounts'] ) ) ); } - if ( ! defined( 'SHIBBOLETH_MANUALLY_COMBINE_ACCOUNTS' ) ) { - update_site_option( 'shibboleth_manually_combine_accounts', $_POST['manually_combine_accounts'] ); + if ( ! defined( 'SHIBBOLETH_MANUALLY_COMBINE_ACCOUNTS' ) && isset( $_POST['manually_combine_accounts'] ) ) { + update_site_option( 'shibboleth_manually_combine_accounts', sanitize_text_field( wp_unslash( $_POST['manually_combine_accounts'] ) ) ); } break; + case 'authorization': - if ( ! defined( 'SHIBBOLETH_ROLES' ) ) { + if ( ! defined( 'SHIBBOLETH_ROLES' ) && isset( $_POST['shibboleth_roles'] ) ) { $shib_roles = (array) get_site_option( 'shibboleth_roles' ); - $shib_roles = array_merge( $shib_roles, $_POST['shibboleth_roles'] ); + $updated_roles = array(); + foreach ( $wp_roles->role_names as $key => $name ) { + if ( isset( $_POST['shibboleth_roles'][ $key ] ) ) { + $updated_roles[ $key ] = array_map( 'sanitize_text_field', wp_unslash( $_POST['shibboleth_roles'][ $key ] ) ); + } + } + $shib_roles = array_merge( $shib_roles, $updated_roles ); /** * Filter shibboleth_form_submit_roles * @@ -148,23 +168,25 @@ function shibboleth_options_page() { $shib_roles = apply_filters( 'shibboleth_form_submit_roles', $shib_roles ); update_site_option( 'shibboleth_roles', $shib_roles ); } - if ( ! defined( 'SHIBBOLETH_DEFAULT_ROLE' ) ) { - update_site_option( 'shibboleth_default_role', $_POST['default_role'] ); + if ( ! defined( 'SHIBBOLETH_DEFAULT_ROLE' ) && isset( $_POST['default_role'] ) ) { + update_site_option( 'shibboleth_default_role', sanitize_text_field( wp_unslash( $_POST['default_role'] ) ) ); } if ( ! defined( 'SHIBBOLETH_UPDATE_ROLES' ) ) { update_site_option( 'shibboleth_update_roles', ! empty( $_POST['update_roles'] ) ); } break; + case 'logging': if ( ! defined( 'SHIBBOLETH_LOGGING' ) ) { if ( isset( $_POST['logging'] ) ) { - update_site_option( 'shibboleth_logging', $_POST['logging'] ); + update_site_option( 'shibboleth_logging', array_map( 'sanitize_text_field', wp_unslash( $_POST['logging'] ) ) ); } else { update_site_option( 'shibboleth_logging', array() ); } } break; } + $type = 'updated'; $message = __( 'Settings saved.', 'shibboleth' ); @@ -180,7 +202,6 @@ function shibboleth_options_page() { * Hint: use global $_POST within the action. */ do_action( 'shibboleth_form_submit' ); - } $shibboleth_plugin_path = apply_filters( 'shibboleth_plugin_path', plugins_url( 'shibboleth' ) ); @@ -191,53 +212,45 @@ function shibboleth_options_page() {

- +

- -
-

Note: Some options below are defined in the wp-config.php file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>

-
+ +
+

Note: Some options below are defined in the wp-config.php file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>

+
+ @@ -305,7 +318,7 @@ function shibboleth_options_page() { For most users, leaving these defaults is perfectly fine. If you are running a special server configuration that results in environment variables being sent with the prefix REDIRECT_, you should select the "Redirected Environment Variables" option. If you are running your Shibboleth Service Provider on a reverse proxy, you should select the "HTTP Headers" option and, if at all possible, add a spoofkey below. - If you are running Shibboleth with a custom prefix, you should select the "Custom Prefix" option and complete the "Custom Attribute Access Prefix" field that appears below.', + If you are running Shibboleth with a custom prefix, you should select the "Custom Prefix" option and complete the "Custom Attribute Access Prefix" field that appears below.', 'shibboleth' ) ); @@ -426,19 +439,19 @@ function shibboleth_options_page() {

wp-login.php page.', 'shibboleth' ) ); ?>

- so add a with appropriate styling. - * - * @param $shib_headers array - * @param $shib_roles array - * @since 1.4 - * @todo support new structure of table and tabs - */ - // do_action( 'shibboleth_options_table', $shib_headers, $shib_roles ); - ?> + so add a with appropriate styling. + * + * @param $shib_headers array + * @param $shib_roles array + * @since 1.4 + * @todo support new structure of table and tabs + */ + // do_action( 'shibboleth_options_table', $shib_headers, $shib_roles );. + ?>

@@ -470,117 +483,92 @@ function AttributeAccessMethod() { } - +

- -
-

Note: Some options below are defined in the wp-config.php file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>

-
+ +
+

Note: Some options below are defined in the wp-config.php file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>

+

- attribute-map.xml (for Shibboleth 2.x) or - AAP.xml (for Shibboleth 1.x).', - 'shibboleth' - ) - ); - ?> + attribute-map.xml (for Shibboleth 2.x) or + AAP.xml (for Shibboleth 1.x).', + 'shibboleth' + ) + ); + ?>

- : - Shibboleth 1.3 | - Shibboleth 2 + : + Shibboleth SP v3 | + Shibboleth SP v2

+ $header_field_label ) { + $header_field_id = 'shibboleth_' . $header_field; + $header_field_managed_id = 'shibboleth_managed_' . $header_field; + $header_field_value = isset( $shib_headers[ $header_field ]['name'] ) ? $shib_headers[ $header_field ]['name'] : ''; + $header_field_managed = ! empty( $shib_headers[ $header_field ]['managed'] ); + $header_field_managed_disabled = $shib_headers_constant; + + // Username field is always managed and disabled. + if ( 'username' === $header_field ) { + $header_field_managed = true; + $header_field_managed_disabled = true; + } + ?> - + - - - - - - - - - - - - - - - - - - - - - - - - - +
+ + - /> + /> - /> -
- /> - - /> -
- /> - - /> -
- /> - - /> -
- /> - - /> -
- /> - - /> + />

- Managed profile fields are updated each time the user logs in using the current - data provided by Shibboleth. Additionally, users will be prevented from manually updating these - fields from within WordPress. Note that Shibboleth data is always used to populate the user - profile during initial account creation.', - 'shibboleth' - ) - ); - ?> + Managed profile fields are updated each time the user logs in using the current + data provided by Shibboleth. Additionally, users will be prevented from manually updating these + fields from within WordPress. Note that Shibboleth data is always used to populate the user + profile during initial account creation.', + 'shibboleth' + ) + ); + ?>

@@ -654,67 +642,68 @@ function AttributeAccessMethod() {
- +

- -
-

Note: Some options below are defined in the wp-config.php file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>

-
- +
+

Note: Some options below are defined in the wp-config.php file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>

+
+ + /** + * Filter shibboleth_role_mapping_override + * Return true to override the default user role mapping form + * + * @param boolean - default value false + * @return boolean - true if override + * @since 1.4 + * + * Use in conjunction with shibboleth_role_mapping_form action below + */ + if ( apply_filters( 'shibboleth_role_mapping_override', false ) === false ) { + ?> -

- -

+

+ +

-

- Current Limitations: While WordPress supports users having - multiple roles, the Shibboleth plugin will only place the user in the highest ranking - role. Only a single header/value pair is supported for each user role. This may be - expanded in the future to support multiple header/value pairs or regular expression - values. In the meantime, you can use the shibboleth_roles and - shibboleth_user_role WordPress filters to provide your own logic for assigning - user roles.', - 'shibboleth' - ) - ); - ?> -

+

+ Current Limitations: While WordPress supports users having + multiple roles, the Shibboleth plugin will only place the user in the highest ranking + role. Only a single header/value pair is supported for each user role. This may be + expanded in the future to support multiple header/value pairs or regular expression + values. In the meantime, you can use the shibboleth_roles and + shibboleth_user_role WordPress filters to provide your own logic for assigning + user roles.', + 'shibboleth' + ) + ); + ?> +