1
0
mirror of git://f0xx.org/ac/ac-ms-identity synced 2026-07-30 02:37:39 +03:00

fix(2fa): QR approve uses request host and one-tap link token

Build approval URLs from the browser Host header (apps.f0xx.org not acl0); allow approve by QR token without a second TOTP on mobile.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Anton Afanasyeu
2026-07-11 17:33:42 +02:00
parent 002e9cb710
commit 3c4e79ecfa
3 changed files with 30 additions and 2 deletions

View File

@@ -227,6 +227,23 @@ final class Auth {
return (string) ($_SERVER['REMOTE_ADDR'] ?? '0.0.0.0');
}
/** Origin for outbound links (QR, email) — matches the host the user is browsing. */
public static function requestPublicOrigin(): string {
$host = trim(explode(',', (string) ($_SERVER['HTTP_X_FORWARDED_HOST'] ?? $_SERVER['HTTP_HOST'] ?? ''))[0]);
$host = preg_replace('/:\d+$/', '', $host);
if ($host !== '' && !in_array($host, ['127.0.0.1', 'localhost'], true)) {
$scheme = 'http';
if (function_exists('platform_is_https_request') && platform_is_https_request()) {
$scheme = 'https';
} elseif (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
$scheme = 'https';
}
return $scheme . '://' . $host;
}
$cfg = rtrim((string) cfg('public_origin', ''), '/');
return $cfg !== '' ? $cfg : 'https://apps.f0xx.org';
}
public static function logout(): void {
self::clearPending2fa();
unset($_SESSION['user']);

View File

@@ -131,7 +131,18 @@ final class AuthApproval {
}
/**
* Approve using TOTP (mobile not logged in — scan QR, enter authenticator code).
* One-tap approve from QR / magic link (token is the credential).
*/
public static function approveByLinkToken(string $rawToken, string $approverIp): bool {
$info = self::getForToken($rawToken);
if ($info === null) {
return false;
}
return self::approve($rawToken, (int) ($info['user_id'] ?? 0), $approverIp);
}
/**
* Approve using TOTP (optional fallback when link alone is not enough).
*/
public static function approveWithTotp(string $rawToken, string $code, string $approverIp): bool {
$info = self::getForToken($rawToken);

View File

@@ -29,7 +29,7 @@ final class AuthTwoFactorPage {
$_SESSION['pending_2fa_approval_token'] = $rawToken;
}
$origin = rtrim((string) cfg('public_origin', 'https://apps.f0xx.org'), '/');
$origin = Auth::requestPublicOrigin();
$approveUrl = $origin . $project . '/two-factor/approve?token=' . urlencode($rawToken);
$payload = [