Google OAuth 2.0 Single Sign-On

A Zero-Dependency SSO Flow

To offer modern Single-Sign-On without a vendor SDK, GoogleAuthController (inside src/Modules/Admin/Controllers/GoogleAuthController.php) implements the OAuth 2.0 authorization-code flow using raw PHP cURL calls. Before redirecting to Google's authorization page, a random state token is stored in $_SESSION['_csrf_token'] via Security::csrfToken(); Google echoes it back in the callback's state parameter, and the callback verifies it with Security::csrfVerify() before proceeding, mitigating CSRF hijacking of the login flow.

Exchanging the Authorization Code

Exchanging the Authorization Code php
$ch = curl_init('https://oauth2.googleapis.com/token');
// POST payload: client_id, client_secret, redirect_uri, code
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$tokenResponse = json_decode(curl_exec($ch), true);

// Then fetch the verified profile email with the access token:
// GET https://www.googleapis.com/oauth2/v3/userinfo(Authorization: Bearer ...)

Multi-Tenant Scoping on Login

Once the Google account's email is resolved, the matching users row is looked up. To prevent an OAuth login from crossing tenant boundaries, the resolved user must either be a global super_admin, or their site_id must match App::getCurrentSiteId() for the domain being logged into. Failing this check redirects back to the login page with an isolation-mismatch warning instead of granting a session.