-
Notifications
You must be signed in to change notification settings - Fork 460
feat(nextjs,backend,integration): Introduce dynamic keys from clerkMiddleware
#3525
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
Merged
Merged
Changes from all commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
877b55b
Require signing key to be defined when using runtime options
LauraBeatris 04a4ceb
Add constant definition for `x-clerk-data` header
LauraBeatris 604d08d
Add utilities to encrypt/decrypt request data
LauraBeatris b83f919
Use propogated secret key
LauraBeatris 1dc02f7
Assert against signing key value
LauraBeatris a7cd636
Fix CryptoJS import statement
LauraBeatris b0954f9
Handle error when signing key is invalid
LauraBeatris 614fac5
Rename signing key to encryption key
LauraBeatris 5e0eff1
Add test to assert against propagation
LauraBeatris 977bc38
Propagate `signInUrl` and `signUpUrl`
LauraBeatris 6111133
Do not allow to pass `signInUrl` and `signUpUrl` from ClerkProvider
LauraBeatris c0f37a8
Restructure test block and add todo
LauraBeatris bc510b8
Rollback props changes on `ClerkProvider`
LauraBeatris d02913e
Introduce fallback for encryption key
LauraBeatris 3e5758b
Implement test case for `signInUrl` option
LauraBeatris 919ec6e
Add `CLERK_ENCRYPTION_KEY` to integration tests
LauraBeatris 73942bd
Access redirect URLs from middleware options
LauraBeatris 853d90e
Add changeset
LauraBeatris c1856cb
Mock `ENCRYPTION_KEY` on `authMiddleware` unit tests
LauraBeatris 0be0727
Update snapshot for request headers
LauraBeatris f520025
Warn when encryption key is missing instead of throwing
LauraBeatris 8059461
Reference to docs on error message and changeset
LauraBeatris 4deca28
Add todo comment for next major version
LauraBeatris aa532db
Propagate secret key to backend client
LauraBeatris 7109105
Update changeset
LauraBeatris 6ee667b
Propagate `publishableKey` to `auth`
LauraBeatris b618edf
Update changeset to mention `Dynamic Keys`
LauraBeatris d8cc06e
Update encryption key env var for integration tests
LauraBeatris 7d462a6
Add `CLERK_ENCRYPTION_KEY` to CI
LauraBeatris f7df0ee
feat(nextjs): Read dynamic keys from `clerkClient` within middleware …
LauraBeatris f3d83c8
Rollback changes on `authMiddleware`
LauraBeatris 25eaaf2
Fix unit tests and Proxy
LauraBeatris e2b4078
Mention `clerkClient` on changeset
LauraBeatris 89a8a4c
Fallback to ALS on `headers` error
LauraBeatris b76e2bb
Update changeset
LauraBeatris ed3aa79
Fix error formatting
LauraBeatris 7170e31
Extract middleware handler to separate variable
LauraBeatris db5fc1e
Re-throw errors related to static generation bail-out
LauraBeatris c458ab7
Remove `@clerk/shared` from changeset
LauraBeatris File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| --- | ||
| '@clerk/backend': minor | ||
| '@clerk/nextjs': minor | ||
| --- | ||
|
|
||
| Introduces dynamic keys from `clerkMiddleware`, allowing access by server-side helpers like `auth`. Keys such as `signUpUrl`, `signInUrl`, `publishableKey` and `secretKey` are securely encrypted using AES algorithm. | ||
|
|
||
| - When providing `secretKey`, `CLERK_ENCRYPTION_KEY` is required as the encryption key. If `secretKey` is not provided, `CLERK_SECRET_KEY` is used by default. | ||
| - `clerkClient` from `@clerk/nextjs` should now be called as a function, and its singleton form is deprecated. This change allows the Clerk backend client to read keys from the current request, which is necessary to support dynamic keys. | ||
|
|
||
| For more information, refer to the documentation: https://clerk.com/docs/references/nextjs/clerk-middleware#dynamic-keys | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| import { expect, test } from '@playwright/test'; | ||
|
|
||
| import type { Application } from '../models/application'; | ||
| import { appConfigs } from '../presets'; | ||
| import { createTestUtils } from '../testUtils'; | ||
|
|
||
| test.describe('dynamic keys @nextjs', () => { | ||
| test.describe.configure({ mode: 'parallel' }); | ||
| let app: Application; | ||
|
|
||
| test.beforeAll(async () => { | ||
| app = await appConfigs.next.appRouter | ||
| .clone() | ||
| .addFile( | ||
| 'src/middleware.ts', | ||
| () => `import { clerkClient, clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server' | ||
| import { NextResponse } from 'next/server' | ||
|
|
||
| const isProtectedRoute = createRouteMatcher(['/protected']); | ||
| const shouldFetchBapi = createRouteMatcher(['/fetch-bapi-from-middleware']); | ||
|
|
||
| export default clerkMiddleware(async (auth, request) => { | ||
| if (isProtectedRoute(request)) { | ||
| auth().protect(); | ||
| } | ||
|
|
||
| if (shouldFetchBapi(request)){ | ||
| const count = await clerkClient().users.getCount(); | ||
|
|
||
| if (count){ | ||
| return NextResponse.redirect(new URL('/users-count', request.url)) | ||
| } | ||
| } | ||
| }, { | ||
| secretKey: process.env.CLERK_DYNAMIC_SECRET_KEY, | ||
| signInUrl: '/foobar' | ||
| }); | ||
|
|
||
| export const config = { | ||
| matcher: ['/((?!.*\\\\..*|_next).*)', '/', '/(api|trpc)(.*)'], | ||
| };`, | ||
| ) | ||
| .addFile( | ||
| 'src/app/users-count/page.tsx', | ||
| () => `import { clerkClient } from '@clerk/nextjs/server' | ||
|
|
||
| export default async function Page(){ | ||
| const count = await clerkClient().users.getCount() | ||
|
|
||
| return <p>Users count: {count}</p> | ||
| } | ||
| `, | ||
| ) | ||
| .commit(); | ||
|
|
||
| await app.setup(); | ||
| await app.withEnv(appConfigs.envs.withDynamicKeys); | ||
| await app.dev(); | ||
| }); | ||
|
|
||
| test.afterAll(async () => { | ||
| await app.teardown(); | ||
| }); | ||
|
|
||
| test.afterEach(async ({ page, context }) => { | ||
| const u = createTestUtils({ app, page, context }); | ||
| await u.page.signOut(); | ||
| await u.page.context().clearCookies(); | ||
| }); | ||
|
|
||
| test('redirects to `signInUrl` on `auth().protect()`', async ({ page, context }) => { | ||
| const u = createTestUtils({ app, page, context }); | ||
|
|
||
| await u.page.goToStart(); | ||
|
|
||
| await u.po.expect.toBeSignedOut(); | ||
|
|
||
| await u.page.goToRelative('/protected'); | ||
|
|
||
| await u.page.waitForURL(/foobar/); | ||
| }); | ||
|
|
||
| test('resolves auth signature with `secretKey` on `auth().protect()`', async ({ page, context }) => { | ||
| const u = createTestUtils({ app, page, context }); | ||
| await u.page.goToRelative('/page-protected'); | ||
| await u.page.waitForURL(/foobar/); | ||
| }); | ||
|
|
||
| test('calls `clerkClient` with dynamic keys from application runtime', async ({ page, context }) => { | ||
| const u = createTestUtils({ app, page, context }); | ||
| await u.page.goToRelative('/users-count'); | ||
| await expect(u.page.getByText(/Users count/i)).toBeVisible(); | ||
| }); | ||
|
|
||
| test('calls `clerkClient` with dynamic keys from middleware runtime', async ({ page, context }) => { | ||
| const u = createTestUtils({ app, page, context }); | ||
| await u.page.goToRelative('/fetch-bapi-from-middleware'); | ||
| await u.page.waitForAppUrl('/users-count'); | ||
| await expect(u.page.getByText(/Users count/i)).toBeVisible(); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.