Skip to content
29 changes: 15 additions & 14 deletions integration/presets/envs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ const withEmailCodes = environmentConfig()
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', envKeys['with-email-codes'].pk)
.setEnvVariable('public', 'CLERK_SIGN_IN_URL', '/sign-in')
.setEnvVariable('public', 'CLERK_SIGN_UP_URL', '/sign-up')
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js')
.setEnvVariable('private', 'CLERK_ENCRYPTION_KEY', constants.E2E_CLERK_ENCRYPTION_KEY);
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js');

const withEmailLinks = environmentConfig()
.setId('withEmailLinks')
Expand All @@ -39,8 +38,7 @@ const withEmailLinks = environmentConfig()
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', envKeys['with-email-links'].pk)
.setEnvVariable('public', 'CLERK_SIGN_IN_URL', '/sign-in')
.setEnvVariable('public', 'CLERK_SIGN_UP_URL', '/sign-up')
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js')
.setEnvVariable('private', 'CLERK_ENCRYPTION_KEY', constants.E2E_CLERK_ENCRYPTION_KEY);
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js');

const withCustomRoles = environmentConfig()
.setId('withCustomRoles')
Expand All @@ -51,8 +49,7 @@ const withCustomRoles = environmentConfig()
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', envKeys['with-custom-roles'].pk)
.setEnvVariable('public', 'CLERK_SIGN_IN_URL', '/sign-in')
.setEnvVariable('public', 'CLERK_SIGN_UP_URL', '/sign-up')
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js')
.setEnvVariable('private', 'CLERK_ENCRYPTION_KEY', constants.CLERK_ENCRYPTION_KEY);
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js');

const withEmailCodesQuickstart = withEmailCodes
.removeEnvVariable('public', 'CLERK_SIGN_IN_URL')
Expand All @@ -63,30 +60,33 @@ const withAPCore1ClerkLatest = environmentConfig()
.setEnvVariable('public', 'CLERK_TELEMETRY_DISABLED', true)
.setEnvVariable('private', 'CLERK_SECRET_KEY', envKeys['with-email-codes'].sk)
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', envKeys['with-email-codes'].pk)
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js')
.setEnvVariable('private', 'CLERK_ENCRYPTION_KEY', constants.CLERK_ENCRYPTION_KEY);
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js');

const withAPCore1ClerkV4 = environmentConfig()
.setId('withAPCore1ClerkV4')
.setEnvVariable('public', 'CLERK_TELEMETRY_DISABLED', true)
.setEnvVariable('private', 'CLERK_SECRET_KEY', envKeys['with-email-codes'].sk)
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', envKeys['with-email-codes'].pk)
.setEnvVariable('private', 'CLERK_ENCRYPTION_KEY', constants.CLERK_ENCRYPTION_KEY);
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', envKeys['with-email-codes'].pk);

const withAPCore2ClerkLatest = environmentConfig()
.setId('withAPCore2ClerkLatest')
.setEnvVariable('public', 'CLERK_TELEMETRY_DISABLED', true)
.setEnvVariable('private', 'CLERK_SECRET_KEY', envKeys['core-2-all-enabled'].sk)
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', envKeys['core-2-all-enabled'].pk)
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js')
.setEnvVariable('private', 'CLERK_ENCRYPTION_KEY', constants.CLERK_ENCRYPTION_KEY);
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js');

const withAPCore2ClerkV4 = environmentConfig()
.setId('withAPCore2ClerkV4')
.setEnvVariable('public', 'CLERK_TELEMETRY_DISABLED', true)
.setEnvVariable('private', 'CLERK_SECRET_KEY', envKeys['core-2-all-enabled'].sk)
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', envKeys['core-2-all-enabled'].pk)
.setEnvVariable('private', 'CLERK_ENCRYPTION_KEY', constants.CLERK_ENCRYPTION_KEY);
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', envKeys['core-2-all-enabled'].pk);

const withDynamicKeys = withEmailCodes
.clone()
.setId('withDynamicKeys')
.setEnvVariable('private', 'CLERK_SECRET_KEY', '')
.setEnvVariable('private', 'CLERK_DYNAMIC_SECRET_KEY', envKeys['with-email-codes'].sk)
.setEnvVariable('private', 'CLERK_ENCRYPTION_KEY', constants.E2E_CLERK_ENCRYPTION_KEY);

