$_GET['response_type'] ?? '', 'client_id' => $_GET['client_id'] ?? '', 'redirect_uri' => $_GET['redirect_uri'] ?? '', 'scope' => $_GET['scope'] ?? '', 'state' => $_GET['state'] ?? '', ]; $responseType = $requestParams['response_type']; $clientId = trim($requestParams['client_id']); $redirectUri = trim($requestParams['redirect_uri']); $scope = trim($requestParams['scope']); $state = $requestParams['state']; function oauth_bad_request(string $message): void { http_response_code(400); header('Content-Type: application/json'); echo json_encode(['error' => 'invalid_request', 'error_description' => $message], JSON_UNESCAPED_SLASHES); exit(); } function oauth_redirect_with_error(string $redirectUri, string $error, ?string $description = null, ?string $state = null): void { $fragment = ''; if (($hashPos = strpos($redirectUri, '#')) !== false) { $fragment = substr($redirectUri, $hashPos); $redirectUri = substr($redirectUri, 0, $hashPos); } $separator = (strpos($redirectUri, '?') === false) ? '?' : '&'; $payload = ['error' => $error]; if ($description) { $payload['error_description'] = $description; } if ($state !== null && $state !== '') { $payload['state'] = $state; } $location = $redirectUri . $separator . http_build_query($payload) . $fragment; header('Location: ' . $location); exit(); } function oauth_redirect_with_params(string $redirectUri, array $params): void { $fragment = ''; if (($hashPos = strpos($redirectUri, '#')) !== false) { $fragment = substr($redirectUri, $hashPos); $redirectUri = substr($redirectUri, 0, $hashPos); } $separator = (strpos($redirectUri, '?') === false) ? '?' : '&'; $location = $redirectUri . $separator . http_build_query($params) . $fragment; header('Location: ' . $location); exit(); } if ($responseType !== 'code') { oauth_bad_request('Unsupported response_type. Only "code" is supported.'); } if ($clientId === '' || $redirectUri === '') { oauth_bad_request('Missing client_id or redirect_uri.'); } if (!is_logged_in()) { $_SESSION['oauth_pending_request'] = [ 'params' => $requestParams, 'created_at' => time(), ]; set_message("Please login to continue with the requested integration.", "warning"); header('Location: ../index.php'); exit(); } if (!isset($_SESSION['person_id']) || (int) $_SESSION['person_id'] <= 0) { oauth_bad_request('Your session is missing required profile information.'); } $oauthService = new OAuthService($pdo); $client = $oauthService->getClient($clientId); if (!$client) { oauth_bad_request('Unknown or revoked client.'); } if (!$oauthService->isRedirectUriAllowed($client, $redirectUri)) { oauth_bad_request('The provided redirect_uri is not registered for this client.'); } if (!$oauthService->isScopeAllowed($client, $scope)) { oauth_redirect_with_error($redirectUri, 'invalid_scope', 'Requested scope is not permitted.', $state); } $codeData = $oauthService->issueAuthorizationCode( $clientId, (int) $_SESSION['person_id'], $redirectUri, $scope !== '' ? $scope : null ); $payload = ['code' => $codeData['code']]; if ($state !== '') { $payload['state'] = $state; } oauth_redirect_with_params($redirectUri, $payload);