Fixes Broken Redirect URL Handling & Moves Away from Cookies (#289)

* Initial Changes to Move Away from Cookies for Redirects

* Add Redirection via State Transient Support

- Adds adding the login redirection to the state transient.
- Deprecates the use of cookies to handle login redirection.
- Fixes Login button shortcode authentication URL encoding.
- Fixes some broken wp-env local Docker environment issues.
- Fixes make_authentication_url attributes usage.
- Removes error_log calls used for debugging.

* Fixes Missed WordPress Coding Standards Issues

- Updates PHP_CodeSniffer configuration to properly support all checks.

* Fixes Login Button Output for Proper Escaping
isekai
Tim Nolte 4 years ago committed by GitHub
parent c839083cf1
commit 8a963301ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,9 +1,33 @@
{
"core": "./wordpress/build",
"plugins": [ "." ],
"plugins": [
"."
],
"mappings": {
"wp-content/mu-plugins": "./tools/local-env/mu-plugins"
},
"env": {
"development": {
"plugins": [
".",
"https://downloads.wordpress.org/plugin/debug-bar.zip",
"https://downloads.wordpress.org/plugin/query-monitor.zip",
"https://downloads.wordpress.org/plugin/debug-bar-post-meta.zip",
"https://downloads.wordpress.org/plugin/transients-manager.zip"
],
"mappings": {
"wp-config.php": "tools/local-env/wp-config.dev.php"
}
},
"tests": {
"plugins": [
"."
],
"mappings": {
"wp-config.php": "tools/local-env/wp-config.tests.php"
}
}
},
"config": {
"PHP_INI_MEMORY_LIMIT": "512M",
"WP_MEMORY_LIMIT": "512M",

@ -0,0 +1,32 @@
#logger-table .col-data {
width: 85%
}
#logger-table .col-data pre {
margin: 0;
white-space: pre; /* CSS 2.0 */
white-space: pre-wrap; /* CSS 2.1 */
white-space: pre-line; /* CSS 3.0 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
white-space: -moz-pre-wrap; /* Mozilla */
white-space: -hp-pre-wrap; /* HP Printers */
word-wrap: break-word; /* IE 5+ */
}
#logger-table .col-details {
width: 200px;
}
#logger-table .col-details div {
padding: 4px 0;
border-bottom: 1px solid #bbb;
}
#logger-table .col-details div:last-child {
border-bottom: none;
}
#logger-table .col-details label {
font-weight: bold;
}

