Skip to content

Commit

Permalink
chore(nextjs): Improve experience when swapping keys on Keyless mode
Browse files Browse the repository at this point in the history
  • Loading branch information
panteliselef committed Dec 16, 2024
1 parent dcd2f39 commit 99f8850
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/young-beans-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/nextjs': patch
---

Improve experience when swapping keys on Keyless mode.
2 changes: 2 additions & 0 deletions packages/nextjs/src/server/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,5 @@ ${verifyMessage}`;
export const authSignatureInvalid = `Clerk: Unable to verify request, this usually means the Clerk middleware did not run. Ensure Clerk's middleware is properly integrated and matches the current route. For more information, see: https://clerk.com/docs/references/nextjs/clerk-middleware. (code=auth_signature_invalid)`;

export const encryptionKeyInvalid = `Clerk: Unable to decrypt request data, this usually means the encryption key is invalid. Ensure the encryption key is properly set. For more information, see: https://clerk.com/docs/references/nextjs/clerk-middleware#dynamic-keys. (code=encryption_key_invalid)`;

export const encryptionKeyInvalidDev = `Clerk: Unable to decrypt request data.\n\nRefresh the page if your .env file was just updated. In the issue persists ensure the encryption key is valid and properly set.\n\nFor more information, see: https://clerk.com/docs/references/nextjs/clerk-middleware#dynamic-keys. (code=encryption_key_invalid)`;
39 changes: 35 additions & 4 deletions packages/nextjs/src/server/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@ import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';

import { constants as nextConstants } from '../constants';
import { canUseKeyless__server } from '../utils/feature-flags';
import { DOMAIN, ENCRYPTION_KEY, IS_SATELLITE, PROXY_URL, SECRET_KEY, SIGN_IN_URL } from './constants';
import { authSignatureInvalid, encryptionKeyInvalid, missingDomainAndProxy, missingSignInUrlInDev } from './errors';
import {
authSignatureInvalid,
encryptionKeyInvalid,
encryptionKeyInvalidDev,
missingDomainAndProxy,
missingSignInUrlInDev,
} from './errors';
import { errorThrower } from './errorThrower';
import type { RequestLike } from './types';

Expand Down Expand Up @@ -280,10 +287,34 @@ export function decryptClerkRequestData(
: ENCRYPTION_KEY || SECRET_KEY || KEYLESS_ENCRYPTION_KEY;

try {
const decryptedBytes = AES.decrypt(encryptedRequestData, maybeKeylessEncryptionKey);
const encoded = decryptedBytes.toString(encUtf8);
return JSON.parse(encoded);
return decryptData(encryptedRequestData, maybeKeylessEncryptionKey);
} catch (err) {
/**
* There is a great chance when running on Keyless mode that the above fails,
* because the keys hot-swapped and the Next.js dev server has not yet fully rebuilt middleware and routes.
*
* Attempt one more time with the default dummy value.
*/
if (canUseKeyless__server) {
try {
return decryptData(encryptedRequestData, KEYLESS_ENCRYPTION_KEY);
} catch (e) {
throwInvalidEncryptionKey();
}
}
throwInvalidEncryptionKey();
}
}

function throwInvalidEncryptionKey(): never {
if (isProductionEnvironment()) {
throw new Error(encryptionKeyInvalid);
}
throw new Error(encryptionKeyInvalidDev);
}

function decryptData(data: string, key: string) {
const decryptedBytes = AES.decrypt(data, key);
const encoded = decryptedBytes.toString(encUtf8);
return JSON.parse(encoded);
}

0 comments on commit 99f8850

Please sign in to comment.