Server-backed flow
Register an exact HTTPS callback. On the backend, generate a new random state and PKCE verifier, derive its S256 challenge, and store the transaction in a short-lived server session tied to the browser. Redirect to https://auth.bhauu.online/oauth/authorize with response_type=code and scope=profile email. At callback, validate state and exchange the code once. Include a server-held client secret only if this registered client uses one; the programming language alone does not make it confidential.
session_start();
$verifier = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');
$state = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');
$challenge = rtrim(strtr(base64_encode(hash('sha256', $verifier, true)), '+/', '-_'), '=');
$_SESSION['bhauu_oauth'] = ['state' => $state, 'verifier' => $verifier];
$query = http_build_query(['client_id' => 'YOUR_CLIENT_ID', 'redirect_uri' => 'https://example.com/auth/callback', 'response_type' => 'code', 'scope' => 'profile email', 'state' => $state, 'code_challenge' => $challenge, 'code_challenge_method' => 'S256']);
header('Location: https://auth.bhauu.online/oauth/authorize?' . $query, true, 302);
exit;Callback exchange
session_start();
$pending = $_SESSION['bhauu_oauth'] ?? null;
unset($_SESSION['bhauu_oauth']);
if (!$pending || !hash_equals($pending['state'], (string) ($_GET['state'] ?? '')) || empty($_GET['code'])) { http_response_code(400); exit('Invalid callback'); }
$fields = ['grant_type' => 'authorization_code', 'client_id' => 'YOUR_CLIENT_ID', 'code' => $_GET['code'], 'redirect_uri' => 'https://example.com/auth/callback', 'code_verifier' => $pending['verifier']];
// For a registered confidential client only: $fields['client_secret'] = getenv('BHAUU_CLIENT_SECRET');
$ch = curl_init('https://auth.bhauu.online/oauth/token');
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query($fields), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10]);
$result = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($result === false || $status !== 200) { http_response_code(502); exit('Token exchange failed'); }
$tokens = json_decode($result, true, 512, JSON_THROW_ON_ERROR);Complete application sign-in
Use the returned access token with https://auth.bhauu.online/oauth/userinfo if scoped identity claims are needed. Establish an HttpOnly, Secure, SameSite application-session cookie where suitable, with CSRF protection. Clear the pending state and do not expose tokens to templates or logs. Handle local logout and Bhauu-side revocation separately.