Files
9router/tests/unit/cline-auth.test.js
izzzzzi f6e7cabe60 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.
2026-09-10 22:48:22 +07:00

40 lines
1.5 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import {
getClineAccessToken,
getClineAuthorizationHeader,
} from "../../open-sse/shared/clineAuth.js";
test("getClineAccessToken keeps an existing workos: prefix", () => {
const token = "workos:eyJhbGciOiJSUzI1NiJ9.eyJwYXAiJ9";
assert.equal(getClineAccessToken(token), token);
assert.equal(getClineAccessToken(` ${token} `), token);
});
test("getClineAccessToken prefixes a bare WorkOS JWT with workos:", () => {
const jwt = "eyJhbGciOiJSUzI1NiJ9.eyJwYXAiJ9";
assert.equal(getClineAccessToken(jwt), `workos:${jwt}`);
});
test("getClineAccessToken does NOT prefix ClinePass API keys", () => {
// ClinePass API keys are opaque strings (e.g. clp_…). Sending them as
// `workos:clp_…` makes api.cline.bot respond 401.
assert.equal(getClineAccessToken("clp_1234567890abcdef"), "clp_1234567890abcdef");
assert.equal(getClineAccessToken("sk-9r-abcdef"), "sk-9r-abcdef");
assert.equal(getClineAccessToken(""), "");
assert.equal(getClineAccessToken(" "), "");
assert.equal(getClineAccessToken(undefined), "");
assert.equal(getClineAccessToken(null), "");
});
test("getClineAuthorizationHeader builds a Bearer header without double prefixing", () => {
assert.equal(getClineAuthorizationHeader("clp_abc"), "Bearer clp_abc");
assert.equal(
getClineAuthorizationHeader("eyJpeg.eyJbG"),
"Bearer workos:eyJpeg.eyJbG"
);
assert.equal(
getClineAuthorizationHeader("workos:eyJpeg.eyJbG"),
"Bearer workos:eyJpeg.eyJbG"
);
});