Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Disable built-in WordPress login / password reset / signup #478

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ nbproject
*.sublime-workspace
.idea
clover.xml
.vscode/launch.json

# Dreamweaver added files
_notes
Expand Down
1 change: 1 addition & 0 deletions HOWTO.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ On the settings page for this plugin (Dashboard > Settings > OpenID Connect Gene
- Enforce privacy: `OIDC_ENFORCE_PRIVACY` (boolean)
- Create user if they do not exist: `OIDC_CREATE_IF_DOES_NOT_EXIST` (boolean)
- Link existing user: `OIDC_LINK_EXISTING_USERS` (boolean)
- Disable WordPress login and signup forms: `OIDC_DISABLE_WP_LOGIN_AND_SIGNUP` (boolean)
- Redirect user back to origin page: `OIDC_REDIRECT_USER_BACK` (boolean)
- Redirect on logout: `OIDC_REDIRECT_ON_LOGOUT` (boolean)

Expand Down
95 changes: 95 additions & 0 deletions includes/openid-connect-generic-login-form.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public static function register( $settings, $client_wrapper ) {
add_shortcode( 'openid_connect_generic_login_button', array( $login_form, 'make_login_button' ) );

$login_form->handle_redirect_login_type_auto();
$login_form->handle_wp_login_and_signup();
}

/**
Expand Down Expand Up @@ -107,6 +108,28 @@ public function handle_login_page( $message ) {
return $message;
}

/**
* Disables built-in login functionality.
*
* @return void
*/
public function handle_wp_login_and_signup() {

if ( $this->settings->disable_wp_login_and_signup ) {
// Login functionality (login, signup, password reset) may be implemented on any page, not only wp-login.php;
// therefore, listen for these hooks globally.
add_filter( 'authenticate', array( $this, 'disable_authenticate' ), 99, 3 );
add_filter( 'lostpassword_errors', array( $this, 'disable_lostpassword' ), 99, 2 );
add_filter( 'registration_errors', array( $this, 'disable_registration' ), 99, 3 );

// Hide the login form and links to reset password and signup. This is just comsmetic change to prevent user confusion.
if ( 'wp-login.php' == $GLOBALS['pagenow'] ) {
add_action( 'login_footer', array( $this, 'remove_login_form_and_links' ), 99 );
}
}

}

/**
* Display an error message to the user.
*
Expand Down Expand Up @@ -173,9 +196,81 @@ public function remove_login_form() {
var loginForm = document.getElementById("user_login").form;
var parent = loginForm.parentNode;
parent.removeChild(loginForm);
</script>
<?php
}

/**
* Removes the login form from the HTML DOM
*
* @return void
*/
public function remove_login_form_and_links() {
?>
<script type="text/javascript">
(function() {
var loginForm = document.getElementById("user_login").form;
var parent = loginForm.parentNode;
parent.removeChild(loginForm);
var linksElem = document.getElementById("nav");
if (linksElem) { linksElem.parentNode.removeChild(linksElem); }
})();
</script>
<?php
}

/**
* Disables built-in login using username/password
*
* @param null|WP_User|WP_Error $user Authenticated user, error or null.
* @param string $username Username or email address.
* @param string $password User password.
*
* @return null|WP_User|WP_Error
*/
public function disable_authenticate( $user, $username, $password ) {

// We cannot completely disable wp-login.php page, because it is also used
// to display error messages. Only return error is login attempt with username/password is made.
if ( empty( $username ) || empty( $password ) ) {
return $user;
} else {
return new WP_Error( 'builtin-login-disabled', __( 'Built-in login is disabled.', 'daggerhart-openid-connect-generic' ) );
}

}

/**
* Disable built-in password reset functionality.
*
* @param WP_Error $errors A WP_Error object containing any errors generated by using invalid credentials.
* @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
*
* @return WP_Error
*/
public function disable_lostpassword( $errors, $user_data ) {

// Remove any previous errors to prevent possible information disclosure (e.g. existing email/username).
$errors = new WP_Error( 'builtin-lostpassword-disabled', __( 'Built-in password reset is disabled.', 'daggerhart-openid-connect-generic' ) );
return $errors;

}

/**
* Disable built-in signup functionality.
*
* @param WP_Error $errors A WP_Error object containing any errors encountered during registration.
* @param string $sanitized_user_login User's username after it has been sanitized.
* @param string $user_email User's email.
*
* @return WP_Error
*/
public function disable_registration( $errors, $sanitized_user_login, $user_email ) {

// Remove any previous errors to prevent possible information disclosure (e.g. existing email/username).
$errors = new WP_Error( 'builtin-signup-disabled', __( 'Built-in signup is disabled.', 'daggerhart-openid-connect-generic' ) );
return $errors;

}

}
48 changes: 25 additions & 23 deletions includes/openid-connect-generic-option-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,16 @@
*
* Plugin Settings:
*
* @property bool $enforce_privacy The flag to indicates whether a user us required to be authenticated to access the site.
* @property bool $alternate_redirect_uri The flag to indicate whether to use the alternative redirect URI.
* @property bool $token_refresh_enable The flag whether to support refresh tokens by IDPs.
* @property bool $link_existing_users The flag to indicate whether to link to existing WordPress-only accounts or greturn an error.
* @property bool $create_if_does_not_exist The flag to indicate whether to create new users or not.
* @property bool $redirect_user_back The flag to indicate whether to redirect the user back to the page on which they started.
* @property bool $redirect_on_logout The flag to indicate whether to redirect to the login screen on session expiration.
* @property bool $enable_logging The flag to enable/disable logging.
* @property int $log_limit The maximum number of log entries to keep.
* @property bool $enforce_privacy The flag to indicates whether a user us required to be authenticated to access the site.
* @property bool $alternate_redirect_uri The flag to indicate whether to use the alternative redirect URI.
* @property bool $token_refresh_enable The flag whether to support refresh tokens by IDPs.
* @property bool $link_existing_users The flag to indicate whether to link to existing WordPress-only accounts or greturn an error.
* @property bool $create_if_does_not_exist The flag to indicate whether to create new users or not.
* @property bool $disable_wp_login_and_signup The flag to indicate whether built-in login is disabled.
* @property bool $redirect_user_back The flag to indicate whether to redirect the user back to the page on which they started.
* @property bool $redirect_on_logout The flag to indicate whether to redirect to the login screen on session expiration.
* @property bool $enable_logging The flag to enable/disable logging.
* @property int $log_limit The maximum number of log entries to keep.
*/
class OpenID_Connect_Generic_Option_Settings {

Expand Down Expand Up @@ -87,20 +88,21 @@ class OpenID_Connect_Generic_Option_Settings {
* @var array<string,string>
*/
private $environment_settings = array(
'client_id' => 'OIDC_CLIENT_ID',
'client_secret' => 'OIDC_CLIENT_SECRET',
'endpoint_end_session' => 'OIDC_ENDPOINT_LOGOUT_URL',
'endpoint_login' => 'OIDC_ENDPOINT_LOGIN_URL',
'endpoint_token' => 'OIDC_ENDPOINT_TOKEN_URL',
'endpoint_userinfo' => 'OIDC_ENDPOINT_USERINFO_URL',
'login_type' => 'OIDC_LOGIN_TYPE',
'scope' => 'OIDC_CLIENT_SCOPE',
'create_if_does_not_exist' => 'OIDC_CREATE_IF_DOES_NOT_EXIST',
'enforce_privacy' => 'OIDC_ENFORCE_PRIVACY',
'link_existing_users' => 'OIDC_LINK_EXISTING_USERS',
'redirect_on_logout' => 'OIDC_REDIRECT_ON_LOGOUT',
'redirect_user_back' => 'OIDC_REDIRECT_USER_BACK',
'acr_values' => 'OIDC_ACR_VALUES',
'client_id' => 'OIDC_CLIENT_ID',
'client_secret' => 'OIDC_CLIENT_SECRET',
'endpoint_end_session' => 'OIDC_ENDPOINT_LOGOUT_URL',
'endpoint_login' => 'OIDC_ENDPOINT_LOGIN_URL',
'endpoint_token' => 'OIDC_ENDPOINT_TOKEN_URL',
'endpoint_userinfo' => 'OIDC_ENDPOINT_USERINFO_URL',
'login_type' => 'OIDC_LOGIN_TYPE',
'scope' => 'OIDC_CLIENT_SCOPE',
'create_if_does_not_exist' => 'OIDC_CREATE_IF_DOES_NOT_EXIST',
'enforce_privacy' => 'OIDC_ENFORCE_PRIVACY',
'link_existing_users' => 'OIDC_LINK_EXISTING_USERS',
'disable_wp_login_and_signup' => 'OIDC_DISABLE_WP_LOGIN_AND_SIGNUP',
'redirect_on_logout' => 'OIDC_REDIRECT_ON_LOGOUT',
'redirect_user_back' => 'OIDC_REDIRECT_USER_BACK',
'acr_values' => 'OIDC_ACR_VALUES',
);

/**
Expand Down
7 changes: 7 additions & 0 deletions includes/openid-connect-generic-settings-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,13 @@ private function get_settings_fields() {
'disabled' => defined( 'OIDC_CREATE_IF_DOES_NOT_EXIST' ),
'section' => 'user_settings',
),
'disable_wp_login_and_signup' => array(
'title' => __( 'Disable WordPress login and signup forms', 'daggerhart-openid-connect-generic' ),
'description' => __( 'If checked, built-in forms for login and registration (wp-login.php) will be disabled. It will be possible to login only via the configured Identity Provider.', 'daggerhart-openid-connect-generic' ),
'type' => 'checkbox',
'disabled' => defined( 'OIDC_DISABLE_WP_LOGIN_AND_SIGNUP' ),
'section' => 'user_settings',
),
'redirect_user_back' => array(
'title' => __( 'Redirect Back to Origin Page', 'daggerhart-openid-connect-generic' ),
'description' => __( 'After a successful OpenID Connect authentication, this will redirect the user back to the page on which they clicked the OpenID Connect login button. This will cause the login process to proceed in a traditional WordPress fashion. For example, users logging in through the default wp-login.php page would end up on the WordPress Dashboard and users logging in through the WooCommerce "My Account" page would end up on their account page.', 'daggerhart-openid-connect-generic' ),
Expand Down
1 change: 1 addition & 0 deletions openid-connect-generic.php
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ public static function bootstrap() {
'token_refresh_enable' => 1,
'link_existing_users' => defined( 'OIDC_LINK_EXISTING_USERS' ) ? intval( OIDC_LINK_EXISTING_USERS ) : 0,
'create_if_does_not_exist' => defined( 'OIDC_CREATE_IF_DOES_NOT_EXIST' ) ? intval( OIDC_CREATE_IF_DOES_NOT_EXIST ) : 1,
'disable_wp_login_and_signup' => defined( 'OIDC_DISABLE_WP_LOGIN_AND_SIGNUP' ) ? intval( OIDC_DISABLE_WP_LOGIN_AND_SIGNUP ) : 0,
'redirect_user_back' => defined( 'OIDC_REDIRECT_USER_BACK' ) ? intval( OIDC_REDIRECT_USER_BACK ) : 0,
'redirect_on_logout' => defined( 'OIDC_REDIRECT_ON_LOGOUT' ) ? intval( OIDC_REDIRECT_ON_LOGOUT ) : 1,
'enable_logging' => 0,
Expand Down