mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
Address CodeRabbit: harden InsufficientScope deserialization, type-only Scope import, explicit null check, snapshot test assertions
Co-Authored-By: mantra <mantra@stack-auth.com>
This commit is contained in:
parent
f18255b6fa
commit
797a5f4dd5
@ -443,7 +443,9 @@ export async function createRefreshTokenObj(options: CreateRefreshTokenOptions)
|
||||
|
||||
const refreshToken = generateSecureRandomString();
|
||||
|
||||
const scopes = options.scopes ? [...new Set(options.scopes)] : [];
|
||||
// Dedupe so the persisted scope string never carries duplicates (the registry intersection at
|
||||
// grant time already constrains the set, this just normalizes it).
|
||||
const scopes = options.scopes != null ? [...new Set(options.scopes)] : [];
|
||||
|
||||
const refreshTokenObj = await globalPrismaClient.projectUserRefreshToken.create({
|
||||
data: {
|
||||
|
||||
@ -79,7 +79,19 @@ it("treats unrestricted (no-scope) sessions as unrestricted for scoped endpoints
|
||||
body: { display_name: "Unrestricted Test Team" },
|
||||
userAuth: { accessToken },
|
||||
});
|
||||
expect(createRes.body.code).not.toBe("INSUFFICIENT_SCOPE");
|
||||
expect(createRes).toMatchInlineSnapshot(`
|
||||
NiceResponse {
|
||||
"status": 201,
|
||||
"body": {
|
||||
"client_metadata": null,
|
||||
"client_read_only_metadata": null,
|
||||
"display_name": "Unrestricted Test Team",
|
||||
"id": "<stripped UUID>",
|
||||
"profile_image_url": null,
|
||||
},
|
||||
"headers": Headers { <some fields may have been hidden> },
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it("persists scopes across a token refresh", async ({ expect }) => {
|
||||
@ -106,8 +118,20 @@ it("persists scopes across a token refresh", async ({ expect }) => {
|
||||
body: { display_name: "Refreshed Scoped Team" },
|
||||
userAuth: { accessToken: refreshedAccessToken },
|
||||
});
|
||||
expect(createRes.status).toBe(403);
|
||||
expect(createRes.body.code).toBe("INSUFFICIENT_SCOPE");
|
||||
expect(createRes).toMatchInlineSnapshot(`
|
||||
NiceResponse {
|
||||
"status": 403,
|
||||
"body": {
|
||||
"code": "INSUFFICIENT_SCOPE",
|
||||
"details": { "missing_scopes": ["teams:write"] },
|
||||
"error": "The access token is missing the following required scope(s): 'teams:write'. Mint a token that includes these scopes and try again.",
|
||||
},
|
||||
"headers": Headers {
|
||||
"x-stack-known-error": "INSUFFICIENT_SCOPE",
|
||||
<some fields may have been hidden>,
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it("rejects creating a session with an unknown scope", async ({ expect }) => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import * as yup from 'yup';
|
||||
import { yupObject, yupString } from './schema-fields';
|
||||
import { Scope } from './scopes';
|
||||
import type { Scope } from './scopes';
|
||||
import { filterUndefined } from './utils/objects';
|
||||
import { NullishCoalesce } from './utils/types';
|
||||
|
||||
|
||||
@ -1389,7 +1389,11 @@ const InsufficientScope = createKnownErrorConstructor(
|
||||
missing_scopes: missingScopes,
|
||||
},
|
||||
] as const,
|
||||
(json: any) => [json.missing_scopes] as const,
|
||||
(json: any) => [
|
||||
Array.isArray(json?.missing_scopes)
|
||||
? json.missing_scopes
|
||||
: throwErr("missing_scopes not found (or not an array) in InsufficientScope details"),
|
||||
] as const,
|
||||
);
|
||||
|
||||
const InvalidSharedOAuthProviderId = createKnownErrorConstructor(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user