get_current_user_login_url();
$parsed_url = wp_parse_url( $redirect_to );
$query = isset( $parsed_url['query'] ) ? '?' . $parsed_url['query'] : '';
return $custom_url . $query;
}
return $redirect_to;
}
public function filter_lostpassword_redirect_url( $location, $status ) {
if ( strpos( $location, 'wp-login.php' ) !== false && ( strpos( $location, 'checkemail=' ) !== false || strpos( $location, 'action=lostpassword' ) !== false ) ) {
$custom_url = $this->get_current_user_login_url();
$parsed_url = wp_parse_url( $location );
$query = isset( $parsed_url['query'] ) ? '?' . $parsed_url['query'] : '';
return $custom_url . $query;
}
return $location;
}
public function plugins_loaded() {
if ( ! is_user_logged_in() ) {
remove_action( 'template_redirect', 'wp_redirect_admin_locations', 1000 );
}
}
/**
* Validate that admin custom login URL is set if custom login is enabled
*/
public function validate_admin_custom_login_url() {
if ( ! is_admin() ) {
return;
}
$settings = get_option( 'ADALC_settings', array() );
$enabled = isset( $settings['enable_custom_login'] ) ? $settings['enable_custom_login'] : 0;
$admin_url = isset( $settings['role_slugs']['administrator'] ) ? trim( $settings['role_slugs']['administrator'] ) : '';
if ( $enabled && empty( $admin_url ) ) {
echo '
AccessDoor: Administrator custom login URL is required when custom login is enabled. Please set it in plugin settings.
';
}
}
/**
* Set intended role cookie/session before sending reset password link
*/
public function set_intended_role_for_reset_link() {
if ( isset( $_POST['user_login'] ) ) {
$user_login = sanitize_text_field( $_POST['user_login'] );
$user = get_user_by( 'login', $user_login );
if ( ! $user ) {
$user = get_user_by( 'email', $user_login );
}
if ( $user ) {
$roles = (array) $user->roles;
foreach ( $roles as $role ) {
if ( $this->get_role_login_url( $role ) ) {
setcookie( 'ADALC_intended_role', $role, time() + 3600, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
$_COOKIE['ADALC_intended_role'] = $role;
if ( ! session_id() ) {
session_start();
}
$_SESSION['ADALC_intended_role'] = $role;
break;
}
}
}
}
}
public function accessdoor_modify_password_reset_link( $message, $key, $user_login, $user_data ) {
$roles = (array) $user_data->roles;
$user_role = $roles[0] ?? '';
$custom_login_url = $this->get_role_login_url( $user_role );
if( ! $custom_login_url ){
$custom_login_url = $this->get_current_user_login_url();
}
// Build new reset link
$new_link = add_query_arg(
array(
'action' => 'rp',
'key' => $key,
'login' => rawurlencode( $user_login ),
),
$custom_login_url
);
// Replace the default reset link in email body
$message = preg_replace(
'#https?://[^\s]+#',
$new_link,
$message
);
return $message;
}
/**
* Handle custom login page request based on role - DIRECTLY SHOW LOGIN FORM.
*/
public function handle_custom_login() {
$login_role = get_query_var( 'ADALC_login_role' );
if ( ! $login_role ) {
return;
}
// Validate that this is a valid role.
if ( ! wp_roles()->is_role( $login_role ) ) {
status_header( 404 );
nocache_headers();
include( get_query_template( '404' ) );
exit;
}
// Store the intended role in cookie for validation during login.
setcookie( 'ADALC_intended_role', $login_role, time() + 3600, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
$_COOKIE['ADALC_intended_role'] = $login_role; // Set for immediate use.
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
// Also store in session as backup.
if ( ! session_id() ) {
session_start();
}
$_SESSION['ADALC_intended_role'] = $login_role;
$_SESSION['ADALC_current_login_url'] = home_url( get_query_var( 'pagename' ) );
// Set nocache headers.
nocache_headers();
// Initialize variables expected by wp-login.php to prevent warnings.
$user_login = '';
$user_email = '';
$redirect_to = '';
$error = '';
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$action = isset( $_REQUEST['action'] ) ? sanitize_key( wp_unslash( $_REQUEST['action'] ) ) : 'login';
// DIRECTLY load wp-login.php to show the login form.
require_once ABSPATH . 'wp-login.php';
exit;
}
/**
* Validate user role BEFORE login completes (during authentication).
*
* @param WP_User|WP_Error|null $user WP_User if authenticated, WP_Error on failure, null if not processed.
* @param string $username Username or email address.
* @param string $password User password.
* @return WP_User|WP_Error User object on success, WP_Error on failure.
*/
public function validate_user_role_before_login( $user, $username, $password ) {
// Only validate if user authentication was successful.
if ( ! is_wp_error( $user ) && $user instanceof WP_User ) {
// Get intended role from cookie or session.
$intended_role = null;
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( isset( $_COOKIE['ADALC_intended_role'] ) ) {
$intended_role = sanitize_key( $_COOKIE['ADALC_intended_role'] );
} elseif ( ! empty( $_SESSION['ADALC_intended_role'] ) ) {
$intended_role = sanitize_key( $_SESSION['ADALC_intended_role'] );
}
// Check if user is logging in via role-specific URL.
if ( $intended_role ) {
$user_roles = (array) $user->roles;
// Check if user has the required role.
if ( ! in_array( $intended_role, $user_roles, true ) ) {
// Get all allowed login URLs for this user
$allowed_urls = array();
foreach ( $user_roles as $role ) {
$url = $this->get_role_login_url( $role );
if ( $url ) {
$allowed_urls[] = trailingslashit( $url );
}
}
// Get the current URL being accessed
$current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$current_url = strtok( $current_url, '?' ); // Remove query string for strict match
$current_url = trailingslashit( $current_url );
// If current URL is not in allowed URLs, block login
if ( ! empty( $allowed_urls ) && ! in_array( $current_url, $allowed_urls, true ) ) {
setcookie( 'ADALC_intended_role', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN );
if ( isset( $_SESSION['ADALC_intended_role'] ) ) {
unset( $_SESSION['ADALC_intended_role'] );
}
return new WP_Error(
'invalid_role_login',
sprintf(
__( 'ERROR: You do not have permission to login via this URL. Please use your designated login page.', 'accessdoor-smart-admin-login-url-control' )
)
);
}
}
// Role is valid - clear the cookie and session after validation.
setcookie( 'ADALC_intended_role', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN );
if ( isset( $_SESSION['ADALC_intended_role'] ) ) {
unset( $_SESSION['ADALC_intended_role'] );
}
}
}
return $user;
}
/**
* Get login URL for specific role.
*
* @param string $role Role slug.
* @return string|false Login URL or false if not set.
*/
public function get_role_login_url( $role ) {
$settings = get_option( 'ADALC_settings', array() );
if ( isset( $settings['role_slugs'][ $role ] ) && ! empty( $settings['role_slugs'][ $role ] ) ) {
return home_url( $settings['role_slugs'][ $role ] );
}
return false;
}
/**
* Get login URL for current user or from session/cookie.
*
* @return string Login URL.
*/
public function get_current_user_login_url() {
// First check if there's an intended role in cookie/session (during login attempt).
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( isset( $_COOKIE['ADALC_intended_role'] ) ) {
$intended_role = sanitize_key( $_COOKIE['ADALC_intended_role'] );
$url = $this->get_role_login_url( $intended_role );
if ( $url ) {
return $url;
}
}
if ( ! empty( $_SESSION['ADALC_intended_role'] ) ) {
$intended_role = sanitize_key( $_SESSION['ADALC_intended_role'] );
$url = $this->get_role_login_url( $intended_role );
if ( $url ) {
return $url;
}
}
// Then check if user is logged in.
if ( is_user_logged_in() ) {
$user = wp_get_current_user();
$roles = (array) $user->roles;
// Try to get URL for user's first role.
foreach ( $roles as $role ) {
$url = $this->get_role_login_url( $role );
if ( $url ) {
return $url;
}
}
}
// Fallback to first available role login URL.
$settings = get_option( 'ADALC_settings', array() );
if ( isset( $settings['role_slugs'] ) && is_array( $settings['role_slugs'] ) ) {
foreach ( $settings['role_slugs'] as $role => $slug ) {
if ( ! empty( $slug ) ) {
return home_url( $slug );
}
}
}
return wp_login_url();
}
/**
* Filter login URL to use custom slug based on context.
*
* @param string $login_url The login URL.
* @param string $redirect The redirect URL.
* @param bool $force_reauth Whether to force reauth.
* @return string Modified login URL.
*/
public function filter_login_url( $login_url, $redirect = '', $force_reauth = false ) {
$settings = get_option( 'ADALC_settings', array() );
$enabled = isset( $settings['enable_custom_login'] ) ? $settings['enable_custom_login'] : 0;
if ( ! $enabled ) {
return $login_url;
}
// Check if any custom login URLs exist.
$has_custom_urls = false;
if ( isset( $settings['role_slugs'] ) && is_array( $settings['role_slugs'] ) ) {
foreach ( $settings['role_slugs'] as $slug ) {
if ( ! empty( $slug ) ) {
$has_custom_urls = true;
break;
}
}
}
// If no custom URLs configured, allow default wp-login/wp-admin access.
if ( ! $has_custom_urls ) {
return $login_url;
}
// If redirect is to wp-admin and no cookies set, redirect to configured redirect URL instead.
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( ! empty( $redirect ) && strpos( $redirect, 'wp-admin' ) !== false && ! isset( $_COOKIE['ADALC_intended_role'] ) ) {
$redirect_enabled = isset( $settings['redirect_wp_login'] ) ? $settings['redirect_wp_login'] : 1;
if ( $redirect_enabled ) {
$redirect_url = isset( $settings['redirect_url'] ) ? $settings['redirect_url'] : home_url();
wp_safe_redirect( $redirect_url, 302 );
exit;
} else {
status_header( 404 );
nocache_headers();
include( get_query_template( '404' ) );
exit;
}
}
// Get appropriate login URL.
$custom_url = $this->get_current_user_login_url();
if ( $redirect ) {
$custom_url = add_query_arg( 'redirect_to', urlencode( $redirect ), $custom_url );
}
if ( $force_reauth ) {
$custom_url = add_query_arg( 'reauth', '1', $custom_url );
}
return $custom_url;
}
/**
* Filter site URL to replace wp-login.php references.
*
* @param string $url The complete site URL.
* @param string $path Path relative to the site URL.
* @param string|null $scheme The scheme to use.
* @param int|null $blog_id The blog ID.
* @return string Modified URL.
*/
public function filter_site_url( $url, $path, $scheme, $blog_id = null) {
if ( $blog_id === null && is_multisite() ) {
$blog_id = get_current_blog_id();
}
static $in_filter = false;
if ( $in_filter ) {
return $url;
}
$in_filter = true;
$settings = get_option( 'ADALC_settings', array() );
$enabled = isset( $settings['enable_custom_login'] ) ? $settings['enable_custom_login'] : 0;
if ( ! $enabled || strpos( $url, 'wp-login.php' ) === false ) {
$in_filter = false;
return $url;
}
// Get custom login URL.
$custom_url = $this->get_current_user_login_url();
// Parse the original URL to preserve query parameters.
$parsed_url = wp_parse_url( $url );
$query = isset( $parsed_url['query'] ) ? '?' . $parsed_url['query'] : '';
// If checkemail or other login actions, keep the query string
$in_filter = false;
return $custom_url . $query;
}
/**
* Store user role before logout for proper redirect.
*/
public function store_user_role_before_logout() {
if ( is_user_logged_in() ) {
$user = wp_get_current_user();
$roles = (array) $user->roles;
// Store the first role that has a custom login URL.
foreach ( $roles as $role ) {
if ( $this->get_role_login_url( $role ) ) {
setcookie( 'ADALC_logout_role', $role, time() + 60, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
$_COOKIE['ADALC_logout_role'] = $role;
break;
}
}
}
}
/**
* Clear all login-related cookies and sessions on logout.
*/
public function clear_login_cookies_on_logout() {
$settings = get_option( 'ADALC_settings', array() );
$enabled = isset( $settings['enable_custom_login'] ) ? $settings['enable_custom_login'] : 0;
if ( ! $enabled ) {
return;
}
// Clear intended role cookie.
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( isset( $_COOKIE['ADALC_intended_role'] ) ) {
setcookie( 'ADALC_intended_role', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
unset( $_COOKIE['ADALC_intended_role'] );
}
// Clear session data.
if ( session_id() ) {
if ( isset( $_SESSION['ADALC_intended_role'] ) ) {
unset( $_SESSION['ADALC_intended_role'] );
}
if ( isset( $_SESSION['ADALC_current_login_url'] ) ) {
unset( $_SESSION['ADALC_current_login_url'] );
}
}
wp_safe_redirect( home_url() );
exit;
}
/**
* Redirect user to their role-specific login URL after logout.
*
* @param string $redirect_to The redirect destination URL.
* @param string $requested_redirect_to The requested redirect destination URL.
* @param WP_User|null $user The WP_User object for the user being logged out.
* @return string Modified redirect URL.
*/
public function logout_redirect( $redirect_to, $requested_redirect_to, $user ) {
$settings = get_option( 'ADALC_settings', array() );
$enabled = isset( $settings['enable_custom_login'] ) ? $settings['enable_custom_login'] : 0;
if ( ! $enabled ) {
return $redirect_to;
}
// Check if we stored a role before logout.
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
// if ( isset( $_COOKIE['ADALC_logout_role'] ) ) {
// $logout_role = sanitize_key( $_COOKIE['ADALC_logout_role'] );
// $custom_url = $this->get_role_login_url( $logout_role );
// // Clear the logout role cookie.
// setcookie( 'ADALC_logout_role', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true );
// unset( $_COOKIE['ADALC_logout_role'] );
// if ( $custom_url ) {
// return $custom_url;
// }
// }
// // Fallback: check if user object is available.
// if ( $user instanceof WP_User ) {
// $roles = (array) $user->roles;
// $custom_url = false;
// foreach ( $roles as $role ) {
// $custom_url = $this->get_role_login_url( $role );
// if ( $custom_url ) {
// return $custom_url;
// }
// }
// // If no slug for any user role, try admin custom slug
// if ( isset( $settings['role_slugs']['administrator'] ) && ! empty( $settings['role_slugs']['administrator'] ) ) {
// return home_url( $settings['role_slugs']['administrator'] );
// }
// }
return home_url();
// Final fallback to redirect URL setting or home.
// return isset( $settings['redirect_url'] ) ? $settings['redirect_url'] : home_url();
}
/**
* Block access to default wp-login.php.
*/
public function block_default_login() {
$settings = get_option( 'ADALC_settings', array() );
$enabled = isset( $settings['enable_custom_login'] ) ? $settings['enable_custom_login'] : 0;
if ( ! $enabled ) {
return;
}
$redirect = isset( $settings['redirect_wp_login'] ) ? $settings['redirect_wp_login'] : 1;
// Allow access for logged in users and AJAX/REST requests.
if ( is_user_logged_in() || wp_doing_ajax() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || ( defined( 'WP_CLI' ) && WP_CLI ) ) {
return;
}
// Check if accessing wp-login.php or wp-admin directly.
global $pagenow;
$is_wp_login = ( 'wp-login.php' === $pagenow );
$is_wp_admin = ( 'admin.php' === $pagenow || 'index.php' === $pagenow ) && strpos( $_SERVER['REQUEST_URI'], '/wp-admin' ) !== false;
if ( $is_wp_login || $is_wp_admin ) {
// Block ALL actions on wp-login.php if custom login is enabled.
// This includes lostpassword, resetpass, rp, etc.
// Only allow access to custom login URLs.
// Clear any existing cookies before redirect or 404
if ( isset( $_COOKIE['ADALC_intended_role'] ) ) {
setcookie( 'ADALC_intended_role', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN );
}
if ( $redirect ) {
$redirect_enabled = isset( $settings['redirect_wp_login'] ) ? $settings['redirect_wp_login'] : 1;
if ( $redirect_enabled ) {
// Redirect to custom URL or home.
$redirect_url = isset( $settings['redirect_url'] ) ? $settings['redirect_url'] : home_url();
wp_safe_redirect( $redirect_url, 302 );
exit;
} else {
// Show 404 if not redirecting
status_header( 404 );
nocache_headers();
include( get_query_template( '404' ) );
exit;
}
} else {
// Show 404 if not redirecting
status_header( 404 );
nocache_headers();
include( get_query_template( '404' ) );
exit;
}
}
}
/**
* Redirect WooCommerce logout to customer custom login URL.
*
* @param string $redirect_url Default redirect URL.
* @return string Modified redirect URL.
*/
public function woocommerce_logout_redirect( $redirect_url ) {
$settings = get_option( 'ADALC_settings', array() );
$enabled = isset( $settings['enable_custom_login'] ) ? $settings['enable_custom_login'] : 0;
if ( ! $enabled ) {
return $redirect_url;
}
// Get customer role login URL.
$customer_login_url = $this->get_role_login_url( 'customer' );
if ( $customer_login_url ) {
return $customer_login_url;
}
// Fallback to configured redirect URL only if redirect_wp_login is enabled.
$redirect_enabled = isset( $settings['redirect_wp_login'] ) ? $settings['redirect_wp_login'] : 1;
if ( $redirect_enabled ) {
return isset( $settings['redirect_url'] ) ? $settings['redirect_url'] : home_url();
}
return home_url();
}
/**
* Apply custom branding to login page
*/
public function enqueue_custom_login_styles() {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( isset( $_COOKIE['ADALC_intended_role'] ) ) {
$role = sanitize_key( $_COOKIE['ADALC_intended_role'] );
$settings = get_option( 'ADALC_settings', array() );
$logo_id = isset( $settings['role_logo'][ $role ] ) ? $settings['role_logo'][ $role ] : '';
$bg_image_id = isset( $settings['role_bg_image'][ $role ] ) ? $settings['role_bg_image'][ $role ] : '';
$bg_color = isset( $settings['role_bg_color'][ $role ] ) ? $settings['role_bg_color'][ $role ] : '#f0f0f1';
$logo = $logo_id ? wp_get_attachment_url( $logo_id ) : '';
$bg_image = $bg_image_id ? wp_get_attachment_url( $bg_image_id ) : '';
$css = '';
if ( ! empty( $bg_image ) ) {
$css .= 'body.login { background: url(' . esc_url( $bg_image ) . ') no-repeat center center fixed; background-size: cover; }';
} else {
$css .= 'body.login { background: ' . esc_attr( $bg_color ) . '; }';
}
if ( ! empty( $logo ) ) {
$css .= '.login h1 a { background-image: url(' . esc_url( $logo ) . '); background-size: contain; width: 100%; }';
}
wp_enqueue_style( 'login' );
wp_add_inline_style( 'login', $css );
}
}
/**
* Block lost password requests for users not matching intended role.
*/
public function block_lostpassword_for_wrong_role() {
if ( ! isset( $_REQUEST['action'] ) || $_REQUEST['action'] !== 'lostpassword' ) {
return;
}
// Only run if custom login is enabled
$settings = get_option( 'ADALC_settings', array() );
$enabled = isset( $settings['enable_custom_login'] ) ? $settings['enable_custom_login'] : 0;
if ( ! $enabled ) {
return;
}
// Get intended role from cookie/session
$intended_role = null;
if ( isset( $_COOKIE['ADALC_intended_role'] ) ) {
$intended_role = sanitize_key( $_COOKIE['ADALC_intended_role'] );
} elseif ( ! empty( $_SESSION['ADALC_intended_role'] ) ) {
$intended_role = sanitize_key( $_SESSION['ADALC_intended_role'] );
}
if ( ! $intended_role ) {
return;
}
// Get entered username/email
$user_login = isset( $_POST['user_login'] ) ? sanitize_text_field( $_POST['user_login'] ) : '';
if ( empty( $user_login ) ) {
return;
}
// Try to get user by login or email
$user = get_user_by( 'login', $user_login );
if ( ! $user ) {
$user = get_user_by( 'email', $user_login );
}
if ( ! $user ) {
return;
}
$has_custom_url = false;
// Check if user has the intended role
$user_roles = (array) $user->roles;
if ( ! in_array( $intended_role, $user_roles, true ) ) {
//check if user has any custom login URL for their roles
// Check if user has no custom login URL for their role
$has_custom_url = false;
foreach ( $user_roles as $role ) {
if ( $this->get_role_login_url( $role ) ) {
$has_custom_url = true;
break;
}
}
// If no custom login URL for user, allow reset from fallback admin login URL
$admin_url = $this->get_role_login_url( 'administrator' );
if (
! $has_custom_url &&
$admin_url &&
isset($_SERVER['REQUEST_URI']) &&
strpos(rtrim($_SERVER['REQUEST_URI'], '/'), rtrim($admin_path, '/')) !== false
) {
// Allow password reset
return;
}
// Otherwise, block and show error
wp_die( esc_html__( 'You are not allowed to reset password from this login page. Please use your designated login page.', 'accessdoor-smart-admin-login-url-control' ), esc_html__( 'Access Denied', 'accessdoor-smart-admin-login-url-control' ), array( 'response' => 403 ) );
}
}
}
// Initialize the login handler class.
new ADALC_Login_Handler();