Skip to content

fix(backend): auth _next/data requests when __client_uat is missing#7923

Open
arthurgeron wants to merge 1 commit intoclerk:mainfrom
arthurgeron:fix/backend-authenticate-next-data-requests
Open

fix(backend): auth _next/data requests when __client_uat is missing#7923
arthurgeron wants to merge 1 commit intoclerk:mainfrom
arthurgeron:fix/backend-authenticate-next-data-requests

Conversation

@arthurgeron
Copy link

@arthurgeron arthurgeron commented Feb 24, 2026

Description

Problem

authenticateRequest returns signedOut for _next/data requests (Next.js Pages Router client-side navigations) when the __client_uat cookie is missing but a valid __session token exists. The __client_uat cookie is not always sent with fetch requests because it is set with SameSite=Strict (e.g., during development). As a result, getAuth() returns a fully null auth object during client-side navigations, even though the user remains authenticated, and no errors are thrown.

Fix

  • In backend/src/tokens/request.ts on the !hasActiveClient && hasSessionToken assertion, handleMaybeHandshakeStatus is now only called when isRequestEligibleForHandshake() returns true (document/iframe navigations). For non-handshake-eligible requests (fetch, _next/data), the code falls through to the full token verification pipeline instead of short-circuiting to signedOut.

  • The iat < clientUat freshness comparison is now guarded with authenticateContext.clientUat &&, so it is skipped when clientUat is missing, avoiding a incorrect comparison.

  • Handshake-eligible requests (document navigations) are unchanged. This change only affects requests where handshake was already impossible.

Observations

  • Before this, non-handshake-eligible requests with a missing __client_uat were returned as signedOut without verifying __session. Now, those requests go through the same token verification pipeline used by all other authenticated requests. No verification steps are skipped or weakened.

__client_uat cookie is a client-side freshness signal used to detect cross-tab session changes. It is not involved in token validation.

  • Handshake-eligible requests (e.g., document navigations) are unaffected.

Related issues

Testing the fix

Unit tests were added as well

  • Create a Next.js (tested on v14) Pages Router app with @clerk/nextjs
  • Add a page with getServerSideProps that logs getAuth(req):
   export const getServerSideProps = (ctx) => {
     const auth = getAuth(ctx.req);
     console.log('auth.userId:', auth.userId);
     return { props: { userId: auth.userId } };
   };
  • Sign in via Clerk
  • Navigate to the page via full page load (i.e., URL bar), userId should be present
  • Navigate to the page via client-side <Link>
    • before: userId is null
    • after: userId is present

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • Bug Fixes

    • getAuth() no longer reports unauthenticated during Next.js Pages Router client-side navigations when a valid session exists but certain client metadata is missing.
    • Prevented unnecessary background handshake attempts when no active client is present.
    • Avoided incorrect token time comparisons when optional client metadata is absent.
  • Tests

    • Added tests covering non-document requests to ensure stable authentication behavior.

@changeset-bot
Copy link

changeset-bot bot commented Feb 24, 2026

🦋 Changeset detected

Latest commit: 4b11b50

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 10 packages
Name Type
@clerk/backend Patch
@clerk/agent-toolkit Patch
@clerk/astro Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch

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

@vercel
Copy link

vercel bot commented Feb 24, 2026

@arthurgeron is attempting to deploy a commit to the Clerk Production Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 79bb92e and 4b11b50.

📒 Files selected for processing (3)
  • .changeset/solid-yaks-enter.md
  • packages/backend/src/tokens/__tests__/request.test.ts
  • packages/backend/src/tokens/request.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • .changeset/solid-yaks-enter.md

📝 Walkthrough

Walkthrough

The PR makes handshake initiation conditional by invoking it only when the request is eligible, and guards the IAT vs clientUat comparison to run only if authenticateContext.clientUat is present. It adds tests covering authentication when a valid session token exists but the __client_uat cookie is missing (production and development). A changeset entry documents a bug fix for getAuth() returning unauthenticated during Next.js Pages Router client-side navigations when __client_uat is absent.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main fix: handling authentication for _next/data requests when the __client_uat cookie is missing.
Linked Issues check ✅ Passed The PR changes address both the immediate bug (#7923) and the underlying issue (#7178) by ensuring non-handshake-eligible requests properly validate sessions instead of short-circuiting to signedOut.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the authentication logic in request.ts, adding related test coverage, and documenting the fix. No unrelated modifications are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@arthurgeron arthurgeron force-pushed the fix/backend-authenticate-next-data-requests branch from 91dc54f to 79bb92e Compare February 25, 2026 12:44
@arthurgeron arthurgeron force-pushed the fix/backend-authenticate-next-data-requests branch from 79bb92e to 4b11b50 Compare February 25, 2026 18:47
@arthurgeron
Copy link
Author

There's already no JSDocs for these methods, only a few in that module have it. Should I create docs for it anyway?

cc @nikosdouvlis

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

authenticateRequest and organizationSyncOptions

1 participant