Skip to main content

Feature suggestion for FluentAuth

The ability to change the default WordPress login URL.

For example: from my-domain.com/wp-login.php to my-domain.com/auth

David Scurlock

+1 this would make it impossible for hackers to find if we could change the login admin url.

+1

Dany Tetreault

I use CHANGE FOR EMAIL plug in, it really simple. In order to modify your login page, afin your all set

Drive Zone

You can use my snippet to redirect all entries on wp-login pages to FC/FA pages if it will help you. It works also with NextEnd Social login plugin which I use.

function redirect_wp_login() {

$allowed_actions = ['logout', 'lostpassword', 'rp', 'resetpass', 'register'];

$request_uri = $_SERVER['REQUEST_URI'];

// βš™οΈ PΕ™idΓ‘me vΓ½jimku pro callback Seznam loginu
if (strpos($request_uri, '/seznam-callback/') !== false) {
    return;
}

// Detekce pΕ™Γ­stupu na wp-login.php
if (strpos($request_uri, 'wp-login.php') !== false) {

    // 1️⃣ β€” PonechΓ‘me pΕ™Γ­stup, pokud jde o povolenΓ© akce
    if (isset($_GET['action']) && in_array($_GET['action'], $allowed_actions, true)) {
        return;
    }

    // 2️⃣ β€” PonechΓ‘me pΕ™Γ­stup, pokud jde o Nextend Social Login (OAuth callback)
    $oauth_params = ['loginSocial', 'redirect_to', 'state', 'code', 'scope', 'authuser', 'prompt'];
    foreach ($oauth_params as $param) {
        if (isset($_GET[$param])) {
            return;
        }
    }

    // 3️⃣ β€” Jinak pΕ™esmΔ›rujeme na vlastnΓ­ login
    wp_safe_redirect(home_url('/portal/?fcom_action=auth'));
    exit;
}

}
add_action('init', 'redirect_wp_login');

William Beem

Security by obscurity does not work. I've tested this with other plugins that redirected the login page and they always found it. The best thing to do is to have good WAF rules at the edge (like Cloudflare) to block the majority of malicious actors and bots, and then have good authentication policies.

It wouldn't bother me if FluentAuth added this feature, but I wouldn't use it. This is an amateur move that gives a false sense of security and it's easily overcome with a scan. The URL has to be public, so it's available to find and overcome.

David Scurlock

William BeemΒ create a dummy admin login and it will keep them busy trying to hack a fake login page and with 100s or 1000s of urls, they won't be able to find the real admin url that is blended in with the rest of the urls. Wannabe hackers are predictable, they will be scanning for admin type urls. A real hacker will try injecting something into wp, he would not be using login anyways.

Mat β€Ž

David ScurlockΒ there are tricks to discover or be redirected to the real wp-admin (login form) so I wouldnt bother hiding the url.

In many cases when a user type url dedicated for logged-in users it is automatically redirecting to the right Login form (all kinds of recovery mode plugins urls can be used to achieve the same)

One of many examples showing how plugins can be used to discover hidden login form:

https://www.sprocketsecurity.com/blog/discovering-wp-admin-urls-in-wordpress-with-gravityforms

Similar logic can be used with query strings like reauth=1 for fluent forms AFAIR - it is just to show the idea

?redirect_to=/wp-admin/admin.php/page/fluent_forms&reauth=1
or
/wp-admin/customize.php
or
/wp-activate
or
have expired fake cookie to force wp to redirect to the login page
or
check CSP header when implemented and look for white listed url in: script-src or form-action

Rafael Piton

William BeemΒ My suggestion was related to the aesthetics of the URL.

William Beem

Rafael PitonΒ It's possible, but I'm not sure it's necessary. With FliuentAuth, my login accomplishes the same thing today. Create a page, plop in a shortcode, and you can choose the slug.

Daanyaal Alamin

Why not create a restricted (access denied) page - jpg of denied access and choose a secret word that would be the wp-admin alternative and if that word isn't typed after your URL (example.com/secretword) then it automatically takes them to that restricted page.

Then you use code within functions.php to make it function.

You can also replace the restricted and just redirect them to the student login homeurl.com/auth/login

Here's a template of what I used. You can easily copy and paste this into chatgpt to have it give you additional code to exclude certain pages from the restriction access if you have certain things built in.

// 02. Access: Admin Masking + Secret Admin Entry
// ======================================
// - Secret entry: /SECRETWORDHERE
// - Access denied page: /restricted
// - Masks /wp-login.php and /wp-admin for logged-out users
// - Keeps Automator/FluentCRM routes & REST working
// - Locks homepage ("/") for guests, so the main link is also restricted (this can be omitted)
// - Bypass request is very important at the top of this code as it prevents the site from having a critical error
// ============================================

if (!function_exists('bypass_request')) {
    function bypass_request() {
        // Bypass loopbacks/sandbox/AJAX/REST/CLI
        if (defined('WP_SANDBOX_SCRAPING') && WP_SANDBOX_SCRAPING) return true;
        if (!empty($_GET['wp_scrape_key'])) return true;
        if (function_exists('wp_doing_ajax') && wp_doing_ajax()) return true;
        if (defined('REST_REQUEST') && REST_REQUEST) return true;
        if (defined('WP_CLI') && WP_CLI) return true;

        // Allow known webhook entry points (don’t block or redirect these)
        $uri = $_SERVER['REQUEST_URI'] ?? '';
        if ($uri) {
            // Uncanny Automator webhook/API style
            if (isset($_GET['automator_api'])) return true;
            // FluentCRM router (e.g., ?fluentcrm=1&route=...)
            if (isset($_GET['fluentcrm']))     return true;
            // REST API (used by plugins)
            if (strpos($uri, '/wp-json/') !== false) return true;
        }
        return false;
    }
}

add_action('template_redirect', function () {
    if (bypass_request()) return;

    $path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/';

    // Secret admin entry (/SECRETWORDHERE):
    // - logged-in  β†’ /wp-admin
    // - logged-out β†’ set short-lived "SECRETWORDHERE" cookie (10m), then forward to /wp-login.php
    if ($path === '/SECRETWORDHERE' || $path === '/SECRETWORDHERE/') {
        if (is_user_logged_in()) {
            wp_safe_redirect(admin_url());
        } else {
            setcookie('SECRETWORDHERE', '1', [
                'expires'  => time() + 600,   // 10 minutes
                'path'     => '/',
                'secure'   => is_ssl(),
                'httponly' => true,
                'samesite' => 'Lax'
            ]);
            wp_safe_redirect(wp_login_url()); // /wp-login.php
        }
        exit;
    }

    // Lock homepage for guests (hub is admin-only)
    if ($path === '/' && !is_user_logged_in()) {
        wp_safe_redirect(home_url('/restricted'));
        exit;
    }

    // Mask /wp-admin for guests (allow ajax/post endpoints)
    if (preg_match('#^/wp-admin/?#', $path) && !is_user_logged_in()) {
        $base = basename($path);
        if (!in_array($base, ['admin-ajax.php','admin-post.php'], true)) {
            wp_safe_redirect(home_url('/restricted'));
            exit;
        }
    }
});

add_action('init', function () {
    if (bypass_request()) return;

    $path = parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?: '';
    if ($path !== '/wp-login.php') return;

    // Logged-out must come via /SECRETWORDHERE (cookie required)
    if (!is_user_logged_in()) {
        if (empty($_COOKIE['wu_inside'])) {
            wp_safe_redirect(home_url('/restricted'));
            exit;
        }
        // Gate cookie present β†’ allow normal wp-login load
        return;
    }

    // Logged-in hitting wp-login.php β†’ go to /wp-admin
    wp_safe_redirect(admin_url());
    exit;
});

// - Security: Disable XML-RPC
// =============================================================================
// Your plugin set does not require XML-RPC. Remove this brute-force surface.
add_filter('xmlrpc_enabled', '__return_false');
add_action('init', function () {
    $uri = $_SERVER['REQUEST_URI'] ?? '';
    if ($uri && strpos($uri, 'xmlrpc.php') !== false) {
        status_header(403); exit;
    }
});

// - Security: Block User Enumeration (REST + ?author=) for guests
// =============================================================================
add_action('template_redirect', function () {
    if (is_user_logged_in()) return;

    // Classic ?author=123 / author archives
    if (isset($_GET['author']) && $_GET['author'] !== '') {
        wp_safe_redirect(home_url('/restricted'));
        exit;
    }
    if (function_exists('is_author') && is_author()) {
        wp_safe_redirect(home_url('/restricted'));
        exit;
    }
});

// Block listing of users via REST for unauthenticated requests
add_filter('rest_endpoints', function ($endpoints) {
    if (!is_user_logged_in()) {
        unset($endpoints['/wp/v2/users']);
        unset($endpoints['/wp/v2/users/(?P<id>[\d]+)']);
    }
    return $endpoints;
});

// Also catch ?rest_route=/wp/v2/users
add_action('init', function () {
    if (is_user_logged_in()) return;
    $rq = $_GET['rest_route'] ?? '';
    if ($rq && stripos($rq, '/wp/v2/users') === 0) {
        status_header(403); exit;
    }
});  

Rafael Piton

FYI Ripon SarkarΒ