@ -9,6 +9,8 @@
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
*/
use \WP_Error as WP_Error;
/**
* OpenID_Connect_Generic_Client_Wrapper class.
*
@ -50,6 +52,8 @@ class OpenID_Connect_Generic_Client_Wrapper {
/**
* The user redirect cookie key.
*
* @deprecated Redirection should be done via state transient and not cookies.
*
* @var string
*/
public $cookie_redirect_key = 'openid-connect-generic-redirect';
@ -70,7 +74,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
* @param OpenID_Connect_Generic_Option_Settings $settings A plugin settings object instance.
* @param OpenID_Connect_Generic_Option_Logger $logger A plugin logger object instance.
*/
function __construct( OpenID_Connect_Generic_Client $client, OpenID_Connect_Generic_Option_Settings $settings, OpenID_Connect_Generic_Option_Logger $logger ) {
public function __construct( OpenID_Connect_Generic_Client $client, OpenID_Connect_Generic_Option_Settings $settings, OpenID_Connect_Generic_Option_Logger $logger ) {
$this->client = $client;
$this->settings = $settings;
$this->logger = $logger;
@ -85,7 +89,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return \OpenID_Connect_Generic_Client_Wrapper
*/
static public function register( OpenID_Connect_Generic_Client $client, OpenID_Connect_Generic_Option_Settings $settings, OpenID_Connect_Generic_Option_Logger $logger ) {
public static function register( OpenID_Connect_Generic_Client $client, OpenID_Connect_Generic_Option_Settings $settings, OpenID_Connect_Generic_Option_Logger $logger ) {
$client_wrapper = new self( $client, $settings, $logger );
// Integrated logout.
@ -128,7 +132,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return mixed
*/
function alternate_redirect_uri_parse_request( $query ) {
public function alternate_redirect_uri_parse_request( $query ) {
if ( isset( $query->query_vars['openid-connect-authorize'] ) &&
'1' === $query->query_vars['openid-connect-authorize'] ) {
$this->authentication_request_callback();
@ -145,14 +149,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return string
*/
function get_authentication_url( $atts = array() ) {
if ( ! empty( $atts['redirect_to'] ) ) {
// Set the request query parameter used to set the cookie redirect.
$_REQUEST['redirect_to'] = $atts['redirect_to'];
$login_form = new OpenID_Connect_Generic_Login_Form( $this->settings, $this );
$login_form->handle_redirect_cookie();
}
public function get_authentication_url( $atts = array() ) {
return $this->client->make_authentication_url( $atts );
@ -163,7 +160,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return void
*/
function ensure_tokens_still_fresh() {
public function ensure_tokens_still_fresh() {
if ( ! is_user_logged_in() ) {
return;
}
@ -225,7 +222,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return void
*/
function error_redirect( $error ) {
public function error_redirect( $error ) {
$this->logger->log( $error );
// Redirect user back to login page.
@ -242,7 +239,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return bool|WP_Error
*/
function get_error() {
public function get_error() {
return $this->error;
}
@ -253,7 +250,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return array<string>|bool
*/
function update_allowed_redirect_hosts( $allowed ) {
public function update_allowed_redirect_hosts( $allowed ) {
$host = parse_url( $this->settings->endpoint_end_session, PHP_URL_HOST );
if ( ! $host ) {
return false;
@ -272,7 +269,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return string
*/
function get_end_session_logout_redirect_url( $redirect_url, $requested_redirect_to, $user ) {
public function get_end_session_logout_redirect_url( $redirect_url, $requested_redirect_to, $user ) {
$url = $this->settings->endpoint_end_session;
$query = parse_url( $url, PHP_URL_QUERY );
$url .= $query ? '&' : '?';
@ -317,7 +314,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return mixed
*/
function alter_request( $request, $operation ) {
public function alter_request( $request, $operation ) {
if ( ! empty( $this->settings->http_request_timeout ) && is_numeric( $this->settings->http_request_timeout ) ) {
$request['timeout'] = intval( $this->settings->http_request_timeout );
}
@ -335,7 +332,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return void
*/
function authentication_request_callback() {
public function authentication_request_callback() {
$client = $this->client;
// Start the authentication flow.
@ -352,6 +349,13 @@ class OpenID_Connect_Generic_Client_Wrapper {
$this->error_redirect( $code );
}
// Retrieve the authentication state from the authentication request.
$state = $client->get_authentication_state( $authentication_request );
if ( is_wp_error( $state ) ) {
$this->error_redirect( $state );
}
// Attempting to exchange an authorization code for an authentication token.
$token_result = $client->request_authentication_token( $code );
@ -452,12 +456,22 @@ class OpenID_Connect_Generic_Client_Wrapper {
// Log our success.
$this->logger->log( "Successful login for: {$user->user_login} ({$user->ID})", 'login-success' );
// Redirect back to the origin page if enabled.
$redirect_url = isset( $_COOKIE[ $this->cookie_redirect_key ] ) ? esc_url_raw( $_COOKIE[ $this->cookie_redirect_key ] ) : false;
// Default redirect to the homepage.
$redirect_url = home_url();
// Redirect user according to redirect set in state.
$state_object = get_transient( 'openid-connect-generic-state--' . $state );
// Get the redirect URL stored with the corresponding authentication request state.
if ( ! empty( $state_object ) ) {
$redirect_url = $state_object['redirect_to'];
}
// Provide backwards compatibility for customization using the deprecated cookie method.
if ( ! empty( $_COOKIE[ $this->cookie_redirect_key ] ) ) {
$redirect_url = esc_url_raw( wp_unslash( $_COOKIE[ $this->cookie_redirect_key ] ) );
}
if ( $this->settings->redirect_user_back && ! empty( $redirect_url ) ) {
do_action( 'openid-connect-generic-redirect-user-back', $redirect_url, $user );
setcookie( $this->cookie_redirect_key, $redirect_url, 1, COOKIEPATH, COOKIE_DOMAIN, is_ssl() );
wp_redirect( $redirect_url );
} else { // Otherwise, go home!
wp_redirect( home_url() );
@ -473,7 +487,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return true|WP_Error
*/
function validate_user( $user ) {
public function validate_user( $user ) {
// Ensure the found user is a real WP_User.
if ( ! is_a( $user, 'WP_User' ) || ! $user->exists() ) {
return new WP_Error( 'invalid-user', __( 'Invalid user.', 'daggerhart-openid-connect-generic' ), $user );
@ -493,7 +507,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return void
*/
function login_user( $user, $token_response, $id_token_claim, $user_claim, $subject_identity ) {
public function login_user( $user, $token_response, $id_token_claim, $user_claim, $subject_identity ) {
// Store the tokens for future reference.
update_user_meta( $user->ID, 'openid-connect-generic-last-token-response', $token_response );
update_user_meta( $user->ID, 'openid-connect-generic-last-id-token-claim', $id_token_claim );
@ -519,7 +533,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
* @param string $token The current users session token.
* @param array|WP_Error|null $token_response The authentication token response.
*/
function save_refresh_token( $manager, $token, $token_response ) {
public function save_refresh_token( $manager, $token, $token_response ) {
if ( ! $this->settings->token_refresh_enable ) {
return;
}
@ -549,7 +563,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return false|WP_User
*/
function get_user_by_identity( $subject_identity ) {
public function get_user_by_identity( $subject_identity ) {
// Look for user by their openid-connect-generic-subject-identity value.
$user_query = new WP_User_Query(
array(
@ -602,10 +616,12 @@ class OpenID_Connect_Generic_Client_Wrapper {
// @var string $transliterated_username The username converted to ASCII from UTF-8.
$transliterated_username = iconv( 'UTF-8', 'ASCII//TRANSLIT', $desired_username );
if ( empty( $transliterated_username ) ) {
// translators: $1$s is a username from the IDP.
return new WP_Error( 'username-transliteration-failed', sprintf( __( 'Username %1$s could not be transliterated.', 'daggerhart-openid-connect-generic' ), $desired_username ), $desired_username );
}
$normalized_username = strtolower( preg_replace( '/[^a-zA-Z0-9 _.\-@]/', '', $transliterated_username ) );
if ( empty( $normalized_username ) ) {
// translators: %1$s is the ASCII version of the username from the IDP.
return new WP_Error( 'username-normalization-failed', sprintf( __( 'Username %1$s could not be normalized.', 'daggerhart-openid-connect-generic' ), $transliterated_username ), $transliterated_username );
}
@ -639,6 +655,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
}
if ( empty( $desired_nickname ) ) {
// translators: %1$s is the configured User Claim nickname key.
return new WP_Error( 'no-nickname', sprintf( __( 'No nickname found in user claim using key: %1$s.', 'daggerhart-openid-connect-generic' ), $this->settings->nickname_key ), $this->settings->nickname_key );
}
@ -723,7 +740,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return \WP_Error | \WP_User
*/
function create_new_user( $subject_identity, $user_claim ) {
public function create_new_user( $subject_identity, $user_claim ) {
$user_claim = apply_filters( 'openid-connect-generic-alter-user-claim', $user_claim );
// Default username & email to the subject identity.
@ -868,7 +885,7 @@ class OpenID_Connect_Generic_Client_Wrapper {
*
* @return WP_Error|WP_User
*/
function update_existing_user( $uid, $subject_identity ) {
public function update_existing_user( $uid, $subject_identity ) {
// Add the OpenID Connect meta data.
update_user_meta( $uid, 'openid-connect-generic-subject-identity', strval( $subject_identity ) );

@ -111,7 +111,7 @@ class OpenID_Connect_Generic_Client {
* @param int $state_time_limit @see OpenID_Connect_Generic_Option_Settings::state_time_limit for description.
* @param OpenID_Connect_Generic_Option_Logger $logger The plugin logging object instance.
*/
function __construct( $client_id, $client_secret, $scope, $endpoint_login, $endpoint_userinfo, $endpoint_token, $redirect_uri, $state_time_limit, $logger ) {
public function __construct( $client_id, $client_secret, $scope, $endpoint_login, $endpoint_userinfo, $endpoint_token, $redirect_uri, $state_time_limit, $logger ) {
$this->client_id = $client_id;
$this->client_secret = $client_secret;
$this->scope = $scope;
@ -130,12 +130,24 @@ class OpenID_Connect_Generic_Client {
*
* @return string
*/
function make_authentication_url( $atts = array() ) {
public function make_authentication_url( $atts = array() ) {
$atts = shortcode_atts(
array(
'endpoint_login' => $this->endpoint_login,
'scope' => $this->scope,
'client_id' => $this->client_id,
'redirect_uri' => $this->redirect_uri,
'redirect_to' => home_url(), // Default redirect to the homepage.
),
$atts,
'openid_connect_generic_auth_url'
);
$endpoint_login = ( ! empty( $atts['endpoint_login'] ) ) ? $atts['endpoint_login'] : $this->endpoint_login;
$scope = ( ! empty( $atts['scope'] ) ) ? $atts['scope'] : $this->scope;
$client_id = ( ! empty( $atts['client_id'] ) ) ? $atts['client_id'] : $this->client_id;
$redirect_uri = ( ! empty( $atts['redirect_uri'] ) ) ? $atts['redirect_uri'] : $this->redirect_uri;
// Validate the redirect to value to prevent a redirection attack.
if ( ! empty( $atts['redirect_to'] ) ) {
$atts['redirect_to'] = wp_validate_redirect( $atts['redirect_to'], home_url() );
}
$separator = '?';
if ( stripos( $this->endpoint_login, '?' ) !== false ) {
@ -143,12 +155,12 @@ class OpenID_Connect_Generic_Client {
}
$url = sprintf(
'%1$s%2$sresponse_type=code&scope=%3$s&client_id=%4$s&state=%5$s&redirect_uri=%6$s',
$endpoint_login,
$atts['endpoint_login'],
$separator,
rawurlencode( $scope ),
rawurlencode( $client_id ),
$this->new_state(),
rawurlencode( $redirect_uri )
rawurlencode( $atts['scope'] ),
rawurlencode( $atts['client_id'] ),
$this->new_state( $atts['redirect_to'] ),
rawurlencode( $atts['redirect_uri'] )
);
$this->logger->log( apply_filters( 'openid-connect-generic-auth-url', $url ), 'make_authentication_url' );
@ -162,7 +174,7 @@ class OpenID_Connect_Generic_Client {
*
* @return array<string>|WP_Error
*/
function validate_authentication_request( $request ) {
public function validate_authentication_request( $request ) {
// Look for an existing error of some kind.
if ( isset( $request['error'] ) ) {
return new WP_Error( 'unknown-error', 'An unknown error occurred.', $request );
@ -193,7 +205,7 @@ class OpenID_Connect_Generic_Client {
*
* @return string|WP_Error
*/
function get_authentication_code( $request ) {
public function get_authentication_code( $request ) {
if ( ! isset( $request['code'] ) ) {
return new WP_Error( 'missing-authentication-code', __( 'Missing authentication code.', 'daggerhart-openid-connect-generic' ), $request );
}
@ -208,7 +220,7 @@ class OpenID_Connect_Generic_Client {
*
* @return array<mixed>|WP_Error
*/
function request_authentication_token( $code ) {
public function request_authentication_token( $code ) {
// Add Host header - required for when the openid-connect endpoint is behind a reverse-proxy.
$parsed_url = parse_url( $this->endpoint_token );
@ -247,7 +259,7 @@ class OpenID_Connect_Generic_Client {
*
* @return array|WP_Error
*/
function request_new_tokens( $refresh_token ) {
public function request_new_tokens( $refresh_token ) {
$request = array(
'body' => array(
'refresh_token' => $refresh_token,
@ -278,7 +290,7 @@ class OpenID_Connect_Generic_Client {
*
* @return array<mixed>|WP_Error|null
*/
function get_token_response( $token_result ) {
public function get_token_response( $token_result ) {
if ( ! isset( $token_result['body'] ) ) {
return new WP_Error( 'missing-token-body', __( 'Missing token body.', 'daggerhart-openid-connect-generic' ), $token_result );
}
@ -310,7 +322,7 @@ class OpenID_Connect_Generic_Client {
*
* @return array|WP_Error
*/
function request_userinfo( $access_token ) {
public function request_userinfo( $access_token ) {
// Allow modifications to the request.
$request = apply_filters( 'openid-connect-generic-alter-request', array(), 'get-userinfo' );
@ -348,12 +360,19 @@ class OpenID_Connect_Generic_Client {
/**
* Generate a new state, save it as a transient, and return the state hash.
*
* @param string $redirect_to The redirect URL to be used after IDP authentication.
*
* @return string
*/
function new_state() {
public function new_state( $redirect_to ) {
// New state w/ timestamp.
$state = md5( mt_rand() . microtime( true ) );
set_transient( 'openid-connect-generic-state--' . $state, $state, $this->state_time_limit );
$state_value = array(
$state => array(
'redirect_to' => $redirect_to,
),
);
set_transient( 'openid-connect-generic-state--' . $state, $state_value, $this->state_time_limit );
return $state;
}
@ -365,7 +384,7 @@ class OpenID_Connect_Generic_Client {
*
* @return bool
*/
function check_state( $state ) {
public function check_state( $state ) {
$state_found = true;
@ -380,7 +399,22 @@ class OpenID_Connect_Generic_Client {
do_action( 'openid-connect-generic-state-expired', $state );
}
return ! ! $valid;
return boolval( $valid );
}
/**
* Get the authorization state from the request
*
* @param array<string>|WP_Error $request The authentication request results.
*
* @return string|WP_Error
*/
public function get_authentication_state( $request ) {
if ( ! isset( $request['state'] ) ) {
return new WP_Error( 'missing-authentication-state', __( 'Missing authentication state.', 'daggerhart-openid-connect-generic' ), $request );
}
return $request['state'];
}
/**
@ -390,7 +424,7 @@ class OpenID_Connect_Generic_Client {
*
* @return bool|WP_Error
*/
function validate_token_response( $token_response ) {
public function validate_token_response( $token_response ) {
/*
* Ensure 2 specific items exist with the token response in order
* to proceed with confidence: id_token and token_type == 'Bearer'
@ -411,7 +445,7 @@ class OpenID_Connect_Generic_Client {
*
* @return array|WP_Error
*/
function get_id_token_claim( $token_response ) {
public function get_id_token_claim( $token_response ) {
// Validate there is an id_token.
if ( ! isset( $token_response['id_token'] ) ) {
return new WP_Error( 'no-identity-token', __( 'No identity token.', 'daggerhart-openid-connect-generic' ), $token_response );
@ -446,7 +480,7 @@ class OpenID_Connect_Generic_Client {
*
* @return bool|WP_Error
*/
function validate_id_token_claim( $id_token_claim ) {
public function validate_id_token_claim( $id_token_claim ) {
if ( ! is_array( $id_token_claim ) ) {
return new WP_Error( 'bad-id-token-claim', __( 'Bad ID token claim.', 'daggerhart-openid-connect-generic' ), $id_token_claim );
}
@ -466,7 +500,7 @@ class OpenID_Connect_Generic_Client {
*
* @return array|WP_Error|null
*/
function get_user_claim( $token_response ) {
public function get_user_claim( $token_response ) {
// Send a userinfo request to get user claim.
$user_claim_result = $this->request_userinfo( $token_response['access_token'] );
@ -489,7 +523,7 @@ class OpenID_Connect_Generic_Client {
*
* @return bool|WP_Error
*/
function validate_user_claim( $user_claim, $id_token_claim ) {
public function validate_user_claim( $user_claim, $id_token_claim ) {
// Validate the user claim.
if ( ! is_array( $user_claim ) ) {
return new WP_Error( 'invalid-user-claim', __( 'Invalid user claim.', 'daggerhart-openid-connect-generic' ), $user_claim );
@ -526,7 +560,7 @@ class OpenID_Connect_Generic_Client {
*
* @return mixed
*/
function get_subject_identity( $id_token_claim ) {
public function get_subject_identity( $id_token_claim ) {
return $id_token_claim['sub'];
}

@ -39,12 +39,9 @@ class OpenID_Connect_Generic_Login_Form {
* @param OpenID_Connect_Generic_Option_Settings $settings A plugin settings object instance.
* @param OpenID_Connect_Generic_Client_Wrapper $client_wrapper A plugin client wrapper object instance.
*/
function __construct( $settings, $client_wrapper ) {
public function __construct( $settings, $client_wrapper ) {
$this->settings = $settings;
$this->client_wrapper = $client_wrapper;
// Handle setting the redirect cookie on a formu page.
add_action( 'login_form_login', array( $this, 'handle_redirect_cookie' ) );
}
/**
@ -55,7 +52,7 @@ class OpenID_Connect_Generic_Login_Form {
*
* @return void
*/
static public function register( $settings, $client_wrapper ) {
public static function register( $settings, $client_wrapper ) {
$login_form = new self( $settings, $client_wrapper );
// Alter the login form as dictated by settings.
@ -72,16 +69,20 @@ class OpenID_Connect_Generic_Login_Form {
*
* @return void
*/
function handle_redirect_login_type_auto() {
public function handle_redirect_login_type_auto() {
if ( 'wp-login.php' == $GLOBALS['pagenow']
&& ( 'auto' == $this->settings->login_type || ! empty( $_GET['force_redirect'] ) )
// Don't send users to the IDP on logout or post password protected authentication.
&& ( ! isset( $_GET['action'] ) || ! in_array( $_GET['action'], array( 'logout', 'postpass' ) ) )
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WP Login Form doesn't have a nonce.
&& ! isset( $_POST['wp-submit'] ) ) {
if ( ! isset( $_GET['login-error'] ) ) {
$this->handle_redirect_cookie();
wp_redirect( $this->client_wrapper->get_authentication_url() );
$redirect_to = $this->get_redirect_to();
if ( empty( $redirect_to ) ) {
return;
}
wp_redirect( $this->client_wrapper->get_authentication_url( array( 'redirect_to' => $redirect_to ) ) );
exit;
} else {
add_action( 'login_footer', array( $this, 'remove_login_form' ), 99 );
@ -91,35 +92,45 @@ class OpenID_Connect_Generic_Login_Form {
}
/**
* Handle login related redirects.
* Get the client login redirect.
*
* @return void
* @return string
*/
function handle_redirect_cookie() {
public function get_redirect_to() {
global $wp;
if ( isset( $GLOBALS['pagenow'] ) && 'wp-login.php' == $GLOBALS['pagenow'] && isset( $_GET['action'] ) && 'logout' === $_GET['action'] ) {
return;
return '';
}
// Record the URL of this page if set to redirect back to origin page.
if ( $this->settings->redirect_user_back ) {
$redirect_expiry = current_time( 'timestamp' ) + DAY_IN_SECONDS;
// Default redirect to the homepage.
$redirect_url = home_url();
// Default redirect to the homepage.
$redirect_url = home_url( esc_url( add_query_arg( null, null ) ) );
// If using the login form, default redirect to the admin dashboard.
if ( isset( $GLOBALS['pagenow'] ) && 'wp-login.php' == $GLOBALS['pagenow'] ) {
$redirect_url = admin_url();
}
if ( isset( $GLOBALS['pagenow'] ) && 'wp-login.php' == $GLOBALS['pagenow'] ) {
// If using the login form, default redirect to the admin dashboard.
$redirect_url = admin_url();
// Honor Core WordPress & other plugin redirects.
if ( isset( $_REQUEST['redirect_to'] ) ) {
$redirect_url = esc_url_raw( wp_unslash( $_REQUEST['redirect_to'] ) );
}
if ( isset( $_REQUEST['redirect_to'] ) ) {
$redirect_url = esc_url_raw( $_REQUEST['redirect_to'] );
}
}
// Record the URL of the redirect_to if set to redirect back to origin page.
if ( $this->settings->redirect_user_back ) {
$redirect_url = home_url( add_query_arg( $wp->request ) );
}
$redirect_url = apply_filters( 'openid-connect-generic-cookie-redirect-url', $redirect_url );
// This hook is being deprecated with the move away from cookies.
$redirect_url = apply_filters_deprecated(
'openid-connect-generic-cookie-redirect-url',
array( $redirect_url ),
'3.8.2',
'openid-connect-generic-client-redirect-to'
);
setcookie( $this->client_wrapper->cookie_redirect_key, $redirect_url, $redirect_expiry, COOKIEPATH, COOKIE_DOMAIN, is_ssl() );
}
// This is the new hook to use with the transients version of redirection.
return apply_filters( 'openid-connect-generic-client-redirect-to', $redirect_url );
}
/**
@ -129,11 +140,11 @@ class OpenID_Connect_Generic_Login_Form {
*
* @return string
*/
function handle_login_page( $message ) {
public function handle_login_page( $message ) {
if ( isset( $_GET['login-error'] ) ) {
$error_message = ! empty( $_GET['message'] ) ? $_GET['message'] : 'Unknown error.';
$message .= $this->make_error_output( $_GET['login-error'], $error_message );
$error_message = ! empty( $_GET['message'] ) ? sanitize_text_field( wp_unslash( $_GET['message'] ) ) : 'Unknown error.';
$message .= $this->make_error_output( sanitize_text_field( wp_unslash( $_GET['login-error'] ) ), $error_message );
}
// Login button is appended to existing messages in case of error.
@ -150,12 +161,12 @@ class OpenID_Connect_Generic_Login_Form {
*
* @return string
*/
function make_error_output( $error_code, $error_message ) {
public function make_error_output( $error_code, $error_message ) {
ob_start();
?>
<div id="login_error">
<strong><?php printf( __( 'ERROR (%1$s)', 'daggerhart-openid-connect-generic' ), $error_code ); ?>: </strong>
<div id="login_error"><?php // translators: %1$s is the error code from the IDP. ?>
<strong><?php printf( esc_html__( 'ERROR (%1$s)', 'daggerhart-openid-connect-generic' ), esc_html( $error_code ) ); ?>: </strong>
<?php print esc_html( $error_message ); ?>
</div>
<?php
@ -170,22 +181,31 @@ class OpenID_Connect_Generic_Login_Form {
*
* @return string
*/
function make_login_button( $atts = array() ) {
$button_text = __( 'Login with OpenID Connect', 'daggerhart-openid-connect-generic' );
if ( ! empty( $atts['button_text'] ) ) {
$button_text = $atts['button_text'];
}
public function make_login_button( $atts = array() ) {
$atts = shortcode_atts(
array(
'button_text' => __( 'Login with OpenID Connect', 'daggerhart-openid-connect-generic' ),
'redirect_to' => $this->get_redirect_to(),
),
$atts,
'openid_connect_generic_login_button'
);
$text = apply_filters( 'openid-connect-generic-login-button-text', $atts['button_text'] );
$text = esc_html( $text );
$text = apply_filters( 'openid-connect-generic-login-button-text', $button_text );
$href = $this->client_wrapper->get_authentication_url( $atts );
$href = esc_url_raw( $href );
$login_button = <<<HTML
<div class="openid-connect-login-button" style="margin: 1em 0; text-align: center;">
<a class="button button-large" href="{$href}">{$text}</a>
</div>
HTML;
return $login_button;
ob_start();
?>
<div class="openid-connect-login-button" style="margin: 1em 0; text-align: center;">
<a class="button button-large" href="<?php print esc_url( $href ); ?>"><?php print $text; ?></a>
</div>
<?php
return wp_kses_post( ob_get_clean() );
}
/**
@ -193,7 +213,7 @@ class OpenID_Connect_Generic_Login_Form {
*
* @return void
*/
function remove_login_form() {
public function remove_login_form() {
?>
<script type="text/javascript">
(function() {

@ -62,7 +62,7 @@ class OpenID_Connect_Generic_Option_Logger {
* @param bool|TRUE $logging_enabled Whether logging is enabled.
* @param int $log_limit The log entry limit.
*/
function __construct( $option_name, $default_message_type = 'none', $logging_enabled = true, $log_limit = 1000 ) {
public function __construct( $option_name, $default_message_type = 'none', $logging_enabled = true, $log_limit = 1000 ) {
$this->option_name = $option_name;
$this->default_message_type = $default_message_type;
$this->logging_enabled = boolval( $logging_enabled );
@ -77,7 +77,7 @@ class OpenID_Connect_Generic_Option_Logger {
*
* @return void
*/
function log_filters( $filter_names, $priority = 10 ) {
public function log_filters( $filter_names, $priority = 10 ) {
if ( ! is_array( $filter_names ) ) {
$filter_names = array( $filter_names );
}
@ -95,7 +95,7 @@ class OpenID_Connect_Generic_Option_Logger {
*
* @return void
*/
function log_actions( $action_names, $priority ) {
public function log_actions( $action_names, $priority ) {
if ( ! is_array( $action_names ) ) {
$action_names = array( $action_names );
}
@ -112,7 +112,7 @@ class OpenID_Connect_Generic_Option_Logger {
*
* @return mixed
*/
function log_hook( $arg1 = null ) {
public function log_hook( $arg1 = null ) {
$this->log( func_get_args(), current_filter() );
return $arg1;
}
@ -178,12 +178,14 @@ class OpenID_Connect_Generic_Option_Logger {
}
}
$request_uri = ( ! empty( $_SERVER['REQUEST_URI'] ) ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : 'Unknown';
// Construct the message.
$message = array(
'type' => $type,
'time' => time(),
'user_ID' => get_current_user_id(),
'uri' => preg_replace( '/code=([^&]+)/i', 'code=', $_SERVER['REQUEST_URI'] ),
'uri' => preg_replace( '/code=([^&]+)/i', 'code=', $request_uri ),
'data' => $data,
);
@ -247,11 +249,6 @@ class OpenID_Connect_Generic_Option_Logger {
ob_start();
?>
<style type="text/css">
#logger-table .col-data { width: 85% }
#logger-table .col-details div { padding: 4px 0; border-bottom: 1px solid #bbb; }
#logger-table .col-details label { font-weight: bold; }
</style>
<table id="logger-table" class="wp-list-table widefat fixed striped posts">
<thead>
<th class="col-details">Details</th>
@ -262,20 +259,20 @@ class OpenID_Connect_Generic_Option_Logger {
<tr>
<td class="col-details">
<div>
<label><?php _e( 'Type', 'daggerhart-openid-connect-generic' ); ?>: </label>
<?php print $log['type']; ?>
<label><?php esc_html_e( 'Type', 'daggerhart-openid-connect-generic' ); ?>: </label>
<?php print esc_html( $log['type'] ); ?>
</div>
<div>
<label><?php _e( 'Date', 'daggerhart-openid-connect-generic' ); ?>: </label>
<?php print gmdate( 'Y-m-d H:i:s', $log['time'] ); ?>
<label><?php esc_html_e( 'Date', 'daggerhart-openid-connect-generic' ); ?>: </label>
<?php print esc_html( gmdate( 'Y-m-d H:i:s', $log['time'] ) ); ?>
</div>
<div>
<label><?php _e( 'User', 'daggerhart-openid-connect-generic' ); ?>: </label>
<?php print ( get_userdata( $log['user_ID'] ) ) ? get_userdata( $log['user_ID'] )->user_login : '0'; ?>
<label><?php esc_html_e( 'User', 'daggerhart-openid-connect-generic' ); ?>: </label>
<?php print esc_html( ( get_userdata( $log['user_ID'] ) ) ? get_userdata( $log['user_ID'] )->user_login : '0' ); ?>
</div>
<div>
<label><?php _e( 'URI ', 'daggerhart-openid-connect-generic' ); ?>: </label>
<?php print $log['uri']; ?>
<label><?php esc_html_e( 'URI ', 'daggerhart-openid-connect-generic' ); ?>: </label>
<?php print esc_url( $log['uri'] ); ?>
</div>
</td>

@ -101,7 +101,7 @@ class OpenID_Connect_Generic_Option_Settings {
* @param array<mixed> $default_settings The default plugin settings values.
* @param bool $granular_defaults The granular defaults.
*/
function __construct( $option_name, $default_settings = array(), $granular_defaults = true ) {
public function __construct( $option_name, $default_settings = array(), $granular_defaults = true ) {
$this->option_name = $option_name;
$this->default_settings = $default_settings;
$this->values = array();
@ -129,7 +129,7 @@ class OpenID_Connect_Generic_Option_Settings {
*
* @return mixed
*/
function __get( $key ) {
public function __get( $key ) {
if ( isset( $this->values[ $key ] ) ) {
return $this->values[ $key ];
}
@ -143,7 +143,7 @@ class OpenID_Connect_Generic_Option_Settings {
*
* @return void
*/
function __set( $key, $value ) {
public function __set( $key, $value ) {
$this->values[ $key ] = $value;
}
@ -154,7 +154,7 @@ class OpenID_Connect_Generic_Option_Settings {
*
* @return bool
*/
function __isset( $key ) {
public function __isset( $key ) {
return isset( $this->values[ $key ] );
}
@ -165,7 +165,7 @@ class OpenID_Connect_Generic_Option_Settings {
*
* @return void
*/
function __unset( $key ) {
public function __unset( $key ) {
unset( $this->values[ $key ] );
}
@ -174,7 +174,7 @@ class OpenID_Connect_Generic_Option_Settings {
*
* @return array
*/
function get_values() {
public function get_values() {
return $this->values;
}
@ -183,7 +183,7 @@ class OpenID_Connect_Generic_Option_Settings {
*
* @return string
*/
function get_option_name() {
public function get_option_name() {
return $this->option_name;
}
@ -192,7 +192,7 @@ class OpenID_Connect_Generic_Option_Settings {
*
* @return void
*/
function save() {
public function save() {
// For each defined environment variable/constant be sure it isn't saved to the database.
foreach ( $this->environment_settings as $key => $constant ) {

@ -61,7 +61,7 @@ class OpenID_Connect_Generic_Settings_Page {
* @param OpenID_Connect_Generic_Option_Settings $settings The plugin settings object.
* @param OpenID_Connect_Generic_Option_Logger $logger The plugin logging class object.
*/
function __construct( OpenID_Connect_Generic_Option_Settings $settings, OpenID_Connect_Generic_Option_Logger $logger ) {
public function __construct( OpenID_Connect_Generic_Option_Settings $settings, OpenID_Connect_Generic_Option_Logger $logger ) {
$this->settings = $settings;
$this->logger = $logger;
@ -87,7 +87,7 @@ class OpenID_Connect_Generic_Settings_Page {
*
* @return void
*/
static public function register( OpenID_Connect_Generic_Option_Settings $settings, OpenID_Connect_Generic_Option_Logger $logger ) {
public static function register( OpenID_Connect_Generic_Option_Settings $settings, OpenID_Connect_Generic_Option_Logger $logger ) {
$settings_page = new self( $settings, $logger );
// Add our options page the the admin menu.
@ -281,6 +281,7 @@ class OpenID_Connect_Generic_Settings_Page {
),
'no_sslverify' => array(
'title' => __( 'Disable SSL Verify', 'daggerhart-openid-connect-generic' ),
// translators: %1$s HTML tags for layout/styles, %2$s closing HTML tag for styles.
'description' => sprintf( __( 'Do not require SSL verification during authorization. The OAuth extension uses curl to make the request. By default CURL will generally verify the SSL certificate to see if its valid an issued by an accepted CA. This setting disabled that verification.%1$sNot recommended for production sites.%2$s', 'daggerhart-openid-connect-generic' ), '<br><strong>', '</strong>' ),
'type' => 'checkbox',
'section' => 'client_settings',
@ -435,25 +436,25 @@ class OpenID_Connect_Generic_Settings_Page {
?>
</form>
<h4><?php _e( 'Notes', 'daggerhart-openid-connect-generic' ); ?></h4>
<h4><?php esc_html_e( 'Notes', 'daggerhart-openid-connect-generic' ); ?></h4>
<p class="description">
<strong><?php _e( 'Redirect URI', 'daggerhart-openid-connect-generic' ); ?></strong>
<code><?php print $redirect_uri; ?></code>
<strong><?php esc_html_e( 'Redirect URI', 'daggerhart-openid-connect-generic' ); ?></strong>
<code><?php print esc_url( $redirect_uri ); ?></code>
</p>
<p class="description">
<strong><?php _e( 'Login Button Shortcode', 'daggerhart-openid-connect-generic' ); ?></strong>
<strong><?php esc_html_e( 'Login Button Shortcode', 'daggerhart-openid-connect-generic' ); ?></strong>
<code>[openid_connect_generic_login_button]</code>
</p>
<p class="description">
<strong><?php _e( 'Authentication URL Shortcode', 'daggerhart-openid-connect-generic' ); ?></strong>
<strong><?php esc_html_e( 'Authentication URL Shortcode', 'daggerhart-openid-connect-generic' ); ?></strong>
<code>[openid_connect_generic_auth_url]</code>
</p>
<?php if ( $this->settings->enable_logging ) { ?>
<h2><?php _e( 'Logs', 'daggerhart-openid-connect-generic' ); ?></h2>
<h2><?php esc_html_e( 'Logs', 'daggerhart-openid-connect-generic' ); ?></h2>
<div id="logger-table-wrapper">
<?php print $this->logger->get_logs_table(); ?>
<?php print wp_kses_post( $this->logger->get_logs_table() ); ?>
</div>
<?php } ?>
@ -507,7 +508,7 @@ class OpenID_Connect_Generic_Settings_Page {
*
* @return void
*/
function do_select( $field ) {
public function do_select( $field ) {
$current_value = isset( $this->settings->{ $field['key'] } ) ? $this->settings->{ $field['key'] } : '';
?>
<select name="<?php print esc_attr( $field['name'] ); ?>">
@ -529,10 +530,10 @@ class OpenID_Connect_Generic_Settings_Page {
public function do_field_description( $field ) {
?>
<p class="description">
<?php print $field['description']; ?>
<?php print esc_html( $field['description'] ); ?>
<?php if ( isset( $field['example'] ) ) : ?>
<br/><strong><?php _e( 'Example', 'daggerhart-openid-connect-generic' ); ?>: </strong>
<code><?php print $field['example']; ?></code>
<br/><strong><?php esc_html_e( 'Example', 'daggerhart-openid-connect-generic' ); ?>: </strong>
<code><?php print esc_html( $field['example'] ); ?></code>
<?php endif; ?>
</p>
<?php
@ -544,7 +545,7 @@ class OpenID_Connect_Generic_Settings_Page {
* @return void
*/
public function client_settings_description() {
_e( 'Enter your OpenID Connect identity provider settings.', 'daggerhart-openid-connect-generic' );
esc_html_e( 'Enter your OpenID Connect identity provider settings.', 'daggerhart-openid-connect-generic' );
}
/**
@ -553,7 +554,7 @@ class OpenID_Connect_Generic_Settings_Page {
* @return void
*/
public function user_settings_description() {
_e( 'Modify the interaction between OpenID Connect and WordPress users.', 'daggerhart-openid-connect-generic' );
esc_html_e( 'Modify the interaction between OpenID Connect and WordPress users.', 'daggerhart-openid-connect-generic' );
}
/**
@ -562,7 +563,7 @@ class OpenID_Connect_Generic_Settings_Page {
* @return void
*/
public function authorization_settings_description() {
_e( 'Control the authorization mechanics of the site.', 'daggerhart-openid-connect-generic' );
esc_html_e( 'Control the authorization mechanics of the site.', 'daggerhart-openid-connect-generic' );
}
/**
@ -571,6 +572,6 @@ class OpenID_Connect_Generic_Settings_Page {
* @return void
*/
public function log_settings_description() {
_e( 'Log information about login attempts through OpenID Connect Generic.', 'daggerhart-openid-connect-generic' );
esc_html_e( 'Log information about login attempts through OpenID Connect Generic.', 'daggerhart-openid-connect-generic' );
}
}

@ -118,7 +118,7 @@ class OpenID_Connect_Generic {
*
* @return void
*/
function __construct( OpenID_Connect_Generic_Option_Settings $settings, OpenID_Connect_Generic_Option_Logger $logger ) {
public function __construct( OpenID_Connect_Generic_Option_Settings $settings, OpenID_Connect_Generic_Option_Logger $logger ) {
$this->settings = $settings;
$this->logger = $logger;
}
@ -128,7 +128,9 @@ class OpenID_Connect_Generic {
*
* @return void
*/
function init() {
public function init() {
wp_enqueue_style( 'daggerhart-openid-connect-generic-admin', plugin_dir_url( __FILE__ ) . 'css/styles-admin.css', array(), self::VERSION, 'all' );
$redirect_uri = admin_url( 'admin-ajax.php?action=openid-connect-authorize' );
@ -179,7 +181,7 @@ class OpenID_Connect_Generic {
*
* @return void
*/
function enforce_privacy_redirect() {
public function enforce_privacy_redirect() {
if ( $this->settings->enforce_privacy && ! is_user_logged_in() ) {
// The client endpoint relies on the wp admind ajax endpoint.
if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX || ! isset( $_GET['action'] ) || 'openid-connect-authorize' != $_GET['action'] ) {
@ -195,7 +197,7 @@ class OpenID_Connect_Generic {
*
* @return mixed
*/
function enforce_privacy_feeds( $content ) {
public function enforce_privacy_feeds( $content ) {
if ( $this->settings->enforce_privacy && ! is_user_logged_in() ) {
$content = __( 'Private site', 'daggerhart-openid-connect-generic' );
}
@ -207,7 +209,7 @@ class OpenID_Connect_Generic {
*
* @return void
*/
function upgrade() {
public function upgrade() {
$last_version = get_option( 'openid-connect-generic-plugin-version', 0 );
$settings = $this->settings;
@ -236,7 +238,7 @@ class OpenID_Connect_Generic {
*
* @return void
*/
function cron_states_garbage_collection() {
public function cron_states_garbage_collection() {
global $wpdb;
$states = $wpdb->get_col( "SELECT `option_name` FROM {$wpdb->options} WHERE `option_name` LIKE '_transient_openid-connect-generic-state--%'" );
@ -253,7 +255,7 @@ class OpenID_Connect_Generic {
*
* @return void
*/
static public function setup_cron_jobs() {
public static function setup_cron_jobs() {
if ( ! wp_next_scheduled( 'openid-connect-generic-cron-daily' ) ) {
wp_schedule_event( time(), 'daily', 'openid-connect-generic-cron-daily' );
}
@ -264,7 +266,7 @@ class OpenID_Connect_Generic {
*
* @return void
*/
static public function activation() {
public static function activation() {
self::setup_cron_jobs();
}
@ -273,7 +275,7 @@ class OpenID_Connect_Generic {
*
* @return void
*/
static public function deactivation() {
public static function deactivation() {
wp_clear_scheduled_hook( 'openid-connect-generic-cron-daily' );
}
@ -284,7 +286,7 @@ class OpenID_Connect_Generic {
*
* @return void
*/
static public function autoload( $class ) {
public static function autoload( $class ) {
$prefix = 'OpenID_Connect_Generic_';
if ( stripos( $class, $prefix ) !== 0 ) {
@ -312,7 +314,7 @@ class OpenID_Connect_Generic {
*
* @return void
*/
static public function bootstrap() {
public static function bootstrap() {
/**
* This is a documented valid call for spl_autoload_register.
*

5517
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -27,13 +27,13 @@
"devDependencies": {
"@floatwork/grunt-po2mo": "^0.3.0",
"@ndigitals/grunt-checkrepo": "^0.2.0",
"@wordpress/env": "^1.6.0",
"@wordpress/scripts": "12.2.1",
"@wordpress/env": "~2.0.0",
"@wordpress/scripts": "12.6.1",
"check-node-version": "~4.1.0",
"grunt": "1.3.0",
"grunt-checkbranch": "^1.0.4",
"grunt-checktextdomain": "^1.0.1",
"grunt-cli": "^1.3.2",
"grunt-cli": "1.4.1",
"grunt-contrib-clean": "^2.0.0",
"grunt-contrib-copy": "^1.0.0",
"grunt-gitinfo": "^0.1.9",
@ -43,7 +43,7 @@
"grunt-wp-readme-to-markdown": "^2.0.0",
"load-grunt-tasks": "^3.5",
"node": "^12.21.0",
"npm": "^6.14.11",
"npm": "6.14.12",
"puppeteer": "^1.20.0",
"typescript": "~3.9.9"
},
@ -70,6 +70,7 @@
"check:licenses": "wp-scripts check-licenses",
"wp-env": "wp-env",
"wp": "wp-env run cli wp",
"wp:tests": "wp-env run tests-cli wp",
"test": "npm run grunt test",
"i18n:check": "npm run grunt checktextdomain",
"i18n:make": "npm run grunt i18n",

@ -1,32 +1,118 @@
<?xml version="1.0"?>
<ruleset name="WordPress Coding Standards for Plugins">
<!-- See https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml -->
<!-- See https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards -->
<!-- See https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/wiki -->
<!-- Set a description for this ruleset. -->
<description>Generally-applicable sniffs for WordPress plugins</description>
<rule ref="WordPress-Core">
<exclude name="WordPress.Files.FileName.NotHyphenatedLowercase" />
<exclude name="WordPress.Files.FileName.InvalidClassFileName" />
</rule>
<rule ref="WordPress-Docs" />
<!--
#############################################################################
COMMAND LINE ARGUMENTS
https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml
#############################################################################
-->
<!-- Pass some flags to PHPCS:
p flag: Show progress of the run.
s flag: Show sniff codes in all reports.
v flag: Print verbose output.
n flag: Do not print warnings.
-->
<!-- Check up to 8 files simultanously. -->
<arg name="parallel" value="8"/>
<!-- Check all PHP files in directory tree by default. -->
<arg name="basepath" value="." />
<!-- Check all PHP files in directory tree by default. -->
<arg name="extensions" value="php" />
<arg name="report" value="summary" />
<!-- Show colors. -->
<arg name="colors" />
<!-- Show progress. -->
<arg value="p" />
<!-- Show sniff codes in all reports -->
<arg value="s"/>
<arg value="n" />
<!-- Check all files in this directory and the directories below it. -->
<file>.</file>
<!-- Show sniff codes in all reports -->
<arg value="s"/>
<exclude-pattern>*/dist/*</exclude-pattern>
<exclude-pattern>*/node_modules/*</exclude-pattern>
<exclude-pattern>*/tests/*</exclude-pattern>
<exclude-pattern>*/tools/*</exclude-pattern>
<exclude-pattern>*/vendor/*</exclude-pattern>
<exclude-pattern>*/wordpress/*</exclude-pattern>
<!--
#############################################################################
USE THE WordPress-Coding-Standards RULESET
#############################################################################
-->
<rule ref="WordPress"/>
<rule ref="WordPress-Core" />
<rule ref="WordPress-Docs" />
<rule ref="WordPress-Extra" />
<!--
#############################################################################
SNIFF SPECIFIC CONFIGURATION
#############################################################################
-->
<!-- Set the minimum supported WP version. This is used by several sniffs.
The minimum version set here should be in line with the minimum WP version
as set in the "Requires at least" tag in the readme.txt file. -->
<config name="minimum_supported_wp_version" value="5.0"/>
<!-- Verify that the text_domain is set to the desired text-domain.
Multiple valid text domains can be provided as a comma-delimited list. -->
<rule ref="WordPress.WP.I18n">
<properties>
<property name="text_domain" type="array" value="daggerhart-openid-connect-generic"/>
</properties>
</rule>
<!-- Allow for plugin specific exceptions to the file name rules based
on the plugin hierarchy and ensure PSR-4 autoloading compatibility. -->
<rule ref="WordPress.Files.FileName">
<properties>
<property name="strict_class_file_names" value="false" />
<property name="is_plugin" value="true"/>
</properties>
<exclude name="WordPress.Files.FileName.NotHyphenatedLowercase" />
<exclude name="WordPress.Files.FileName.InvalidClassFileName" />
</rule>
<rule ref="WordPress.Arrays.MultipleStatementAlignment">
<properties>
<!-- No need to adjust alignment of large arrays when the item with the largest key is removed. -->
<property name="exact" value="false"/>
<!-- Don't align multi-line items if ALL items in the array are multi-line. -->
<property name="alignMultilineItems" value="!=100"/>
<!-- Array assignment operator should always be on the same line as the array key. -->
<property name="ignoreNewlines" value="false"/>
</properties>
</rule>
<!-- Exclude test from Commenting Rules. -->
<rule ref="Squiz.Commenting">
<exclude-pattern>tests/</exclude-pattern>
<exclude name="Squiz.Commenting.LongConditionClosingComment" />
<exclude name="Squiz.Commenting.PostStatementComment" />
<exclude name="Squiz.Commenting.FunctionComment.MissingParamComment" />
<exclude-pattern>tests/*</exclude-pattern>
</rule>
<!--
#############################################################################
USE THE PHPCompatibility RULESET
#############################################################################
-->
<config name="testVersion" value="7.3-"/>
<rule ref="PHPCompatibilityWP" />
</ruleset>

@ -49,3 +49,5 @@ parameters:
# WP-CLI accepts a class as callable
# - '/^Parameter #2 \$callable of static method WP_CLI::add_command\(\) expects callable\(\): mixed, \S+ given\.$/'
# Please consider commenting ignores: issue URL or reason for ignoring
# Ignore cookie_redirect_key deprecation errors.
- '/.*Access to deprecated property \$cookie_redirect_key.*/'

@ -0,0 +1,133 @@
<?php
/**
* The base configuration for WordPress
*
* The wp-config.php creation script uses this file during the
* installation. You don't have to use the web site, you can
* copy this file to "wp-config.php" and fill in the values.
*
* This file contains the following configurations:
*
* * MySQL settings
* * Secret keys
* * Database table prefix
* * ABSPATH
*
* This has been slightly modified (to read environment variables) for use in Docker.
*
* @link https://wordpress.org/support/article/editing-wp-config-php/
*
* @package WordPress
*/
// IMPORTANT: this file needs to stay in-sync with https://github.com/WordPress/WordPress/blob/master/wp-config-sample.php
// (it gets parsed by the upstream wizard in https://github.com/WordPress/WordPress/blob/f27cb65e1ef25d11b535695a660e7282b98eb742/wp-admin/setup-config.php#L356-L392)
// a helper function to lookup "env_FILE", "env", then fallback
function getenv_docker($env, $default) {
if ($fileEnv = getenv($env . '_FILE')) {
return rtrim(file_get_contents($fileEnv), "\r\n");
}
else if (($val = getenv($env)) !== false) {
return $val;
}
else {
return $default;
}
}
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'wordpress') );
/** MySQL database username */
define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'root') );
/** MySQL database password */
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', '') );
/**
* Docker image fallback values above are sourced from the official WordPress installation wizard:
* https://github.com/WordPress/WordPress/blob/f9cc35ebad82753e9c86de322ea5c76a9001c7e2/wp-admin/setup-config.php#L216-L230
* (However, using "example username" and "example password" in your database is strongly discouraged. Please use strong, random credentials!)
*/
/** MySQL hostname */
define( 'DB_HOST', getenv_docker('WORDPRESS_DB_HOST', 'mysql') );
/** Database Charset to use in creating database tables. */
define( 'DB_CHARSET', getenv_docker('WORDPRESS_DB_CHARSET', 'utf8') );
/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', getenv_docker('WORDPRESS_DB_COLLATE', '') );
/**#@+
* Authentication Unique Keys and Salts.
*
* Change these to different unique phrases!
* You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}
* You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again.
*
* @since 2.6.0
*/
define( 'AUTH_KEY', getenv_docker('WORDPRESS_AUTH_KEY', '96f6bcee44eacbd3e9a5c3c78f52d615bbe550f1') );
define( 'SECURE_AUTH_KEY', getenv_docker('WORDPRESS_SECURE_AUTH_KEY', 'cd0555ee6a32c91e064a499ebb3fd5ceea62e2a3') );
define( 'LOGGED_IN_KEY', getenv_docker('WORDPRESS_LOGGED_IN_KEY', '34b7c03618d67a8d626cd5c78508adfe542e6349') );
define( 'NONCE_KEY', getenv_docker('WORDPRESS_NONCE_KEY', '848d7098eb38eca67857d6e0ee5b3fba5962c7c1') );
define( 'AUTH_SALT', getenv_docker('WORDPRESS_AUTH_SALT', '881a5f5689e7c265b8dd8c6ae4fdff54888e06fa') );
define( 'SECURE_AUTH_SALT', getenv_docker('WORDPRESS_SECURE_AUTH_SALT', '2275b260e683602a91c8d19f6a05a6362bd5a91f') );
define( 'LOGGED_IN_SALT', getenv_docker('WORDPRESS_LOGGED_IN_SALT', '7cf0086a484ed4eabd1ce1b09a6a59a11297c61f') );
define( 'NONCE_SALT', getenv_docker('WORDPRESS_NONCE_SALT', '2fc8e8507b204f6e69e2c750a5ceaed9f5951736') );
// (See also https://wordpress.stackexchange.com/a/152905/199287)
/**#@-*/
/**
* WordPress Database Table prefix.
*
* You can have multiple installations in one database if you give each
* a unique prefix. Only numbers, letters, and underscores please!
*/
$table_prefix = getenv_docker('WORDPRESS_TABLE_PREFIX', 'wp_');
/**
* For developers: WordPress debugging mode.
*
* Change this to true to enable the display of notices during development.
* It is strongly recommended that plugin and theme developers use WP_DEBUG
* in their development environments.
*
* For information on other constants that can be used for debugging,
* visit the documentation.
*
* @link https://wordpress.org/support/article/debugging-in-wordpress/
*/
define( 'WP_DEBUG', true );
// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact
// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
// (we include this by default because reverse proxying is extremely common in container environments)
if ($configExtra = getenv_docker('WORDPRESS_CONFIG_EXTRA', '')) {
eval($configExtra);
}
define( 'PHP_INI_MEMORY_LIMIT', '512M' );
define( 'WP_MEMORY_LIMIT', '512M' );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', true );
define( 'SCRIPT_DEBUG', true );
define( 'SMTP_HOST', 'mailhog' );
define( 'SMTP_PORT', 1025 );
define( 'WP_TESTS_DOMAIN', 'localhost:8889' );
/* That's all, stop editing! Happy publishing. */
/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
/** Sets up WordPress vars and included files. */

@ -0,0 +1,140 @@
<?php
/**
* The base configuration for WordPress
*
* The wp-config.php creation script uses this file during the
* installation. You don't have to use the web site, you can
* copy this file to "wp-config.php" and fill in the values.
*
* This file contains the following configurations:
*
* * MySQL settings
* * Secret keys
* * Database table prefix
* * ABSPATH
*
* This has been slightly modified (to read environment variables) for use in Docker.
*
* @link https://wordpress.org/support/article/editing-wp-config-php/
*
* @package WordPress
*/
// IMPORTANT: this file needs to stay in-sync with https://github.com/WordPress/WordPress/blob/master/wp-config-sample.php
// (it gets parsed by the upstream wizard in https://github.com/WordPress/WordPress/blob/f27cb65e1ef25d11b535695a660e7282b98eb742/wp-admin/setup-config.php#L356-L392)
// a helper function to lookup "env_FILE", "env", then fallback
function getenv_docker($env, $default) {
if ($fileEnv = getenv($env . '_FILE')) {
return rtrim(file_get_contents($fileEnv), "\r\n");
}
else if (($val = getenv($env)) !== false) {
return $val;
}
else {
return $default;
}
}
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'wordpress') );
/** MySQL database username */
define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'root') );
/** MySQL database password */
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', '') );
/**
* Docker image fallback values above are sourced from the official WordPress installation wizard:
* https://github.com/WordPress/WordPress/blob/f9cc35ebad82753e9c86de322ea5c76a9001c7e2/wp-admin/setup-config.php#L216-L230
* (However, using "example username" and "example password" in your database is strongly discouraged. Please use strong, random credentials!)
*/
/** MySQL hostname */
define( 'DB_HOST', getenv_docker('WORDPRESS_DB_HOST', 'mysql') );
/** Database Charset to use in creating database tables. */
define( 'DB_CHARSET', getenv_docker('WORDPRESS_DB_CHARSET', 'utf8') );
/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', getenv_docker('WORDPRESS_DB_COLLATE', '') );
/**#@+
* Authentication Unique Keys and Salts.
*
* Change these to different unique phrases!
* You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}
* You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again.
*
* @since 2.6.0
*/
define( 'AUTH_KEY', getenv_docker('WORDPRESS_AUTH_KEY', '96f6bcee44eacbd3e9a5c3c78f52d615bbe550f1') );
define( 'SECURE_AUTH_KEY', getenv_docker('WORDPRESS_SECURE_AUTH_KEY', 'cd0555ee6a32c91e064a499ebb3fd5ceea62e2a3') );
define( 'LOGGED_IN_KEY', getenv_docker('WORDPRESS_LOGGED_IN_KEY', '34b7c03618d67a8d626cd5c78508adfe542e6349') );
define( 'NONCE_KEY', getenv_docker('WORDPRESS_NONCE_KEY', '848d7098eb38eca67857d6e0ee5b3fba5962c7c1') );
define( 'AUTH_SALT', getenv_docker('WORDPRESS_AUTH_SALT', '881a5f5689e7c265b8dd8c6ae4fdff54888e06fa') );
define( 'SECURE_AUTH_SALT', getenv_docker('WORDPRESS_SECURE_AUTH_SALT', '2275b260e683602a91c8d19f6a05a6362bd5a91f') );
define( 'LOGGED_IN_SALT', getenv_docker('WORDPRESS_LOGGED_IN_SALT', '7cf0086a484ed4eabd1ce1b09a6a59a11297c61f') );
define( 'NONCE_SALT', getenv_docker('WORDPRESS_NONCE_SALT', '2fc8e8507b204f6e69e2c750a5ceaed9f5951736') );
// (See also https://wordpress.stackexchange.com/a/152905/199287)
/**#@-*/
/**
* WordPress Database Table prefix.
*
* You can have multiple installations in one database if you give each
* a unique prefix. Only numbers, letters, and underscores please!
*/
$table_prefix = getenv_docker('WORDPRESS_TABLE_PREFIX', 'wp_');
/**
* For developers: WordPress debugging mode.
*
* Change this to true to enable the display of notices during development.
* It is strongly recommended that plugin and theme developers use WP_DEBUG
* in their development environments.
*
* For information on other constants that can be used for debugging,
* visit the documentation.
*
* @link https://wordpress.org/support/article/debugging-in-wordpress/
*/
define( 'WP_PHP_BINARY', 'php' );
define( 'WP_TESTS_EMAIL', 'admin@example.org' );
define( 'WP_TESTS_TITLE', 'Test Blog' );
define( 'WP_SITEURL', 'http://localhost:8888/' );
define( 'WP_HOME', 'http://localhost:8888/' );
define( 'WP_DEBUG', true );
// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact
// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
// (we include this by default because reverse proxying is extremely common in container environments)
if ($configExtra = getenv_docker('WORDPRESS_CONFIG_EXTRA', '')) {
eval($configExtra);
}
define( 'WP_LOCAL_DEV', true );
define( 'PHP_INI_MEMORY_LIMIT', '512M' );
define( 'WP_MEMORY_LIMIT', '512M' );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
define( 'SCRIPT_DEBUG', true );
define( 'SMTP_HOST', 'mailhog' );
define( 'SMTP_PORT', 1025 );
define( 'WP_TESTS_DOMAIN', 'http://localhost:8888/' );
/* That's all, stop editing! Happy publishing. */
/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';

@ -0,0 +1,247 @@
<?php
/**
* The base configuration for WordPress
*
* The wp-config.php creation script uses this file during the
* installation. You don't have to use the web site, you can
* copy this file to "wp-config.php" and fill in the values.
*
* This file contains the following configurations:
*
* * MySQL settings
* * Secret keys
* * Database table prefix
* * ABSPATH
*
* This has been slightly modified (to read environment variables) for use in Docker.
*
* @link https://wordpress.org/support/article/editing-wp-config-php/
*
* @package WordPress
*/
// IMPORTANT: this file needs to stay in-sync with https://github.com/WordPress/WordPress/blob/master/wp-config-sample.php
// (it gets parsed by the upstream wizard in https://github.com/WordPress/WordPress/blob/f27cb65e1ef25d11b535695a660e7282b98eb742/wp-admin/setup-config.php#L356-L392)
// a helper function to lookup "env_FILE", "env", then fallback
function getenv_docker($env, $default) {
if ($fileEnv = getenv($env . '_FILE')) {
return rtrim(file_get_contents($fileEnv), "\r\n");
}
else if (($val = getenv($env)) !== false) {
return $val;
}
else {
return $default;
}
}
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', getenv_docker('WORDPRESS_DB_NAME', 'tests-wordpress') );
/** MySQL database username */
define( 'DB_USER', getenv_docker('WORDPRESS_DB_USER', 'root') );
/** MySQL database password */
define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', '') );
/**
* Docker image fallback values above are sourced from the official WordPress installation wizard:
* https://github.com/WordPress/WordPress/blob/f9cc35ebad82753e9c86de322ea5c76a9001c7e2/wp-admin/setup-config.php#L216-L230
* (However, using "example username" and "example password" in your database is strongly discouraged. Please use strong, random credentials!)
*/
/** MySQL hostname */
define( 'DB_HOST', getenv_docker('WORDPRESS_DB_HOST', 'mysql') );
/** Database Charset to use in creating database tables. */
define( 'DB_CHARSET', getenv_docker('WORDPRESS_DB_CHARSET', 'utf8') );
/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', getenv_docker('WORDPRESS_DB_COLLATE', '') );
/**#@+
* Authentication Unique Keys and Salts.
*
* Change these to different unique phrases!
* You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}
* You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again.
*
* @since 2.6.0
*/
define( 'AUTH_KEY', getenv_docker('WORDPRESS_AUTH_KEY', '755ef358c5a27ed0dc746d9787d4921218514caf') );
define( 'SECURE_AUTH_KEY', getenv_docker('WORDPRESS_SECURE_AUTH_KEY', '2ab5c46490b1f076010c19e6d2f13e5af9357ee9') );
define( 'LOGGED_IN_KEY', getenv_docker('WORDPRESS_LOGGED_IN_KEY', 'f7701c9a21f9f13dde7f0098325050c3a5cb8265') );
define( 'NONCE_KEY', getenv_docker('WORDPRESS_NONCE_KEY', 'f6b4c843e5d2c4b8d9d9c68d0509d6da03b79986') );
define( 'AUTH_SALT', getenv_docker('WORDPRESS_AUTH_SALT', '93b47cee7f7afb7d6a91ec224e705b0eac0fc9f0') );
define( 'SECURE_AUTH_SALT', getenv_docker('WORDPRESS_SECURE_AUTH_SALT', '59c8f022ed0da0fe3cb9e33090f11d4d141d6031') );
define( 'LOGGED_IN_SALT', getenv_docker('WORDPRESS_LOGGED_IN_SALT', 'c30efb00b0252d2fd709d212792a27bc6a279f73') );
define( 'NONCE_SALT', getenv_docker('WORDPRESS_NONCE_SALT', '4e56339167a14453a3b4044f9eaa3735a1a368f0') );
// (See also https://wordpress.stackexchange.com/a/152905/199287)
/**#@-*/
/**
* WordPress Database Table prefix.
*
* You can have multiple installations in one database if you give each
* a unique prefix. Only numbers, letters, and underscores please!
*/
$table_prefix = getenv_docker('WORDPRESS_TABLE_PREFIX', 'wp_');
/**
* For developers: WordPress debugging mode.
*
* Change this to true to enable the display of notices during development.
* It is strongly recommended that plugin and theme developers use WP_DEBUG
* in their development environments.
*
* For information on other constants that can be used for debugging,
* visit the documentation.
*
* @link https://wordpress.org/support/article/debugging-in-wordpress/
*/
define( 'WP_PHP_BINARY', 'php' );
define( 'WP_TESTS_EMAIL', 'admin@example.org' );
define( 'WP_TESTS_TITLE', 'Test Blog' );
define( 'WP_SITEURL', 'http://localhost:8889/' );
define( 'WP_HOME', 'http://localhost:8889/' );
define( 'WP_DEBUG', true );
// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact
// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
// (we include this by default because reverse proxying is extremely common in container environments)
if ($configExtra = getenv_docker('WORDPRESS_CONFIG_EXTRA', '')) {
eval($configExtra);
}
define( 'PHP_INI_MEMORY_LIMIT', '512M' );
define( 'WP_MEMORY_LIMIT', '512M' );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', true );
define( 'SCRIPT_DEBUG', true );
define( 'SMTP_HOST', 'mailhog' );
define( 'SMTP_PORT', 1025 );
define( 'WP_TESTS_DOMAIN', 'http://localhost:8889/' );
/* That's all, stop editing! Happy publishing. */
/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';
Loading…
Cancel
Save