From 28c7e0d62f80da39e8df82da2261875c7af5384c Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Sat, 21 Feb 2026 18:24:56 -0300 Subject: [PATCH] Fix OAuth client_secret issues (#103) & Codex Business quotas (#101) --- open-sse/services/usage.ts | 40 +++++++++++++++++-- .../usage/components/ProviderLimits/utils.tsx | 7 +++- src/lib/oauth/providers/antigravity.ts | 19 +++++---- src/lib/oauth/providers/gemini.ts | 19 +++++---- src/lib/oauth/providers/iflow.ts | 35 ++++++++++------ 5 files changed, 88 insertions(+), 32 deletions(-) diff --git a/open-sse/services/usage.ts b/open-sse/services/usage.ts index 0878f10c50..406d0f7192 100644 --- a/open-sse/services/usage.ts +++ b/open-sse/services/usage.ts @@ -486,12 +486,44 @@ async function getClaudeUsage(accessToken) { */ async function getCodexUsage(accessToken) { try { + let accountId = null; + try { + const accountsRes = await fetch("https://chatgpt.com/backend-api/accounts/check/v4", { + method: "GET", + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json", + }, + }); + if (accountsRes.ok) { + const accountsData = await accountsRes.json(); + if (accountsData.accounts) { + const accountsArray = Object.values(accountsData.accounts) as any[]; + const targetWorkspace = + accountsArray.find((a) => a.account?.plan_type === "biz") || + accountsArray.find((a) => a.account?.plan_type !== "free") || + accountsArray.find((a) => a.is_default) || + accountsArray[0]; + if (targetWorkspace && targetWorkspace.account?.id) { + accountId = targetWorkspace.account.id; + } + } + } + } catch (err) { + console.warn("Could not fetch ChatGPT accounts for quota:", err); + } + + const headers: Record = { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json", + }; + if (accountId) { + headers["chatgpt-account-id"] = accountId; + } + const response = await fetch(CODEX_CONFIG.usageUrl, { method: "GET", - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json", - }, + headers, }); if (!response.ok) { diff --git a/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx b/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx index fb8fc9f623..515dc9cc1f 100644 --- a/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx +++ b/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx @@ -216,7 +216,12 @@ export function normalizePlanTier(plan) { return { key: "enterprise", label: "Enterprise", variant: "info", rank: 6, raw }; } - if (upper.includes("BUSINESS") || upper.includes("TEAM") || upper.includes("STANDARD")) { + if ( + upper.includes("BUSINESS") || + upper.includes("TEAM") || + upper.includes("STANDARD") || + upper.includes("BIZ") + ) { return { key: "business", label: "Business", variant: "warning", rank: 5, raw }; } diff --git a/src/lib/oauth/providers/antigravity.ts b/src/lib/oauth/providers/antigravity.ts index 1ea71a45f0..0349679799 100644 --- a/src/lib/oauth/providers/antigravity.ts +++ b/src/lib/oauth/providers/antigravity.ts @@ -16,19 +16,24 @@ export const antigravity = { return `${config.authorizeUrl}?${params.toString()}`; }, exchangeToken: async (config, code, redirectUri) => { + const bodyParams: Record = { + grant_type: "authorization_code", + client_id: config.clientId, + code: code, + redirect_uri: redirectUri, + }; + + if (config.clientSecret) { + bodyParams.client_secret = config.clientSecret; + } + const response = await fetch(config.tokenUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", Accept: "application/json", }, - body: new URLSearchParams({ - grant_type: "authorization_code", - client_id: config.clientId, - client_secret: config.clientSecret, - code: code, - redirect_uri: redirectUri, - }), + body: new URLSearchParams(bodyParams), }); if (!response.ok) { diff --git a/src/lib/oauth/providers/gemini.ts b/src/lib/oauth/providers/gemini.ts index 0f04c8137e..a14a9b87dd 100644 --- a/src/lib/oauth/providers/gemini.ts +++ b/src/lib/oauth/providers/gemini.ts @@ -16,19 +16,24 @@ export const gemini = { return `${config.authorizeUrl}?${params.toString()}`; }, exchangeToken: async (config, code, redirectUri) => { + const bodyParams: Record = { + grant_type: "authorization_code", + client_id: config.clientId, + code: code, + redirect_uri: redirectUri, + }; + + if (config.clientSecret) { + bodyParams.client_secret = config.clientSecret; + } + const response = await fetch(config.tokenUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", Accept: "application/json", }, - body: new URLSearchParams({ - grant_type: "authorization_code", - client_id: config.clientId, - client_secret: config.clientSecret, - code: code, - redirect_uri: redirectUri, - }), + body: new URLSearchParams(bodyParams), }); if (!response.ok) { diff --git a/src/lib/oauth/providers/iflow.ts b/src/lib/oauth/providers/iflow.ts index 6699841a52..f496eada6e 100644 --- a/src/lib/oauth/providers/iflow.ts +++ b/src/lib/oauth/providers/iflow.ts @@ -14,22 +14,31 @@ export const iflow = { return `${config.authorizeUrl}?${params.toString()}`; }, exchangeToken: async (config, code, redirectUri) => { - const basicAuth = Buffer.from(`${config.clientId}:${config.clientSecret}`).toString("base64"); + const headers: Record = { + "Content-Type": "application/x-www-form-urlencoded", + Accept: "application/json", + }; + + if (config.clientSecret) { + const basicAuth = Buffer.from(`${config.clientId}:${config.clientSecret}`).toString("base64"); + headers.Authorization = `Basic ${basicAuth}`; + } + + const bodyParams: Record = { + grant_type: "authorization_code", + code: code, + redirect_uri: redirectUri, + client_id: config.clientId, + }; + + if (config.clientSecret) { + bodyParams.client_secret = config.clientSecret; + } const response = await fetch(config.tokenUrl, { method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - Accept: "application/json", - Authorization: `Basic ${basicAuth}`, - }, - body: new URLSearchParams({ - grant_type: "authorization_code", - code: code, - redirect_uri: redirectUri, - client_id: config.clientId, - client_secret: config.clientSecret, - }), + headers: headers, + body: new URLSearchParams(bodyParams), }); if (!response.ok) {