ALPID_CLIENT_ID, 'response_type' => 'code', 'scope' => 'openid profile email', 'redirect_uri' => CALLBACK_URL, 'state' => $state, 'nonce' => $nonce, ]); } function oidc_exchange_code(string $code): array { $ch = curl_init(ALPID_TOKEN_URL); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query([ 'grant_type' => 'authorization_code', 'code' => $code, 'redirect_uri' => CALLBACK_URL, 'client_id' => ALPID_CLIENT_ID, 'client_secret' => ALPID_CLIENT_SECRET, ]), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, ]); $body = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($status !== 200) { throw new RuntimeException("Erreur token OIDC ($status) : $body"); } return json_decode($body, true); } function oidc_userinfo(string $access_token): array { $ch = curl_init(ALPID_USERINFO_URL); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ["Authorization: Bearer $access_token"], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, ]); $body = curl_exec($ch); curl_close($ch); return json_decode($body, true) ?? []; } function oidc_logout_url(string $id_token = ''): string { $params = ['post_logout_redirect_uri' => APP_URL . '/']; if ($id_token) { $params['id_token_hint'] = $id_token; } return ALPID_LOGOUT_URL . '?' . http_build_query($params); }