export const envs = {
withEmailCodes,
Expand All @@ -97,4 +97,5 @@ export const envs = {
withAPCore1ClerkV4,
withAPCore2ClerkLatest,
withAPCore2ClerkV4,
withDynamicKeys,
} as const;
101 changes: 101 additions & 0 deletions integration/tests/dynamic-keys.test.ts
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();
});
});
2 changes: 1 addition & 1 deletion integration/tests/handshake.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { generateConfig, getJwksFromSecretKey } from '../testUtils/handshake';

const PORT = 4199;

test.skip('Client handshake @generic', () => {
test.describe('Client handshake @generic', () => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@nikosdouvlis I've went ahead and removed the skip from handshake tests here.

test.describe.configure({ mode: 'serial' });

let app: Application;
Expand Down
2 changes: 1 addition & 1 deletion packages/nextjs/src/app-router/server/currentUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ export async function currentUser(): Promise<User | null> {
return null;
}

return clerkClient.users.getUser(userId);
return clerkClient().users.getUser(userId);
}
2 changes: 1 addition & 1 deletion packages/nextjs/src/server/__tests__/clerkClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { clerkClient } from '../clerkClient';

describe('clerkClient', () => {
it('should pass version package to userAgent', async () => {
await clerkClient.users.getUser('user_test');
await clerkClient().users.getUser('user_test');

expect(global.fetch).toBeCalled();
expect((global.fetch as any).mock.calls[0][1].headers).toMatchObject({
Expand Down
34 changes: 17 additions & 17 deletions packages/nextjs/src/server/__tests__/clerkMiddleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ describe('clerkMiddleware(params)', () => {

expect(resp?.status).toEqual(307);
expect(resp?.headers.get('location')).toContain('sign-in');
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('redirects to sign-in url when redirectToSignIn is called with the correct returnBackUrl', async () => {
Expand All @@ -270,7 +270,7 @@ describe('clerkMiddleware(params)', () => {
expect(resp?.status).toEqual(307);
expect(resp?.headers.get('location')).toContain('sign-in');
expect(new URL(resp!.headers.get('location')!).searchParams.get('redirect_url')).toContain('/protected');
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('redirects to sign-in url with redirect_url set to the provided returnBackUrl param', async () => {
Expand All @@ -289,7 +289,7 @@ describe('clerkMiddleware(params)', () => {
expect(new URL(resp!.headers.get('location')!).searchParams.get('redirect_url')).toEqual(
'https://www.clerk.com/hello',
);
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('redirects to sign-in url without a redirect_url when returnBackUrl is null', async () => {
Expand All @@ -306,7 +306,7 @@ describe('clerkMiddleware(params)', () => {
expect(resp?.status).toEqual(307);
expect(resp?.headers.get('location')).toContain('sign-in');
expect(new URL(resp!.headers.get('location')!).searchParams.get('redirect_url')).toBeNull();
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});
});

Expand All @@ -331,7 +331,7 @@ describe('clerkMiddleware(params)', () => {

expect(resp?.status).toEqual(307);
expect(resp?.headers.get('location')).toContain('sign-in');
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('does not redirect to sign-in url when protect is called, the user is signed in and the request is a page request', async () => {
Expand All @@ -354,7 +354,7 @@ describe('clerkMiddleware(params)', () => {

expect(resp?.status).toEqual(200);
expect(resp?.headers.get('location')).toBeFalsy();
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('throws a not found error when protect is called, the user is signed out, and is not a page request', async () => {
Expand All @@ -377,7 +377,7 @@ describe('clerkMiddleware(params)', () => {

expect(resp?.status).toEqual(200);
expect(resp?.headers.get(constants.Headers.AuthReason)).toContain('protect-rewrite');
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('throws a not found error when protect is called with RBAC params the user does not fulfill, and is a page request', async () => {
Expand All @@ -400,7 +400,7 @@ describe('clerkMiddleware(params)', () => {

expect(resp?.status).toEqual(200);
expect(resp?.headers.get(constants.Headers.AuthReason)).toContain('protect-rewrite');
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('redirects to unauthenticatedUrl when protect is called with the redirectUrl param, the user is signed out, and is a page request', async () => {
Expand All @@ -424,7 +424,7 @@ describe('clerkMiddleware(params)', () => {
expect(resp?.status).toEqual(307);
expect(resp?.headers.get('location')).toEqual('https://www.clerk.com/hello');
expect(resp?.headers.get(constants.Headers.ClerkRedirectTo)).toEqual('true');
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('redirects to unauthorizedUrl when protect is called with the redirectUrl param, the user does not fulfill the RBAC params, and is a page request', async () => {
Expand Down Expand Up @@ -454,7 +454,7 @@ describe('clerkMiddleware(params)', () => {
expect(resp?.status).toEqual(307);
expect(resp?.headers.get('location')).toEqual('https://www.clerk.com/discover');
expect(resp?.headers.get(constants.Headers.ClerkRedirectTo)).toEqual('true');
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});
});

Expand All @@ -479,7 +479,7 @@ describe('clerkMiddleware(params)', () => {

expect(resp?.status).toEqual(307);
expect(resp?.headers.get('location')).toContain('sign-in');
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('forwards headers from authenticateRequest when auth().protect() is called', async () => {
Expand Down Expand Up @@ -507,7 +507,7 @@ describe('clerkMiddleware(params)', () => {
expect(resp?.headers.get('X-Clerk-Auth')).toEqual('1');
expect(resp?.headers.get('Set-Cookie')).toEqual('session=;');
expect(resp?.headers.get('location')).toContain('sign-in');
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('redirects to unauthenticatedUrl when protect is called with the unauthenticatedUrl param, the user is signed out, and is a page request', async () => {
Expand All @@ -534,7 +534,7 @@ describe('clerkMiddleware(params)', () => {
expect(resp?.status).toEqual(307);
expect(resp?.headers.get('location')).toContain('https://www.clerk.com/unauthenticatedUrl');
expect(resp?.headers.get(constants.Headers.ClerkRedirectTo)).toEqual('true');
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('redirects to unauthorizedUrl when protect is called with the unauthorizedUrl param, the user is signed in but does not have permissions, and is a page request', async () => {
Expand Down Expand Up @@ -564,7 +564,7 @@ describe('clerkMiddleware(params)', () => {
expect(resp?.status).toEqual(307);
expect(resp?.headers.get('location')).toContain('https://www.clerk.com/unauthorizedUrl');
expect(resp?.headers.get(constants.Headers.ClerkRedirectTo)).toEqual('true');
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});
});
});
Expand Down Expand Up @@ -592,7 +592,7 @@ describe('Dev Browser JWT when redirecting to cross origin for page requests', f
expect(resp?.headers.get('location')).toEqual(
'https://accounts.included.katydid-92.lcl.dev/sign-in?redirect_url=https%3A%2F%2Fwww.clerk.com%2Fprotected',
);
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('appends the Dev Browser JWT to the search when cookie __clerk_db_jwt exists and location is an Account Portal URL', async () => {
Expand All @@ -616,7 +616,7 @@ describe('Dev Browser JWT when redirecting to cross origin for page requests', f
expect(resp?.headers.get('location')).toEqual(
'https://accounts.included.katydid-92.lcl.dev/sign-in?redirect_url=https%3A%2F%2Fwww.clerk.com%2Fprotected&__clerk_db_jwt=test_jwt',
);
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});

it('does NOT append the Dev Browser JWT if x-clerk-redirect-to header is not set (user-returned redirect)', async () => {
Expand All @@ -642,6 +642,6 @@ describe('Dev Browser JWT when redirecting to cross origin for page requests', f
expect(resp?.headers.get('location')).toEqual(
'https://accounts.included.katydid-92.lcl.dev/sign-in?redirect_url=https%3A%2F%2Fwww.clerk.com%2Fprotected',
);
expect(clerkClient.authenticateRequest).toBeCalled();
expect(clerkClient().authenticateRequest).toBeCalled();
});
});
Loading