-
-
Save AlkoKod/9394bba46faea31bd80028f8727c8ec8 to your computer and use it in GitHub Desktop.
WordPress cross-domain login system that auto-authenticates users across multiple Polylang language domains using secure AJAX calls.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: Polylang + Bricks Cross Domain usage | |
* Description: Enables automatic login across multiple domains and paths using Polylang with folder installation support | |
* Version: 1.1 | |
* Author: Aleš Sýkora - forked from Vláďa Smitka - Lynt | |
*/ | |
// Get site URLs from Polylang | |
function lynt_get_site_urls() | |
{ | |
$site_urls = []; | |
if (function_exists('pll_languages_list')) { | |
$languages = pll_languages_list(array('fields' => 'home_url')); | |
foreach ($languages as $home_url) { | |
// Store complete URLs, not just domains | |
$site_urls[] = $home_url; | |
} | |
} | |
return apply_filters('lynt_login_site_urls', $site_urls); | |
} | |
function lynt_initialize_cross_login() | |
{ | |
// Only run on the dashboard page | |
$screen = get_current_screen(); | |
if (!$screen || $screen->id !== 'dashboard') { | |
return; | |
} | |
add_action('admin_footer', 'lynt_render_cross_login_script'); | |
} | |
// Add script for multi-domain login to dashboard | |
function lynt_render_cross_login_script() | |
{ | |
$site_urls = lynt_get_site_urls(); | |
$user_id = get_current_user_id(); | |
$current_url = home_url(); | |
if ($user_id > 0) { | |
// Create a signature for secure transmission of user ID | |
$timestamp = time(); | |
$signature = hash_hmac('sha256', $user_id . '|' . $timestamp, AUTH_KEY . SECURE_AUTH_KEY); | |
?> | |
<script> | |
jQuery(document).ready(function($) { | |
var currentUrl = '<?php echo esc_js($current_url); ?>'; | |
var loginData = { | |
'action': 'lynt_manage', | |
'cmd': 'login', | |
'user_id': <?php echo intval($user_id); ?>, | |
'timestamp': <?php echo intval($timestamp); ?>, | |
'signature': '<?php echo esc_js($signature); ?>' | |
}; | |
var siteUrls = <?php echo json_encode($site_urls); ?>; | |
siteUrls.forEach(function(siteUrl) { | |
if (siteUrl !== currentUrl) { | |
$.ajax({ | |
type: "POST", | |
url: siteUrl + "/wp-admin/admin-ajax.php", | |
data: loginData, | |
xhrFields: { | |
withCredentials: true | |
} | |
}); | |
} | |
}); | |
}); | |
</script> | |
<?php | |
} | |
} | |
// Handle AJAX - login process | |
function lynt_manage() | |
{ | |
// Set CORS | |
lynt_add_cors_headers(); | |
// Init result | |
$result = [ | |
'status' => 'error', | |
'message' => 'Invalid request' | |
]; | |
// Validate | |
if (!isset($_POST['cmd']) || !isset($_POST['user_id']) || !isset($_POST['timestamp']) || !isset($_POST['signature'])) { | |
wp_send_json($result); | |
return; | |
} | |
// Sanitize | |
$cmd = sanitize_text_field($_POST['cmd']); | |
$user_id = intval($_POST['user_id']); | |
$timestamp = intval($_POST['timestamp']); | |
$signature = sanitize_text_field($_POST['signature']); | |
if ($cmd === 'login' && is_user_logged_in()) { | |
$result = [ | |
'status' => 'info', | |
'message' => 'User already logged in', | |
]; | |
wp_send_json($result); | |
return; | |
} | |
// Process login command | |
if ($cmd === 'login' && !is_user_logged_in()) { | |
// Verify timestamp < 5 minutes | |
if (time() - $timestamp > 300) { | |
$result['message'] = 'Request expired'; | |
wp_send_json($result); | |
return; | |
} | |
// Verify signature | |
$expected_signature = hash_hmac('sha256', $user_id . '|' . $timestamp, AUTH_KEY . SECURE_AUTH_KEY); | |
if (!hash_equals($expected_signature, $signature)) { | |
$result['message'] = 'Invalid signature'; | |
wp_send_json($result); | |
return; | |
} | |
// Check user exists | |
$user = get_user_by('id', $user_id); | |
if (!$user) { | |
$result['message'] = 'User does not exist'; | |
wp_send_json($result); | |
return; | |
} | |
// Generate auth cookies | |
$expiration = time() + 8 * HOUR_IN_SECONDS; | |
$expire = $expiration + (1 * HOUR_IN_SECONDS); | |
$secure = true; // Vždy nastavit jako secure | |
$auth_cookie = wp_generate_auth_cookie($user_id, $expiration, 'secure_auth'); | |
$logged_in_cookie = wp_generate_auth_cookie($user_id, $expiration, 'logged_in'); | |
// Set cookies with SameSite=None (it will slightly decrease SECURITY) | |
setcookie( | |
SECURE_AUTH_COOKIE, | |
$auth_cookie, | |
[ | |
'expires' => $expire, | |
'path' => ADMIN_COOKIE_PATH, | |
'domain' => COOKIE_DOMAIN, | |
'secure' => $secure, | |
'httponly' => true, | |
'samesite' => 'None' | |
] | |
); | |
setcookie( | |
LOGGED_IN_COOKIE, | |
$logged_in_cookie, | |
[ | |
'expires' => $expire, | |
'path' => COOKIEPATH, | |
'domain' => COOKIE_DOMAIN, | |
'secure' => $secure, | |
'httponly' => true, | |
'samesite' => 'None' | |
] | |
); | |
// Optional call wp_login e.g. for auditing | |
// do_action('wp_login', $user->user_login, $user); | |
$result = [ | |
'status' => 'success', | |
'message' => 'Login successful' | |
]; | |
} | |
wp_send_json($result); | |
} | |
// Set CORS headers for cross-domain requests | |
function lynt_add_cors_headers() | |
{ | |
$allowed_site_urls = lynt_get_site_urls(); | |
// Check if request is from an allowed origin | |
if (isset($_SERVER['HTTP_ORIGIN'])) { | |
$origin = $_SERVER['HTTP_ORIGIN']; | |
// Check if the origin matches one of our allowed site URLs | |
$origin_matches = false; | |
foreach ($allowed_site_urls as $site_url) { | |
// Extract domain from site URL | |
$site_domain = parse_url($site_url, PHP_URL_HOST); | |
// Extract domain from origin | |
$origin_domain = parse_url($origin, PHP_URL_HOST); | |
if ($site_domain === $origin_domain) { | |
$origin_matches = true; | |
break; | |
} | |
} | |
if ($origin_matches) { | |
// Set CORS headers | |
header('Access-Control-Allow-Origin: ' . $origin); | |
header('Access-Control-Allow-Credentials: true'); | |
} | |
} | |
} | |
add_action('current_screen', 'lynt_initialize_cross_login'); | |
add_action('wp_ajax_nopriv_lynt_manage', 'lynt_manage'); | |
add_action('wp_ajax_lynt_manage', 'lynt_manage'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment