From e344e52d709f662bcb46595bdab4ddb20454ea1b Mon Sep 17 00:00:00 2001 From: Myron Blair Date: Fri, 29 May 2026 15:13:38 +0000 Subject: [PATCH] Add Google OAuth admin login; fix header comment; both auth methods active --- admin/auth/google/callback.php | 109 +++++++++++++++++++++++++++++++++ admin/auth/google/login.php | 30 +++++++++ admin/includes/header.php | 4 +- admin/login.php | 27 +++++++- 4 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 admin/auth/google/callback.php create mode 100644 admin/auth/google/login.php diff --git a/admin/auth/google/callback.php b/admin/auth/google/callback.php new file mode 100644 index 0000000..1160ef9 --- /dev/null +++ b/admin/auth/google/callback.php @@ -0,0 +1,109 @@ + [ + 'method' => 'POST', + 'header' => 'Content-Type: application/x-www-form-urlencoded', + 'content' => http_build_query([ + 'code' => $_GET['code'], + 'client_id' => GOOGLE_CLIENT_ID, + 'client_secret' => GOOGLE_CLIENT_SECRET, + 'redirect_uri' => GOOGLE_REDIRECT_URI, + 'grant_type' => 'authorization_code', + ]), + 'timeout' => 15, + ], +])), true); + +if (empty($tokenResp['access_token'])) { + error_log('[Google OAuth] token exchange failed: ' . json_encode($tokenResp)); + googleOAuthError('Failed to complete Google sign-in. Please try again.'); +} + +// Fetch Google user info +$userInfo = json_decode(file_get_contents('https://www.googleapis.com/oauth2/v3/userinfo', false, stream_context_create([ + 'http' => [ + 'method' => 'GET', + 'header' => 'Authorization: Bearer ' . $tokenResp['access_token'], + 'timeout' => 10, + ], +])), true); + +if (empty($userInfo['email'])) { + googleOAuthError('Could not retrieve email from Google. Please try again.'); +} + +$googleEmail = strtolower($userInfo['email']); + +// Look up admin by email +$admin = db()->fetch( + "SELECT * FROM admin_users WHERE email = :email", + ['email' => $googleEmail] +); + +if (!$admin) { + error_log('[Google OAuth] login attempt by non-admin: ' . $googleEmail); + googleOAuthError('No admin account found for ' . htmlspecialchars($googleEmail) . '. Contact the site administrator.'); +} + +// Store google_id on first Google login +if (empty($admin['google_id'])) { + try { + db()->query( + "UPDATE admin_users SET google_id = :gid, last_login = NOW() WHERE user_id = :id", + ['gid' => $userInfo['sub'], 'id' => $admin['user_id']] + ); + } catch (Exception $e) { + // google_id column may not exist yet — update last_login only + db()->query( + "UPDATE admin_users SET last_login = NOW() WHERE user_id = :id", + ['id' => $admin['user_id']] + ); + } +} else { + db()->query( + "UPDATE admin_users SET last_login = NOW() WHERE user_id = :id", + ['id' => $admin['user_id']] + ); +} + +// Create session +$_SESSION['admin'] = [ + 'user_id' => $admin['user_id'], + 'email' => $admin['email'], + 'name' => $admin['name'], + 'is_master' => (bool)$admin['is_master'], + 'permissions' => json_decode($admin['permissions'] ?? '[]', true), + 'auth_method' => 'google', +]; +session_regenerate_id(true); + +$redirect = $_SESSION['admin_redirect'] ?? '/admin/'; +unset($_SESSION['admin_redirect']); +header('Location: ' . $redirect); +exit; diff --git a/admin/auth/google/login.php b/admin/auth/google/login.php new file mode 100644 index 0000000..5d0cf8e --- /dev/null +++ b/admin/auth/google/login.php @@ -0,0 +1,30 @@ + GOOGLE_CLIENT_ID, + 'redirect_uri' => GOOGLE_REDIRECT_URI, + 'response_type' => 'code', + 'scope' => 'openid email profile', + 'state' => $state, + 'access_type' => 'online', + 'prompt' => 'select_account', +]); + +header('Location: https://accounts.google.com/o/oauth2/v2/auth?' . $params); +exit; diff --git a/admin/includes/header.php b/admin/includes/header.php index 003b228..d956bd8 100644 --- a/admin/includes/header.php +++ b/admin/includes/header.php @@ -1,7 +1,7 @@ "> Email Campaigns + Email Log +
+ + + + + + + + + + Sign in with Google + +
or sign in with email
+ +