Merge pull request #1926 from useautumn/fix/cli-scopes-3

fix: 🐛 cli auth for the last time
This commit is contained in:
amianthus
2026-06-13 01:13:09 +01:00
committed by GitHub
3 changed files with 52 additions and 4 deletions

View File

@@ -1,5 +1,8 @@
import { LEAF_OAUTH_SCOPES } from "@autumn/shared/leafOAuthScopes";
import { OPENID_SCOPES } from "@autumn/shared/scopeDefinitions";
import {
LEGACY_SCOPE_ALIASES,
OPENID_SCOPES,
} from "@autumn/shared/scopeDefinitions";
const leafScopeSet = new Set<string>(LEAF_OAUTH_SCOPES);
const oauthPassthroughScopeSet = new Set<string>(["offline_access"]);
@@ -11,8 +14,12 @@ export const getDefaultOAuthScopes = (requestedScopes?: string[] | null) => {
? requestedScopes
: [...LEAF_OAUTH_SCOPES, ...oauthPassthroughScopeSet];
// Issued scopes must echo the client's request verbatim (better-auth
// rejects rewrites), so legacy CRUDL aliases are used for filtering only.
return [...new Set(requested)].filter(
(scope) => leafScopeSet.has(scope) || oauthPassthroughScopeSet.has(scope),
(scope) =>
leafScopeSet.has(LEGACY_SCOPE_ALIASES[scope] ?? scope) ||
oauthPassthroughScopeSet.has(scope),
);
};

View File

@@ -1,4 +1,10 @@
import { AppEnv, ErrCode, RecaseError, Scopes } from "@autumn/shared";
import {
AppEnv,
ErrCode,
LEGACY_SCOPE_ALIASES,
RecaseError,
Scopes,
} from "@autumn/shared";
import { createRoute } from "@/honoMiddlewares/routeHandler.js";
import { isMcpOAuthClientId } from "@/internal/auth/oauth/mcpOAuthScopes.js";
import {
@@ -84,7 +90,15 @@ export const handleCreateOAuthApiKeys = createRoute({
statusCode: 401,
});
}
const apiKeyScopes = requestedScopes ?? tokenRecord.scopes;
// Tokens may carry legacy CRUDL scopes (old CLI); store modern R/W on keys.
const apiKeyScopes = [
...new Set(
(requestedScopes ?? tokenRecord.scopes).map(
(scope) => LEGACY_SCOPE_ALIASES[scope] ?? scope,
),
),
];
if (await isMcpOAuthClientId({ clientId, ctx })) {
throw new RecaseError({
message: "MCP OAuth clients must use OAuth access tokens directly",

View File

@@ -64,6 +64,33 @@ describe("getRequestedScopesForMcpClient", () => {
]);
});
test("keeps legacy CRUDL scopes (old CLI) whose alias is leaf-allowed, verbatim", () => {
expect(
getDefaultOAuthScopes([
"customers:create",
"customers:read",
"customers:list",
"customers:update",
"customers:delete",
"features:create",
"features:read",
"plans:update",
"apiKeys:create",
"organisation:read",
]),
).toEqual([
"customers:create",
"customers:read",
"customers:list",
"customers:update",
"customers:delete",
"features:create",
"features:read",
"plans:update",
"organisation:read",
]);
});
test("strips OAuth protocol scopes from resource scopes", () => {
expect(
getOAuthResourceScopes([