fix(cline): stop workos:-prefixing ClinePass API keys and add clinepass token refresh
Cline/ClinePass requests failed with HTTP 401 ("Please make sure you are using
the latest version of Cline and re-authenticate your Cline account", #3230 /
#2333 / #3644). `getClineAccessToken()` unconditionally prefixed every token
with `workos:`, which is correct for Cline OAuth access tokens (WorkOS JWTs)
but wrong for ClinePass API keys — those are opaque strings (e.g. `clp_…`)
that the API accepts only verbatim, so the `workos:`-prefixed value was
rejected.
Only prefix tokens that look like a WorkOS JWT (`eyJ…`); API keys and other
opaque tokens pass through untouched, and an existing `workos:` prefix is
never doubled.
Also register `clinepass` in the token-refresh handlers. ClinePass shares
Cline's WorkOS auth endpoints, but without the entry expired ClinePass OAuth
tokens were never rotated, so every request kept 401ing. Finally, list
`apikey` first in the ClinePass `authModes` (ClinePass is meant to be used
with an API key from app.cline.bot/settings/api-keys), and add an "Import
from /models" button that pulls the live Cline catalog into custom models.
This commit is contained in:
@@ -14,7 +14,10 @@ export default {
|
||||
},
|
||||
},
|
||||
category: "oauth",
|
||||
authModes: ["oauth", "apikey"],
|
||||
// ClinePass authenticates with a plain API key from app.cline.bot/settings/api-keys
|
||||
// (category "apikey"). The OAuth extension flow used by Cline does not issue
|
||||
// tokens that the ClinePass API consumer endpoint accepts (HTTP 401) — see #2333.
|
||||
authModes: ["apikey", "oauth"],
|
||||
hasOAuth: true,
|
||||
transport: {
|
||||
baseUrl: "https://api.cline.bot/api/v1/chat/completions",
|
||||
|
||||
@@ -148,6 +148,8 @@ const REFRESH_HANDLERS = {
|
||||
"codebuddy-intl": (c, log) => refreshCodebuddyIntlToken(c.refreshToken, log),
|
||||
trae: (c, log) => refreshTraeToken(c.refreshToken, c, log),
|
||||
cline: (c, log) => refreshClineToken(c.refreshToken, log),
|
||||
// ClinePass shares Cline's WorkOS auth endpoints, so the same refresh works.
|
||||
clinepass: (c, log) => refreshClineToken(c.refreshToken, log),
|
||||
zed: () => refreshZedToken(),
|
||||
windsurf: (c, log) => refreshWindsurfToken(c, log),
|
||||
// Kimi Code OAuth (merged into id `kimi`); legacy id still routes here
|
||||
|
||||
@@ -6,7 +6,14 @@ export function getClineAccessToken(token) {
|
||||
if (typeof token !== "string") return "";
|
||||
const trimmed = token.trim();
|
||||
if (!trimmed) return "";
|
||||
return trimmed.startsWith("workos:") ? trimmed : `workos:${trimmed}`;
|
||||
if (trimmed.toLowerCase().startsWith("workos:")) return trimmed;
|
||||
// Cline OAuth access tokens are WorkOS JWTs (base64url `eyJ…` header).
|
||||
// ClinePass API keys (category "apikey", e.g. `clp_…`) are NOT JWTs and must
|
||||
// be sent verbatim — prefixing them with `workos:` makes the Cline API reject
|
||||
// the request with HTTP 401 ("Please make sure you're using the latest
|
||||
// version of Cline and re-authenticate your Cline account.").
|
||||
const isWorkOsJwt = /^eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/.test(trimmed);
|
||||
return isWorkOsJwt ? `workos:${trimmed}` : trimmed;
|
||||
}
|
||||
|
||||
export function getClineAuthorizationHeader(token) {
|
||||
|
||||
Reference in New Issue
Block a user