Skip to content

feat(nextjs): Introduce machine authentication #5710

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

Open
wants to merge 71 commits into
base: rob/robo-36-sdk-m2m
Choose a base branch
from

Conversation

wobsoriano
Copy link
Member

@wobsoriano wobsoriano commented Apr 24, 2025

Description

This is a companion PR to #5689, that updates the Next.js SDK clerkMiddleware(), auth(), and auth.protect() helpers to accommodate machine auth tokens.

Key changes:

  • Updated auth() to accept a acceptTokens param. Useful for leaf node route protection.
  • Updated auth.protect() to accept a tokens param. Useful in protecting routes inside a middleware.
  • Updated clerkMiddleware() to pass any as the default acceptsToken type to authenticateRequest. This however opens up an opportunity for an economic attacks and will be tackled in a separate PR.
  • Added proper type inference for auth objects based on token types.
  • Added tests for middleware and auth() verification with machine tokens.

Resolves ROBO-114 and ROBO-134

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:

Copy link

changeset-bot bot commented Apr 24, 2025

⚠️ No Changeset found

Latest commit: 26a3b5d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

vercel bot commented Apr 24, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
clerk-js-sandbox ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 5, 2025 4:00pm

Copy link
Contributor

@jescalan jescalan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good so far

@wobsoriano wobsoriano force-pushed the rob/robo-114-nextjs-sdk-m2m branch from 5e0630b to 69e9760 Compare April 25, 2025 19:28
@jacekradko jacekradko requested a review from Copilot May 1, 2025 03:20
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces machine authentication support for the Next.js SDK by updating auth-related helpers and middleware to accept and correctly process machine tokens. The changes include:

  • Enhancements to type inference for auth objects via new generic types.
  • Updates to auth(), auth.protect(), and clerkMiddleware() to handle both session and machine tokens.
  • Additional tests to verify the new machine token behaviors.

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/nextjs/src/server/types.ts Added generic types to infer auth objects from single and multiple token types.
packages/nextjs/src/server/protect.ts Extended protection logic to validate and handle machine tokens.
packages/nextjs/src/server/nextErrors.ts Introduced an unauthorized() function for machine token error handling.
packages/nextjs/src/server/data/getAuthDataFromRequest.ts Split auth data retrieval into sync/async versions, with sync only accepting session tokens.
packages/nextjs/src/server/createGetAuth.ts Updated options propagation to include acceptsToken for dynamic auth behavior.
packages/nextjs/src/server/clerkMiddleware.ts Modified middleware auth handling to support machine tokens and enhanced redirects.
packages/nextjs/src/app-router/server/auth.ts Updated auth() API to correctly infer return types based on token type.
tests files Added/updated tests verifying machine token support and related error handling.


const authHandler = async (options?: GetAuthOptions) => {
const acceptsToken = options?.acceptsToken ?? TokenType.SessionToken;

Copy link
Preview

Copilot AI May 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of 'any' as the acceptsToken value bypasses token type validation, which is noted as a TODO regarding potential economic attacks. Consider adding a clarifying comment that explains this behavior and its intended usage to help maintain security awareness.

Suggested change
// The 'any' value for acceptsToken bypasses token type validation.
// This is intended for scenarios where the token type is irrelevant or
// where the caller explicitly accepts all token types. However, this
// behavior comes with potential security risks, such as economic attacks,
// if misused. Use 'any' cautiously and only when absolutely necessary.

Copilot uses AI. Check for mistakes.

@wobsoriano wobsoriano force-pushed the rob/robo-36-sdk-m2m branch from 26ea907 to 58c0c97 Compare May 1, 2025 16:17
@wobsoriano wobsoriano changed the title feat(nextjs): Add machine authentication support feat(nextjs): Introduce machine authentication May 1, 2025
@wobsoriano
Copy link
Member Author

!snapshot

@clerk-cookie
Copy link
Collaborator

Hey @wobsoriano - the snapshot version command generated the following package versions:

Package Version
@clerk/agent-toolkit 0.0.29-snapshot.v20250501230217
@clerk/astro 2.6.11-snapshot.v20250501230217
@clerk/backend 1.31.0-snapshot.v20250501230217
@clerk/chrome-extension 2.3.5-snapshot.v20250501230217
@clerk/clerk-js 5.63.3-snapshot.v20250501230217
@clerk/clerk-expo 2.10.5-snapshot.v20250501230217
@clerk/express 1.4.12-snapshot.v20250501230217
@clerk/fastify 2.2.12-snapshot.v20250501230217
@clerk/nextjs 6.18.3-snapshot.v20250501230217
@clerk/nuxt 1.5.12-snapshot.v20250501230217
@clerk/react-router 1.3.3-snapshot.v20250501230217
@clerk/remix 4.6.3-snapshot.v20250501230217
@clerk/tanstack-react-start 0.14.3-snapshot.v20250501230217
@clerk/testing 1.6.2-snapshot.v20250501230217

Tip: Use the snippet copy button below to quickly install the required packages.
@clerk/agent-toolkit

npm i @clerk/[email protected] --save-exact

@clerk/astro

npm i @clerk/[email protected] --save-exact

@clerk/backend

npm i @clerk/[email protected] --save-exact

@clerk/chrome-extension

npm i @clerk/[email protected] --save-exact

@clerk/clerk-js

npm i @clerk/[email protected] --save-exact

@clerk/clerk-expo

npm i @clerk/[email protected] --save-exact

@clerk/express

npm i @clerk/[email protected] --save-exact

@clerk/fastify

npm i @clerk/[email protected] --save-exact

@clerk/nextjs

npm i @clerk/[email protected] --save-exact

@clerk/nuxt

npm i @clerk/[email protected] --save-exact

@clerk/react-router

npm i @clerk/[email protected] --save-exact

@clerk/remix

npm i @clerk/[email protected] --save-exact

@clerk/tanstack-react-start

npm i @clerk/[email protected] --save-exact

@clerk/testing

npm i @clerk/[email protected] --save-exact

}) =>
withLogger(debugLoggerName, logger => {
return (req: RequestLike, opts?: { secretKey?: string }): AuthObject => {
return (req: RequestLike, opts?: { secretKey?: string }): SignedInAuthObject | SignedOutAuthObject => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since getAuth() does not have machine auth feature yet (will be breaking because it's async), we need to type it as session auth

})(req, {} as NextFetchEvent);

expect(resp?.status).toEqual(401);
expect(resp?.headers.get('WWW-Authenticate')).toBeTruthy();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 it might be a good idea to assert on the explicit value here, instead of just the truthy check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants