Skip to content

Commit 919862d

Browse files
committed
[FIX] SSO.
1 parent 77704ed commit 919862d

File tree

2 files changed

+22
-14
lines changed

2 files changed

+22
-14
lines changed

functions/sso.php

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function ms_b64u_json(array $a): string { return ms_b64u(json_encode($a, JSON_UN
3232
* Order of precedence:
3333
* 1) SMULTI_SSO_SECRET from environment (recommended: same across domains).
3434
* 2) If absent — read/write core/storage/ms_sso/secret.key (shared FS).
35-
* 3) Derive the final key by HMAC with SESSION_COOKIE_NAME as "info"/salt.
35+
* 3) Normalize the final key to 32 raw bytes (SHA-256).
3636
*
3737
* @return string Raw bytes (string) to be used as HMAC key.
3838
*/
@@ -42,6 +42,9 @@ function ms_sso_secret(): string {
4242
if ($sec) return $sec;
4343

4444
$base = getenv('SMULTI_SSO_SECRET');
45+
if ((!$base || $base === '') && function_exists('env')) {
46+
$base = env('SMULTI_SSO_SECRET');
47+
}
4548
if (!$base || strlen($base) < 32) {
4649
$dir = rtrim(EVO_CORE_PATH ?? __DIR__, '/') . '/storage/ms_sso';
4750
$file = $dir . '/secret.key';
@@ -54,10 +57,10 @@ function ms_sso_secret(): string {
5457
}
5558
}
5659

57-
$cookieName = defined('SESSION_COOKIE_NAME') ? SESSION_COOKIE_NAME : session_name();
58-
// HKDF-like derivation: bind to cookie name (makes cross-install reuse safer).
59-
$derived = hash_hmac('sha256', $cookieName, $base, true);
60-
return $sec = $derived;
60+
// Important: do not bind the signing key to SESSION_COOKIE_NAME.
61+
// In multi-domain setups cookie names often differ between domains,
62+
// which would make SSO tokens unverifiable and produce "Invalid/expired".
63+
return $sec = hash('sha256', (string)$base, true);
6164
}
6265
}
6366

@@ -86,16 +89,17 @@ function ms_sso_token_make(array $claims, int $ttl = 180): string {
8689
* @return array|null Payload if valid; null otherwise
8790
*/
8891
if (!function_exists('ms_sso_token_parse')) {
89-
function ms_sso_token_parse(string $jwt): ?array {
90-
if (!preg_match('~^[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+$~', $jwt)) return null;
92+
function ms_sso_token_parse(string $jwt, ?string &$err = null): ?array {
93+
$err = null;
94+
if (!preg_match('~^[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+$~', $jwt)) { $err = 'format'; return null; }
9195
[$h, $p, $s] = explode('.', $jwt, 3);
9296
$calc = ms_b64u(hash_hmac('sha256', "$h.$p", ms_sso_secret(), true));
93-
if (!hash_equals($calc, $s)) return null;
97+
if (!hash_equals($calc, $s)) { $err = 'signature'; return null; }
9498
$payload = json_decode(base64_decode(strtr($p, '-_', '+/')), true);
95-
if (!$payload || !is_array($payload)) return null;
99+
if (!$payload || !is_array($payload)) { $err = 'payload'; return null; }
96100
$now = time();
97-
if (isset($payload['nbf']) && $payload['nbf'] > $now) return null;
98-
if (isset($payload['exp']) && $payload['exp'] < $now) return null;
101+
if (isset($payload['nbf']) && $payload['nbf'] > $now) { $err = 'nbf'; return null; }
102+
if (isset($payload['exp']) && $payload['exp'] < $now) { $err = 'exp'; return null; }
99103
return $payload;
100104
}
101105
}

plugins/sMultisitePlugin.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ function ms_sso_load_functions(): void {
332332
$scheme = $https ? 'https' : 'http';
333333
$slow = isset($_GET['slow']);
334334
$cookie = defined('SESSION_COOKIE_NAME') ? SESSION_COOKIE_NAME : session_name();
335-
$rootDom = getenv('MS_SESSION_ROOT_DOMAIN') ?: '';
335+
$rootDom = getenv('MS_SESSION_ROOT_DOMAIN') ?: (function_exists('env') ? (string)env('MS_SESSION_ROOT_DOMAIN', '') : '');
336336

337337
$noStore = static function () {
338338
header('Cache-Control: no-store, no-cache, must-revalidate');
@@ -447,8 +447,10 @@ function ms_sso_load_functions(): void {
447447
$code = (string)($_GET['c'] ?? '');
448448
$return = (string)($_GET['return'] ?? '/');
449449

450-
$data = ms_sso_token_parse($code);
450+
$err = null;
451+
$data = ms_sso_token_parse($code, $err);
451452
if (!$data || ($data['mode'] ?? '') !== 'login' || empty($data['sid'])) {
453+
error_log('[sMultisite SSO] RECEIVER login invalid token err=' . ($err ?? 'unknown') . ' host=' . ($_SERVER['HTTP_HOST'] ?? '') . ' sfm=' . ($_SERVER['HTTP_SEC_FETCH_MODE'] ?? ''));
452454
header('HTTP/1.1 400 Bad Request'); echo 'Invalid/expired'; exit;
453455
}
454456

@@ -477,8 +479,10 @@ function ms_sso_load_functions(): void {
477479
$code = (string)($_GET['c'] ?? '');
478480
$return = (string)($_GET['return'] ?? '/');
479481

480-
$data = ms_sso_token_parse($code);
482+
$err = null;
483+
$data = ms_sso_token_parse($code, $err);
481484
if (!$data || ($data['mode'] ?? '') !== 'logout') {
485+
error_log('[sMultisite SSO] RECEIVER logout invalid token err=' . ($err ?? 'unknown') . ' host=' . ($_SERVER['HTTP_HOST'] ?? '') . ' sfm=' . ($_SERVER['HTTP_SEC_FETCH_MODE'] ?? ''));
482486
header('HTTP/1.1 400 Bad Request'); echo 'Invalid/expired'; exit;
483487
}
484488

0 commit comments

Comments
 (0)