-
Notifications
You must be signed in to change notification settings - Fork 366
chore(backend,nextjs): Refactor unauthenticated auth object fallback to respect intent #6112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🦋 Changeset detectedLatest commit: e672cd3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Skipped Deployment
|
Warning Rate limit exceeded@wobsoriano has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 12 minutes and 6 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
📝 Walkthrough## Walkthrough
The changes refactor machine token handling by replacing `isMachineToken` with `isMachineTokenByPrefix` and introducing `isMachineTokenType`. Related exports and imports are updated throughout the backend and Next.js packages. Authentication logic and tests are revised to reflect these changes, with improved handling of accepted token types and expanded test coverage.
## Changes
| Files/Groups | Change Summary |
|------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `packages/backend/src/internal.ts`, `packages/backend/src/__tests__/exports.test.ts` | Updated exports: replaced `isMachineToken` with `isMachineTokenByPrefix` and `isMachineTokenType`. Adjusted tests to reflect new exports. |
| `packages/backend/src/tokens/machine.ts`, `packages/backend/src/tokens/__tests__/machine.test.ts` | Renamed `isMachineToken` to `isMachineTokenByPrefix`. Added new function `isMachineTokenType` and corresponding tests. Updated imports and test usage to match new function names. |
| `packages/backend/src/tokens/authObjects.ts`, `packages/backend/src/tokens/__tests__/authObjects.test.ts` | Refactored `getAuthObjectForAcceptedToken` for clearer handling of accepted token types, distinguishing between array and single-value cases. Added `isAuthenticated` property to auth object types. Added new `InvalidTokenAuthObject` type and factory. Updated and expanded related tests for new logic. |
| `packages/backend/src/tokens/request.ts` | Replaced usage of `isMachineToken` with `isMachineTokenByPrefix` in authentication logic. No changes to public exports. |
| `packages/nextjs/src/server/data/getAuthDataFromRequest.ts` | Refactored `getAuthDataFromRequestAsync` to use new helpers for machine token handling and intent-based logic. Improved handling of token type acceptance. No changes to public exports. |
| `packages/nextjs/src/server/clerkMiddleware.ts` | Updated import and usage from `isMachineToken` to `isMachineTokenByPrefix` in middleware logic. No changes to public exports. |
| `packages/nextjs/src/server/__tests__/getAuthDataFromRequest.test.ts` | Added tests for new token type acceptance scenarios and updated type assertions in existing tests. |
| `packages/express/src/__tests__/getAuth.test.ts`, `packages/fastify/src/__tests__/getAuth.test.ts` | Updated tests to expect the accepted token type instead of the actual token type in unauthenticated auth objects when token types do not match. |
| `packages/backend/src/index.ts`, `packages/backend/src/tokens/types.ts`, `packages/nextjs/src/app-router/server/auth.ts` | Updated exports and type signatures to include `InvalidTokenAuthObject` in public API and authentication function return types. |
| `packages/nextjs/src/server/protect.ts` | Added explicit check to handle `null` tokenType by calling `handleUnauthorized()` early in `createProtect`. |
| `.changeset/open-swans-count.md` | Added patch update note describing changes to respect `acceptsToken` flag in unauthenticated session or machine object returns. |
## Suggested labels
`nextjs`, `backend`
## Suggested reviewers
- panteliselef
- tmilewski ✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
@clerk/agent-toolkit
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/dev-cli
@clerk/elements
@clerk/clerk-expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/clerk-react
@clerk/react-router
@clerk/remix
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/themes
@clerk/types
@clerk/upgrade
@clerk/vue
commit: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🔭 Outside diff range comments (1)
packages/backend/src/tokens/request.ts (1)
656-663
:⚠️ Potential issue
acceptsToken
may be an array – leads to wrongtokenType
in signed-out state
acceptsToken
is cast toMachineTokenType
, but when the caller supplied an array (e.g.['api_key','machine_token']
) this branch is still reached andsignedOut()
will receive an array instead of a string, violating the expected contract and potentially blowing up downstream logic that pattern-matches ontokenType
.- return signedOut({ - tokenType: acceptsToken as MachineTokenType, + const fallbackTokenType = + Array.isArray(acceptsToken) ? TokenType.MachineToken : (acceptsToken as MachineTokenType); + return signedOut({ + tokenType: fallbackTokenType,At minimum guard with
Array.isArray
, or refactor the control-flow earlier so thatauthenticateMachineRequestWithTokenInHeader
is never called whenacceptsToken
is an array.
🧹 Nitpick comments (14)
packages/nextjs/src/server/clerkMiddleware.ts (1)
286-297
: Minor: make “Bearer ” stripping case-insensitive
replace('Bearer ', '')
misses the common lowercase form (bearer
) and variants with extra spacing, which would causeisMachineTokenByPrefix
to receive an untrimmed string and returnfalse
.-const authHeader = getHeader(request, constants.Headers.Authorization)?.replace('Bearer ', '') ?? ''; +const authHeader = + getHeader(request, constants.Headers.Authorization) + // Strip the bearer scheme in a case-insensitive way and any leading spaces + ?.replace(/^Bearer\s+/i, '') ?? '';packages/backend/src/tokens/request.ts (1)
691-709
: (optional) avoid duplicate prefix scanning
isMachineTokenByPrefix
is executed, and on the success pathgetMachineTokenType
scans the prefixes again. Caching the mapping (prefix → type) removes the extra work and keeps the two helpers in sync.packages/backend/src/tokens/machine.ts (2)
21-23
: Unify prefix → type logic & avoid double iterationBoth
isMachineTokenByPrefix
andgetMachineTokenType
perform separate prefix scans.
Creating one canonical lookup avoids divergence and improves perf (especially if custom prefixes grow).-const MACHINE_TOKEN_PREFIXES = [M2M_TOKEN_PREFIX, OAUTH_TOKEN_PREFIX, API_KEY_PREFIX] as const; +const PREFIX_TO_TYPE: Record<string, MachineTokenType> = { + [M2M_TOKEN_PREFIX]: TokenType.MachineToken, + [OAUTH_TOKEN_PREFIX]: TokenType.OAuthToken, + [API_KEY_PREFIX]: TokenType.ApiKey, +} as const; + +const MACHINE_TOKEN_PREFIXES = Object.keys(PREFIX_TO_TYPE); export function isMachineTokenByPrefix(token: string): boolean { - return MACHINE_TOKEN_PREFIXES.some(prefix => token.startsWith(prefix)); + return MACHINE_TOKEN_PREFIXES.some(prefix => token.startsWith(prefix)); } export function getMachineTokenType(token: string): MachineTokenType { - if (token.startsWith(M2M_TOKEN_PREFIX)) { - return TokenType.MachineToken; - } - ... - throw new Error('Unknown machine token type'); + for (const [prefix, type] of Object.entries(PREFIX_TO_TYPE)) { + if (token.startsWith(prefix)) { + return type; + } + } + throw new Error('Unknown machine token type'); }Also applies to: 36-50, 71-79
77-79
: Nit: rename parameter for clarityUsing the identifier
type
for the function parameter shadows its semantic meaning.tokenType
is more explicit and avoids confusion.-export function isMachineTokenType(type: string): type is MachineTokenType { - return type === TokenType.ApiKey || type === TokenType.MachineToken || type === TokenType.OAuthToken; +export function isMachineTokenType(tokenType: string): tokenType is MachineTokenType { + return ( + tokenType === TokenType.ApiKey || + tokenType === TokenType.MachineToken || + tokenType === TokenType.OAuthToken + ); }packages/backend/src/tokens/__tests__/machine.test.ts (2)
13-13
: Rename describe block to match the renamed helper.The suite is still titled
isMachineToken
, but the implementation under test is nowisMachineTokenByPrefix
.
Keeping the names in sync avoids confusion when reading test output.-describe('isMachineToken', () => { +describe('isMachineTokenByPrefix', () => {
82-93
: Broaden negative-case coverage forisMachineTokenType
.Consider adding non-machine strings with similar shapes (
'api_Key'
,'API_KEY'
, etc.) to ensure the predicate remains case- and value-sensitive.it('returns false for non-machine token types', () => { expect(isMachineTokenType('session_token')).toBe(false); + expect(isMachineTokenType('api_Key')).toBe(false); // mixed case + expect(isMachineTokenType('API_KEY')).toBe(false); // upper case });packages/nextjs/src/server/__tests__/getAuthDataFromRequest.test.ts (3)
45-47
: Use the correct unauthenticated type in assertions.
auth
is expected to be unauthenticated, but the cast usesAuthenticatedMachineObject
.
Switching toUnauthenticatedMachineObject
prevents accidental misuse of authenticated-only members in future edits.- expect((auth as AuthenticatedMachineObject<'machine_token'>).machineId).toBeNull(); + expect( + (auth as UnauthenticatedMachineObject<'machine_token'>).machineId, + ).toBeNull();
50-63
: Same casting nit – unauthenticated object.Apply the same type-accurate cast here.
- expect((auth as AuthenticatedMachineObject<'api_key'>).userId).toBeNull(); + expect((auth as UnauthenticatedMachineObject<'api_key'>).userId).toBeNull();
65-71
: Reset mocked verification between tests to avoid leakage.
verifyMachineAuthToken
is globally mocked and mutated in multiple tests.
Add anafterEach(() => vi.resetAllMocks())
(orrestoreAllMocks
) to ensure each test starts with a clean slate.32 describe('getAuthDataFromRequestAsync', () => { + afterEach(() => { + vi.resetAllMocks(); + });packages/nextjs/src/server/data/getAuthDataFromRequest.ts (2)
171-173
: Redundant null-check ontokenType
.
handleMachineToken
is only invoked whentokenType
is already defined.
The early guard can be removed, simplifying the flow.- if (!tokenType) { - return signedOutAuthObject(options); - }
188-223
: Nested conditional complexity ‑ consider flattening for readability.
handleIntentBased
now has three levels of branching plus early returns.
A small refactor to guard-clauses / separate helpers would improve maintainability, especially as fallback rules evolve.(No diff provided – structural suggestion.)
packages/backend/src/tokens/__tests__/authObjects.test.ts (3)
393-428
: Consider table-driven tests to reduce duplicationAll five scenarios are valuable, but the structure is repetitive and could be collapsed into a parameterised (table-driven) test:
const cases = [ { acceptsToken: 'any', auth: machineAuth, expectedType: 'api_key' }, { acceptsToken: 'api_key', auth: machineAuth, expectedType: 'api_key' }, { acceptsToken: ['machine_token','oauth_token'], auth: machineAuth, expectedType: 'api_key' }, { acceptsToken: ['api_key','oauth_token'], auth: sessionAuth, expectedType: 'session_token' }, { acceptsToken: 'machine_token', auth: machineAuth, expectedType: 'machine_token' }, ] as const; cases.forEach(({acceptsToken, auth, expectedType}) => it(`returns correct object for acceptsToken=${JSON.stringify(acceptsToken)}`, () => { const result = getAuthObjectForAcceptedToken({authObject: auth, acceptsToken}); expect(result.tokenType).toBe(expectedType); }), );This eliminates boilerplate, makes future additions trivial, and keeps intent crystal-clear.
408-415
: Broaden assertions for stronger guaranteesOnly
tokenType
andid
are asserted. If downstream logic relies on other properties (name
,subject
,scopes
, etc.), they could silently regress without detection. Suggest asserting the entire object shape for the unauthenticated machine variant:expect(result).toMatchObject({ tokenType: 'api_key', id: null, subject: null, scopes: null, claims: null, });Strengthens the safety net with negligible overhead.
423-427
: Minor semantic nit – variable naming
machineAuth
actually represents an API-key auth object. Renaming toapiKeyAuth
makes the mismatch between the provided token (api_key
) and the requested one (machine_token
) more explicit and self-documenting.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
packages/backend/src/__tests__/exports.test.ts
(1 hunks)packages/backend/src/internal.ts
(1 hunks)packages/backend/src/tokens/__tests__/authObjects.test.ts
(2 hunks)packages/backend/src/tokens/__tests__/machine.test.ts
(2 hunks)packages/backend/src/tokens/authObjects.ts
(3 hunks)packages/backend/src/tokens/machine.ts
(2 hunks)packages/backend/src/tokens/request.ts
(3 hunks)packages/nextjs/src/server/__tests__/getAuthDataFromRequest.test.ts
(2 hunks)packages/nextjs/src/server/clerkMiddleware.ts
(2 hunks)packages/nextjs/src/server/data/getAuthDataFromRequest.ts
(3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (6)
packages/nextjs/src/server/__tests__/getAuthDataFromRequest.test.ts (5)
packages/nextjs/src/server/index.ts (1)
auth
(44-44)packages/backend/src/tokens/authObjects.ts (1)
AuthenticatedMachineObject
(115-125)packages/express/src/__tests__/helpers.ts (1)
mockRequest
(25-27)packages/nextjs/src/server/data/getAuthDataFromRequest.ts (1)
getAuthDataFromRequestAsync
(87-138)packages/backend/src/tokens/verify.ts (1)
verifyMachineAuthToken
(248-260)
packages/backend/src/tokens/__tests__/machine.test.ts (1)
packages/backend/src/tokens/machine.ts (5)
isMachineTokenByPrefix
(21-23)M2M_TOKEN_PREFIX
(5-5)OAUTH_TOKEN_PREFIX
(6-6)API_KEY_PREFIX
(7-7)isMachineTokenType
(77-79)
packages/backend/src/tokens/machine.ts (2)
packages/backend/src/internal.ts (4)
isMachineTokenByPrefix
(56-56)isMachineTokenType
(56-56)MachineTokenType
(19-19)TokenType
(18-18)packages/backend/src/tokens/tokenTypes.ts (3)
MachineTokenType
(20-20)TokenType
(1-6)TokenType
(11-11)
packages/backend/src/tokens/request.ts (2)
packages/backend/src/internal.ts (1)
isMachineTokenByPrefix
(56-56)packages/backend/src/tokens/machine.ts (1)
isMachineTokenByPrefix
(21-23)
packages/nextjs/src/server/clerkMiddleware.ts (1)
packages/backend/src/tokens/machine.ts (1)
isMachineTokenByPrefix
(21-23)
packages/backend/src/tokens/authObjects.ts (2)
packages/backend/src/internal.ts (4)
isTokenTypeAccepted
(56-56)isMachineTokenType
(56-56)unauthenticatedMachineObject
(33-33)signedOutAuthObject
(30-30)packages/backend/src/tokens/machine.ts (2)
isTokenTypeAccepted
(59-69)isMachineTokenType
(77-79)
⏰ Context from checks skipped due to timeout of 90000ms (5)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: Build Packages
- GitHub Check: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
packages/backend/src/__tests__/exports.test.ts (1)
53-55
: Snapshot update looks correctThe new exports
isMachineTokenByPrefix
andisMachineTokenType
are alphabetically sorted and preserve the public surface.
No further action required.packages/backend/src/internal.ts (1)
56-56
: Export list updated coherentlyThe re-exports now reflect the new helpers without breaking existing consumers. 👍
packages/backend/src/tokens/machine.ts (1)
21-23
: Single-responsibility helper is fine
isMachineTokenByPrefix
is concise and readable. 👍packages/backend/src/tokens/__tests__/authObjects.test.ts (2)
6-14
: Type-only imports 👍Good move extracting
SignedOutAuthObject
&UnauthenticatedMachineObject
as type-only imports – keeps runtime bundle clean while preserving strong typing.
417-421
: Edge-case: legacy cookie-based session tokens
sessionAuth
here comes fromsignedOutAuthObject
, which defaults tosession_token
.
If the codebase still supports legacy__session
cookies (no explicit token type), add a fixture & test to ensuregetAuthObjectForAcceptedToken
falls back identically for that path, preventing accidental breakage during cookie deprecation work.
if (!isTokenTypeAccepted(tokenType, acceptsToken ?? TokenType.SessionToken)) { | ||
return unauthenticatedMachineObject(tokenType, options); | ||
} | ||
const { data, errors } = await verifyMachineAuthToken(bearerToken, options); | ||
if (errors) { | ||
return unauthenticatedMachineObject(tokenType, options); | ||
} | ||
return authenticatedMachineObject(tokenType, bearerToken, data); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Pass only the expected shape to verifyMachineAuthToken
.
verifyMachineAuthToken
only needs { secretKey, publishableKey, apiUrl }
.
Passing the full options
(with unrelated fields) weakens type contracts.
- const { data, errors } = await verifyMachineAuthToken(bearerToken, options);
+ const { data, errors } = await verifyMachineAuthToken(bearerToken, {
+ secretKey: options.secretKey,
+ publishableKey: options.publishableKey,
+ apiUrl: options.apiUrl,
+ });
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if (!isTokenTypeAccepted(tokenType, acceptsToken ?? TokenType.SessionToken)) { | |
return unauthenticatedMachineObject(tokenType, options); | |
} | |
const { data, errors } = await verifyMachineAuthToken(bearerToken, options); | |
if (errors) { | |
return unauthenticatedMachineObject(tokenType, options); | |
} | |
return authenticatedMachineObject(tokenType, bearerToken, data); | |
} | |
if (!isTokenTypeAccepted(tokenType, acceptsToken ?? TokenType.SessionToken)) { | |
return unauthenticatedMachineObject(tokenType, options); | |
} | |
- const { data, errors } = await verifyMachineAuthToken(bearerToken, options); | |
+ const { data, errors } = await verifyMachineAuthToken(bearerToken, { | |
+ secretKey: options.secretKey, | |
+ publishableKey: options.publishableKey, | |
+ apiUrl: options.apiUrl, | |
+ }); | |
if (errors) { | |
return unauthenticatedMachineObject(tokenType, options); | |
} | |
return authenticatedMachineObject(tokenType, bearerToken, data); | |
} |
🤖 Prompt for AI Agents
In packages/nextjs/src/server/data/getAuthDataFromRequest.ts between lines 174
and 182, the function verifyMachineAuthToken is currently called with the entire
options object, which includes unrelated fields. To fix this, extract only the
expected properties secretKey, publishableKey, and apiUrl from options and pass
them to verifyMachineAuthToken. This ensures the function receives only the
necessary data, maintaining strong type contracts.
const options = { | ||
secretKey: opts?.secretKey || SECRET_KEY, | ||
publishableKey: PUBLISHABLE_KEY, | ||
apiUrl: API_URL, | ||
authStatus, | ||
authMessage, | ||
authReason, | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
options
deserves a typed interface instead of Record<string, any>
.
Using Record<string, any>
erodes type safety and allows accidental leakage of irrelevant keys throughout the call-chain.
Define a dedicated interface with the exact props consumed by downstream helpers and use it here & in helper signatures.
- const options = {
+ interface AuthOptions {
+ secretKey: string;
+ publishableKey: string;
+ apiUrl: string;
+ authStatus: string | null;
+ authMessage: string | null;
+ authReason: string | null;
+ }
+
+ const options: AuthOptions = {
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const options = { | |
secretKey: opts?.secretKey || SECRET_KEY, | |
publishableKey: PUBLISHABLE_KEY, | |
apiUrl: API_URL, | |
authStatus, | |
authMessage, | |
authReason, | |
}; | |
interface AuthOptions { | |
secretKey: string; | |
publishableKey: string; | |
apiUrl: string; | |
authStatus: string | null; | |
authMessage: string | null; | |
authReason: string | null; | |
} | |
const options: AuthOptions = { | |
secretKey: opts?.secretKey || SECRET_KEY, | |
publishableKey: PUBLISHABLE_KEY, | |
apiUrl: API_URL, | |
authStatus, | |
authMessage, | |
authReason, | |
}; |
🤖 Prompt for AI Agents
In packages/nextjs/src/server/data/getAuthDataFromRequest.ts around lines 96 to
104, the options object is currently typed as Record<string, any>, which reduces
type safety. Define a dedicated TypeScript interface specifying the exact
properties (secretKey, publishableKey, apiUrl, authStatus, authMessage,
authReason) with their appropriate types, then use this interface to type the
options object and update any downstream helper function signatures accordingly
to ensure strict type checking and prevent accidental key leakage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
.changeset/open-swans-count.md (1)
6-6
: Clarify the changeset summary for future readersA single-sentence summary is fine, but adding one more phrase about how the fallback now behaves (e.g., “returns an unauthenticated object of the accepted token type rather than the parsed token type”) would make the patch note self-contained and clearer in changelogs.
packages/fastify/src/__tests__/getAuth.test.ts (1)
37-43
: Update the inline comment to match the new behaviourThe expectation is now
api_key
because it mirrors the accepted token type, not the actual token found.
Leaving the old wording is misleading for future maintainers.- expect(result.tokenType).toBe('api_key'); // reflects the actual token found + expect(result.tokenType).toBe('api_key'); // mirrors the *accepted* token typepackages/express/src/__tests__/getAuth.test.ts (1)
40-46
: Fix the stale comment to avoid confusionSame as in the Fastify test: the returned
tokenType
reflects the accepted token type, not the one on the incoming request. Adjust the comment accordingly.- expect(result.tokenType).toBe('api_key'); // reflects the actual token found + expect(result.tokenType).toBe('api_key'); // mirrors the *accepted* token type
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.changeset/open-swans-count.md
(1 hunks)packages/express/src/__tests__/getAuth.test.ts
(1 hunks)packages/fastify/src/__tests__/getAuth.test.ts
(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (5)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: Build Packages
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
!snapshot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
packages/nextjs/src/server/protect.ts (1)
144-151
: Consider folding the newnull
check into the existing guard for cleaner flowFunctionally this works, but we now have two adjacent early-return guards that both call
handleUnauthorized()
.
Combining them (or moving thenull
check first) keeps the intent crystal-clear and avoids an unnecessary call toisTokenTypeAccepted
when the token is already known to be invalid.- if (!isTokenTypeAccepted(authObject.tokenType, requestedToken)) { - return handleUnauthorized(); - } - - if (authObject.tokenType === null) { - return handleUnauthorized(); - } + if ( + authObject.tokenType === null || + !isTokenTypeAccepted(authObject.tokenType, requestedToken) + ) { + return handleUnauthorized(); + }Same behaviour, fewer branches.
Use or ignore at your discretion.packages/nextjs/src/app-router/server/auth.ts (1)
59-65
: Document the newInvalidTokenAuthObject
return pathThe overload now rightfully includes
InvalidTokenAuthObject
, but the surrounding JSDoc (@example
lines 52-56) still states “returns the auth object” without mentioning this extra unauthenticated variant. Adding a short note (or an extra example) will prevent consumers from overlooking the possibility of the invalid-token path and improves IntelliSense docs.packages/backend/src/tokens/types.ts (1)
204-206
: Synchronise docs & ‘any’ overload with the new invalid token unionThe array overload now unions
InvalidTokenAuthObject
, but:
- The earlier JSDoc (
@example
lines 197-200) doesn’t mention that an invalid object may be returned.- The
'any'
overload (line 225) still returns plainAuthObject
; verify thatAuthObject
already includesInvalidTokenAuthObject
, otherwise callers using'any'
won’t see this variant in their type checking.Updating the docs and, if needed, the
'any'
overload will keep the public contract crystal-clear.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
packages/backend/src/__tests__/exports.test.ts
(1 hunks)packages/backend/src/index.ts
(1 hunks)packages/backend/src/internal.ts
(2 hunks)packages/backend/src/tokens/__tests__/authObjects.test.ts
(2 hunks)packages/backend/src/tokens/__tests__/getAuth.test-d.ts
(2 hunks)packages/backend/src/tokens/authObjects.ts
(12 hunks)packages/backend/src/tokens/machine.ts
(2 hunks)packages/backend/src/tokens/types.ts
(2 hunks)packages/nextjs/src/app-router/server/auth.ts
(2 hunks)packages/nextjs/src/server/protect.ts
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- packages/backend/src/index.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- packages/backend/src/tests/exports.test.ts
- packages/backend/src/tokens/machine.ts
- packages/backend/src/internal.ts
- packages/backend/src/tokens/tests/authObjects.test.ts
- packages/backend/src/tokens/authObjects.ts
🧰 Additional context used
🧬 Code Graph Analysis (3)
packages/backend/src/tokens/types.ts (4)
packages/backend/src/internal.ts (2)
InferAuthObjectFromTokenArray
(14-14)SessionTokenType
(19-19)packages/backend/src/index.ts (3)
SessionAuthObject
(165-165)MachineAuthObject
(165-165)InvalidTokenAuthObject
(164-164)packages/backend/src/tokens/tokenTypes.ts (1)
SessionTokenType
(16-16)packages/backend/src/tokens/authObjects.ts (1)
InvalidTokenAuthObject
(151-157)
packages/nextjs/src/app-router/server/auth.ts (3)
packages/backend/src/tokens/types.ts (2)
InferAuthObjectFromTokenArray
(160-168)MachineAuthObject
(181-183)packages/backend/src/tokens/tokenTypes.ts (1)
SessionTokenType
(16-16)packages/backend/src/tokens/authObjects.ts (1)
InvalidTokenAuthObject
(151-157)
packages/backend/src/tokens/__tests__/getAuth.test-d.ts (2)
packages/backend/src/tokens/types.ts (2)
SessionAuthObject
(180-180)MachineAuthObject
(181-183)packages/backend/src/tokens/authObjects.ts (1)
InvalidTokenAuthObject
(151-157)
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
packages/backend/src/tokens/__tests__/getAuth.test-d.ts (1)
24-29
: LGTM – type expectations correctly expandedThe added
InvalidTokenAuthObject
in the unions accurately mirrors the new fallback behaviour and compiles as expected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
packages/backend/src/tokens/authObjects.ts (1)
455-462
:⚠️ Potential issue
authObject.debug
is still passed as data – identical issue flagged previously
unauthenticatedMachineObject
/signedOutAuthObject
expect raw debug data which they wrap withcreateDebug
.
Passing the already-wrappedauthObject.debug
(a function) leads tocreateDebug
spreading a function and silently discarding the original context.Issue was highlighted in an earlier review and remains unfixed.
- return unauthenticatedMachineObject(acceptsToken, authObject.debug); + return unauthenticatedMachineObject(acceptsToken, authObject.debug?.()); - return signedOutAuthObject(authObject.debug); + return signedOutAuthObject(authObject.debug?.());Please apply the same fix everywhere this pattern occurs.
🧹 Nitpick comments (2)
packages/backend/src/tokens/authObjects.ts (2)
151-157
: Consider surfacing minimal debug context inInvalidTokenAuthObject
debug
currently returns an empty object, so consumers lose request-level hints (e.g. headers) that might aid investigation. Passing through sanitised context (like in other factory helpers) would keep parity across auth-object variants.
361-372
:invalidTokenAuthObject()
duplicates boilerplate – could reuse helpersImplementation is hand-rolled; reusing
unauthenticatedMachineObject
& friends (or a shared base factory) would avoid future drift if common props change.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/backend/src/tokens/authObjects.ts
(12 hunks)packages/nextjs/src/server/__tests__/getAuthDataFromRequest.test.ts
(2 hunks)packages/nextjs/src/server/data/getAuthDataFromRequest.ts
(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/nextjs/src/server/tests/getAuthDataFromRequest.test.ts
- packages/nextjs/src/server/data/getAuthDataFromRequest.ts
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep/ci
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
packages/backend/src/tokens/authObjects.ts (1)
61-63
: Nice explicitness withisAuthenticated
flagIntroducing a literal
true/false
discriminator simplifies downstream type-narrowing and improves DX. No further action required.Also applies to: 82-83, 126-128, 147-148
!snapshot |
Hey @wobsoriano - the snapshot version command generated the following package versions:
Tip: Use the snippet copy button below to quickly install the required packages. npm i @clerk/agent-toolkit@0.1.1-snapshot.v20250613203834 --save-exact
npm i @clerk/astro@2.9.1-snapshot.v20250613203834 --save-exact
npm i @clerk/backend@2.1.0-snapshot.v20250613203834 --save-exact
npm i @clerk/chrome-extension@2.4.12-snapshot.v20250613203834 --save-exact
npm i @clerk/clerk-js@5.68.1-snapshot.v20250613203834 --save-exact
npm i @clerk/elements@0.23.33-snapshot.v20250613203834 --save-exact
npm i @clerk/clerk-expo@2.13.1-snapshot.v20250613203834 --save-exact
npm i @clerk/expo-passkeys@0.3.10-snapshot.v20250613203834 --save-exact
npm i @clerk/express@1.7.0-snapshot.v20250613203834 --save-exact
npm i @clerk/fastify@2.4.0-snapshot.v20250613203834 --save-exact
npm i @clerk/localizations@3.16.5-snapshot.v20250613203834 --save-exact
npm i @clerk/nextjs@6.22.0-snapshot.v20250613203834 --save-exact
npm i @clerk/nuxt@1.7.1-snapshot.v20250613203834 --save-exact
npm i @clerk/clerk-react@5.31.10-snapshot.v20250613203834 --save-exact
npm i @clerk/react-router@1.6.0-snapshot.v20250613203834 --save-exact
npm i @clerk/remix@4.8.1-snapshot.v20250613203834 --save-exact
npm i @clerk/shared@3.9.7-snapshot.v20250613203834 --save-exact
npm i @clerk/tanstack-react-start@0.17.0-snapshot.v20250613203834 --save-exact
npm i @clerk/testing@1.8.1-snapshot.v20250613203834 --save-exact
npm i @clerk/themes@2.2.50-snapshot.v20250613203834 --save-exact
npm i @clerk/types@4.60.1-snapshot.v20250613203834 --save-exact
npm i @clerk/vue@1.8.8-snapshot.v20250613203834 --save-exact |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed this with @wobsoriano on Tuple. 🚀
Description
isAuthenticated
property to auth objectFor
acceptsToken
as a single value:This means that even if the result of
authenticateRequest()
parses a different token type, the returned object will always match what the developer specified inacceptsToken
ofauth()
orgetAuth()
.Example:
For
acceptsToken
as an array:Example:
Note:
These changes only affect the behavior for unauthenticated requests and fallback logic. Authenticated flows and matching token types are unchanged.
Checklist
pnpm test
runs as expected.pnpm build
runs as expected.Type of change
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Refactor