From a2a1b9e5bb35a0462c98ffcf044d3d0ec48b44b0 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 16 Jun 2023 11:04:59 -0700 Subject: [PATCH 01/14] fix(clerk) add alternative decoder --- .../auth-providers/clerk/api/src/decoder.ts | 39 +++++++++++++++++++ .../auth-providers/clerk/api/src/index.ts | 2 +- .../clerk/setup/src/setupHandler.ts | 7 +--- .../src/templates/api/lib/auth.ts.template | 12 ++---- 4 files changed, 46 insertions(+), 14 deletions(-) diff --git a/packages/auth-providers/clerk/api/src/decoder.ts b/packages/auth-providers/clerk/api/src/decoder.ts index 8335fd25be66..a56422505062 100644 --- a/packages/auth-providers/clerk/api/src/decoder.ts +++ b/packages/auth-providers/clerk/api/src/decoder.ts @@ -1,5 +1,8 @@ import { Decoder } from '@redwoodjs/api' +/** + * @deprecated This function will be removed; it uses uses a rate-limited API. Use `jwtAuthDecoder` instead. + */ export const authDecoder: Decoder = async (token: string, type: string) => { if (type !== 'clerk') { return null @@ -34,3 +37,39 @@ export const authDecoder: Decoder = async (token: string, type: string) => { return Promise.reject(error) } } + +export const jwtAuthDecoder: Decoder = async (token: string, type: string) => { + if (type !== 'clerk') { + return null + } + + const { verifyToken } = await import('@clerk/clerk-sdk-node') + + try { + const issuer = (iss: string) => + iss.startsWith('https://clerk.') || iss.includes('.clerk.accounts') + + const jwtPayload = await verifyToken(token, { + issuer, + apiUrl: process.env.CLERK_API_URL || 'https://api.clerk.dev', + jwtKey: process.env.CLERK_JWT_KEY, + apiKey: process.env.CLERK_API_KEY, + secretKey: process.env.CLERK_SECRET_KEY, + }) + + if (!jwtPayload.sub) { + return Promise.reject(new Error('Session invalid')) + } + + // @ts-expect-error need to to type this + const roles = jwtPayload.sessionClaims.publicMetadata['roles'] ?? [] + + return { + ...jwtPayload, + roles: roles, + } + } catch (error) { + console.error(error) + return Promise.reject(error) + } +} diff --git a/packages/auth-providers/clerk/api/src/index.ts b/packages/auth-providers/clerk/api/src/index.ts index ead5bdde8676..21912411006e 100644 --- a/packages/auth-providers/clerk/api/src/index.ts +++ b/packages/auth-providers/clerk/api/src/index.ts @@ -1 +1 @@ -export { authDecoder } from './decoder' +export { authDecoder, jwtAuthDecoder } from './decoder' diff --git a/packages/auth-providers/clerk/setup/src/setupHandler.ts b/packages/auth-providers/clerk/setup/src/setupHandler.ts index ba42638f863e..f83e5b444d6d 100644 --- a/packages/auth-providers/clerk/setup/src/setupHandler.ts +++ b/packages/auth-providers/clerk/setup/src/setupHandler.ts @@ -13,7 +13,7 @@ export const handler = async ({ force: forceArg }: Args) => { standardAuthHandler({ basedir: __dirname, forceArg, - authDecoderImport: `import { authDecoder } from '@redwoodjs/auth-clerk-api'`, + authDecoderImport: `import { jwtAuthDecoder as authDecoder } from '@redwoodjs/auth-clerk-api'`, provider: 'clerk', webPackages: [ '@clerk/clerk-react@^4', @@ -26,9 +26,6 @@ export const handler = async ({ force: forceArg }: Args) => { '```title=".env"', 'CLERK_PUBLISHABLE_KEY="..."', 'CLERK_SECRET_KEY="..."', - 'CLERK_JWT_KEY="-----BEGIN PUBLIC KEY-----', - '...', - '-----END PUBLIC KEY-----"', '```', '', `You can find their values under "API Keys" on your Clerk app's dashboard.`, @@ -36,7 +33,7 @@ export const handler = async ({ force: forceArg }: Args) => { '', '```toml title="redwood.toml"', 'includeEnvironmentVariables = [', - ' "CLERK_PUBLISHABLE_KEY"', + ' "CLERK_PUBLISHABLE_KEY,"', ']', '```', '', diff --git a/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template b/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template index 92f1ee761481..55e8502941a9 100644 --- a/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template +++ b/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template @@ -27,16 +27,12 @@ export const getCurrentUser = async ( return null } - const { roles } = parseJWT({ decoded }) + const { roles, ...user } = parseJWT({ decoded }) - // Remove privateMetadata property from CurrentUser as it should not be accessible on the web - const { privateMetadata, ...userWithoutPrivateMetadata } = decoded - - if (roles) { - return { ...userWithoutPrivateMetadata, roles } + return { + ...user, + ...(roles && { roles }) } - - return { ...userWithoutPrivateMetadata } } /** From 7dfda7596ce0245995e69b6faaf3a048a7574b74 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 16 Jun 2023 11:35:30 -0700 Subject: [PATCH 02/14] Update packages/auth-providers/clerk/api/src/decoder.ts Co-authored-by: Charlie Ray --- packages/auth-providers/clerk/api/src/decoder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/auth-providers/clerk/api/src/decoder.ts b/packages/auth-providers/clerk/api/src/decoder.ts index a56422505062..25f13d3d01ce 100644 --- a/packages/auth-providers/clerk/api/src/decoder.ts +++ b/packages/auth-providers/clerk/api/src/decoder.ts @@ -1,7 +1,7 @@ import { Decoder } from '@redwoodjs/api' /** - * @deprecated This function will be removed; it uses uses a rate-limited API. Use `jwtAuthDecoder` instead. + * @deprecated This function will be removed; it uses a rate-limited API. Use `jwtAuthDecoder` instead. */ export const authDecoder: Decoder = async (token: string, type: string) => { if (type !== 'clerk') { From 32d78b9057a5ca3d362150f9ef9af52a1aad1e6d Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 16 Jun 2023 11:35:37 -0700 Subject: [PATCH 03/14] Update packages/auth-providers/clerk/api/src/decoder.ts Co-authored-by: Charlie Ray --- packages/auth-providers/clerk/api/src/decoder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/auth-providers/clerk/api/src/decoder.ts b/packages/auth-providers/clerk/api/src/decoder.ts index 25f13d3d01ce..b76b9c8f1356 100644 --- a/packages/auth-providers/clerk/api/src/decoder.ts +++ b/packages/auth-providers/clerk/api/src/decoder.ts @@ -61,7 +61,7 @@ export const jwtAuthDecoder: Decoder = async (token: string, type: string) => { return Promise.reject(new Error('Session invalid')) } - // @ts-expect-error need to to type this + // @ts-expect-error need to type this const roles = jwtPayload.sessionClaims.publicMetadata['roles'] ?? [] return { From 22a8d4630836d0230349b419ac5b375e8937ee78 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 16 Jun 2023 11:51:23 -0700 Subject: [PATCH 04/14] add `id` for backwards compatibility --- packages/auth-providers/clerk/api/src/decoder.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/auth-providers/clerk/api/src/decoder.ts b/packages/auth-providers/clerk/api/src/decoder.ts index b76b9c8f1356..c092c994d0fe 100644 --- a/packages/auth-providers/clerk/api/src/decoder.ts +++ b/packages/auth-providers/clerk/api/src/decoder.ts @@ -66,6 +66,7 @@ export const jwtAuthDecoder: Decoder = async (token: string, type: string) => { return { ...jwtPayload, + id: jwtPayload.sub, roles: roles, } } catch (error) { From ec9ea36a5e9e1cf2cfade4a477b7f9973682d73b Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 16 Jun 2023 12:05:34 -0700 Subject: [PATCH 05/14] fix prettier error --- .../clerk/setup/src/templates/api/lib/auth.ts.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template b/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template index 55e8502941a9..173a210d4cd2 100644 --- a/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template +++ b/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template @@ -31,7 +31,7 @@ export const getCurrentUser = async ( return { ...user, - ...(roles && { roles }) + ...(roles && { roles }), } } From 7a4bdb5784abd499bf50cb3132e81d19f900a490 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 16 Jun 2023 12:24:08 -0700 Subject: [PATCH 06/14] extend type for jwt payload --- packages/auth-providers/clerk/api/src/decoder.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/auth-providers/clerk/api/src/decoder.ts b/packages/auth-providers/clerk/api/src/decoder.ts index c092c994d0fe..6fa6c758ee0a 100644 --- a/packages/auth-providers/clerk/api/src/decoder.ts +++ b/packages/auth-providers/clerk/api/src/decoder.ts @@ -45,11 +45,21 @@ export const jwtAuthDecoder: Decoder = async (token: string, type: string) => { const { verifyToken } = await import('@clerk/clerk-sdk-node') + // We expect the user to have customized the JWT payload to include the + // `roles` claim. If they haven't, we'll just return an empty array. + type RedwoodJwtPayload = Awaited> & { + sessionClaims?: { + publicMetadata?: { + roles?: string[] + } + } + } + try { const issuer = (iss: string) => iss.startsWith('https://clerk.') || iss.includes('.clerk.accounts') - const jwtPayload = await verifyToken(token, { + const jwtPayload: RedwoodJwtPayload = await verifyToken(token, { issuer, apiUrl: process.env.CLERK_API_URL || 'https://api.clerk.dev', jwtKey: process.env.CLERK_JWT_KEY, @@ -61,8 +71,7 @@ export const jwtAuthDecoder: Decoder = async (token: string, type: string) => { return Promise.reject(new Error('Session invalid')) } - // @ts-expect-error need to type this - const roles = jwtPayload.sessionClaims.publicMetadata['roles'] ?? [] + const roles = jwtPayload.sessionClaims?.publicMetadata?.['roles'] ?? [] return { ...jwtPayload, From e6a8edc8b08ef5de0cd37cd4b9f225af07435117 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 16 Jun 2023 12:29:17 -0700 Subject: [PATCH 07/14] simplify decoder --- packages/auth-providers/clerk/api/src/decoder.ts | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/packages/auth-providers/clerk/api/src/decoder.ts b/packages/auth-providers/clerk/api/src/decoder.ts index 6fa6c758ee0a..37a9109a3337 100644 --- a/packages/auth-providers/clerk/api/src/decoder.ts +++ b/packages/auth-providers/clerk/api/src/decoder.ts @@ -45,21 +45,11 @@ export const jwtAuthDecoder: Decoder = async (token: string, type: string) => { const { verifyToken } = await import('@clerk/clerk-sdk-node') - // We expect the user to have customized the JWT payload to include the - // `roles` claim. If they haven't, we'll just return an empty array. - type RedwoodJwtPayload = Awaited> & { - sessionClaims?: { - publicMetadata?: { - roles?: string[] - } - } - } - try { const issuer = (iss: string) => iss.startsWith('https://clerk.') || iss.includes('.clerk.accounts') - const jwtPayload: RedwoodJwtPayload = await verifyToken(token, { + const jwtPayload = await verifyToken(token, { issuer, apiUrl: process.env.CLERK_API_URL || 'https://api.clerk.dev', jwtKey: process.env.CLERK_JWT_KEY, @@ -71,12 +61,9 @@ export const jwtAuthDecoder: Decoder = async (token: string, type: string) => { return Promise.reject(new Error('Session invalid')) } - const roles = jwtPayload.sessionClaims?.publicMetadata?.['roles'] ?? [] - return { ...jwtPayload, id: jwtPayload.sub, - roles: roles, } } catch (error) { console.error(error) From ff0df16293e97cbaf860119855952c9776ab11fd Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 16 Jun 2023 12:47:55 -0700 Subject: [PATCH 08/14] duplicate test for new decoder --- .../clerk/api/src/__tests__/clerk.test.ts | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/auth-providers/clerk/api/src/__tests__/clerk.test.ts b/packages/auth-providers/clerk/api/src/__tests__/clerk.test.ts index 50643326c471..4c870eb95545 100644 --- a/packages/auth-providers/clerk/api/src/__tests__/clerk.test.ts +++ b/packages/auth-providers/clerk/api/src/__tests__/clerk.test.ts @@ -1,6 +1,6 @@ import type { APIGatewayProxyEvent, Context as LambdaContext } from 'aws-lambda' -import { authDecoder } from '../decoder' +import { authDecoder, jwtAuthDecoder } from '../decoder' const req = { event: {} as APIGatewayProxyEvent, @@ -18,14 +18,32 @@ afterAll(() => { console.error = consoleError }) -test('returns null for unsupported type', async () => { - const decoded = await authDecoder('token', 'netlify', req) +describe('deprecated authDecoder', () => { + test('returns null for unsupported type', async () => { + const decoded = await authDecoder('token', 'netlify', req) - expect(decoded).toBe(null) + expect(decoded).toBe(null) + }) + + test('rejects when the token is invalid', async () => { + process.env.CLERK_JWT_KEY = 'jwt-key' + + await expect(authDecoder('invalid-token', 'clerk', req)).rejects.toThrow() + }) }) -test('rejects when the token is invalid', async () => { - process.env.CLERK_JWT_KEY = 'jwt-key' +describe('jwtAuthDecoder', () => { + test('returns null for unsupported type', async () => { + const decoded = await jwtAuthDecoder('token', 'netlify', req) + + expect(decoded).toBe(null) + }) + + test('rejects when the token is invalid', async () => { + process.env.CLERK_JWT_KEY = 'jwt-key' - await expect(authDecoder('invalid-token', 'clerk', req)).rejects.toThrow() + await expect( + jwtAuthDecoder('invalid-token', 'clerk', req) + ).rejects.toThrow() + }) }) From edc897fa7dd0e78b7b6770df830ca78722e2d166 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 16 Jun 2023 12:57:38 -0700 Subject: [PATCH 09/14] fix set up notes --- packages/auth-providers/clerk/setup/src/setupHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/auth-providers/clerk/setup/src/setupHandler.ts b/packages/auth-providers/clerk/setup/src/setupHandler.ts index f83e5b444d6d..865d5bb1281e 100644 --- a/packages/auth-providers/clerk/setup/src/setupHandler.ts +++ b/packages/auth-providers/clerk/setup/src/setupHandler.ts @@ -21,7 +21,7 @@ export const handler = async ({ force: forceArg }: Args) => { ], apiPackages: [`@redwoodjs/auth-clerk-api@${version}`], notes: [ - "You'll need to add three env vars to your .env file:", + "You'll need to add two env vars to your .env file:", '', '```title=".env"', 'CLERK_PUBLISHABLE_KEY="..."', From 1a5417cfe1e99dd366cb33b9c3550a4829366edb Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 16 Jun 2023 19:32:14 -0700 Subject: [PATCH 10/14] remove `parseJWT`; only return `id` in the template --- .../setup/src/templates/api/lib/auth.ts.template | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template b/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template index 173a210d4cd2..46ac56367275 100644 --- a/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template +++ b/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template @@ -1,12 +1,11 @@ -import { parseJWT } from '@redwoodjs/api' import { AuthenticationError, ForbiddenError } from '@redwoodjs/graphql-server' import { logger } from 'src/lib/logger' /** - * getCurrentUser returns the user information together with - * an optional collection of roles used by requireAuth() to check - * if the user is authenticated or has role-based access + * getCurrentUser returns the user information. + * Once you're ready you can also return a collection of roles + * for `requireAuth` and the Router to use. * * @param decoded - The decoded access token containing user info and JWT claims like `sub`. Note could be null. * @param { token, SupportedAuthTypes type } - The access token itself as well as the auth provider type @@ -27,12 +26,10 @@ export const getCurrentUser = async ( return null } - const { roles, ...user } = parseJWT({ decoded }) + const { id, ...rest } = decoded - return { - ...user, - ...(roles && { roles }), - } + // Be careful to only return information that should be accessible on the web side. + return { id } } /** From ed528379c3bdcefa20a1f535d60e71a2525b31be Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 16 Jun 2023 19:38:13 -0700 Subject: [PATCH 11/14] lint fix --- .../clerk/setup/src/templates/api/lib/auth.ts.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template b/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template index 46ac56367275..10339861cb1b 100644 --- a/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template +++ b/packages/auth-providers/clerk/setup/src/templates/api/lib/auth.ts.template @@ -26,7 +26,7 @@ export const getCurrentUser = async ( return null } - const { id, ...rest } = decoded + const { id, ..._rest } = decoded // Be careful to only return information that should be accessible on the web side. return { id } From 092a326b51fdb4fe74ad85aa4e51bb7060fb43b2 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Thu, 22 Jun 2023 15:15:49 -0700 Subject: [PATCH 12/14] update docs --- docs/docs/auth/clerk.md | 56 ++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/docs/docs/auth/clerk.md b/docs/docs/auth/clerk.md index f81dfd2fdfc1..da21ebfc5d6c 100644 --- a/docs/docs/auth/clerk.md +++ b/docs/docs/auth/clerk.md @@ -4,6 +4,16 @@ sidebar_label: Clerk # Clerk Authentication +:::caution Did you set up Clerk a while ago? + +If you set up Clerk a while ago, you may be using a deprecated authDecoder that's subject to rate limiting. +This decoder will be removed in the next major. +There's a new decoder you can use now. +See the migration guide for how to upgrade now. + +::: + + To get started, run the setup command: ```text @@ -12,7 +22,7 @@ yarn rw setup auth clerk This installs all the packages, writes all the files, and makes all the code modifications you need. For a detailed explanation of all the api- and web-side changes that aren't exclusive to Clerk, see the top-level [Authentication](../authentication.md) doc. -There's one Clerk-specific thing we'll get to, but for now, let's focus on Clerk's side of things. +But for now, let's focus on Clerk's side of things. If you don't have a Clerk account yet, now's the time to make one: navigate to https://clerk.dev, sign up, and create an application. The defaults are good enough to get us going, but feel free to configure things as you wish. @@ -27,9 +37,8 @@ How you get your API keys to production depends on your deploy provider. ::: -We're looking for two API keys. -Head over to the "Developers" section in the nav on the left and click "API Keys". Finally select RedwoodJS in the Framework dropdown in the Quick Copy section. -Do as it says and copy the two keys into your project's `.env` file: +After you create the application, you should be redirected to its dashboard where you should see the RedwoodJS logo. +Click on it and copy the two API keys it shows into your project's `.env` file: ```bash title=".env" CLERK_PUBLISHABLE_KEY="..." @@ -41,7 +50,9 @@ Lastly, in your project's `redwood.toml` file, include `CLERK_PUBLISHABLE_KEY` i ```toml title="redwood.toml" [web] # ... - includeEnvironmentVariables = ["CLERK_PUBLISHABLE_KEY"] + includeEnvironmentVariables = [ + "CLERK_PUBLISHABLE_KEY", + ] ``` That should be enough; now, things should just work. @@ -71,15 +82,28 @@ Clicking sign up should open a sign-up box: After you sign up, you should see `{"isAuthenticated":true}` on the page. -## Deep dive: the `ClerkStatusUpdater` component +## Customizing the session token + +There's not a lot to the default session token. +Besides the standard claims, the only thing it really has is the user's `id`. +Eventually, you'll want to customize it so that you can get back more information from Clerk. +You can do so by navigating to the "Sessions" section in the nav on the left, then clicking on "Customize session token": -At the start of this doc, we said that there's one Clerk-specific thing worth noting. -We'll discuss it here, but feel free to skip this section if you'd like—this is all extracurricular. +![clerk_customize_session_token](https://github.com/redwoodjs/redwood/assets/32992335/6d30c616-b4d2-4b44-971b-8addf3b79e5a) -Clerk is a bit unlike the other auth providers Redwood integrates with in that it puts an instance of its client SDK on the browser's `window` object. -That means we have to wait for it to be ready. -With other providers, we instantiate their client SDK in `web/src/auth.ts`, then pass it to `createAuth`. -Not so with Clerk—instead we use special Clerk components and hooks, like `ClerkLoaded` and `useUser`, to update Redwood's auth context with the client when it's ready. +As long as you're using the `clerkJwtDecoder` +all the properties you add will be available to the `getCurrentUser` function: + +```ts title="api/src/lib/auth.ts" +export const getCurrentUser = async ( + decoded, // 👈 All the claims you add will be available on the `decoded` object + // ... +) => { + decoded.myClaim... + + // ... +} +```` ## Avoiding feature duplication @@ -87,3 +111,11 @@ Redwood's Clerk integration is based on [Clerk's React SDK](https://clerk.dev/do This means that there's some duplication between the features in the SDK and the ones in `@redwoodjs/auth-clerk-web`. For example, the SDK ha a `SignedOut` component that redirects a user away from a private page—very much like wrapping a route with Redwood's `Private` component. We recommend you use Redwood's way of doing things as much as possible since it's much more likely to get along with the rest of the framework. + +## Deep dive: the ClerkStatusUpdater component + +For Clerk, there's a bit more going on in the `web/src/auth.tsx` file than other auth providers. +This is because Clerk is a bit unlike the other auth providers Redwood integrates with in that it puts an instance of its client SDK on the browser's `window` object. +That means Redwood has to wait for it to be ready. +With other providers, Redwood instantiate their client SDK in `web/src/auth.ts{x}`, then passes it to `createAuth`. +With Clerk, instead Redwood uses Clerk components and hooks, like `ClerkLoaded` and `useUser`, to update Redwood's auth context with the client when it's ready. From 8a3d12e00b6f4cfed70832c29897a1195bf299d7 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Thu, 22 Jun 2023 15:21:09 -0700 Subject: [PATCH 13/14] fix typos, add link --- docs/docs/auth/clerk.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/docs/auth/clerk.md b/docs/docs/auth/clerk.md index da21ebfc5d6c..ed71df136f8e 100644 --- a/docs/docs/auth/clerk.md +++ b/docs/docs/auth/clerk.md @@ -6,10 +6,10 @@ sidebar_label: Clerk :::caution Did you set up Clerk a while ago? -If you set up Clerk a while ago, you may be using a deprecated authDecoder that's subject to rate limiting. +If you set up Clerk a while ago, you may be using a deprecated `authDecoder` that's subject to rate limiting. This decoder will be removed in the next major. -There's a new decoder you can use now. -See the migration guide for how to upgrade now. +There's a new decoder you can use right now! +See the [migration guide](https://github.com/redwoodjs/redwood/releases/tag/v5.3.2) for how to upgrade. ::: @@ -87,7 +87,7 @@ After you sign up, you should see `{"isAuthenticated":true}` on the page. There's not a lot to the default session token. Besides the standard claims, the only thing it really has is the user's `id`. Eventually, you'll want to customize it so that you can get back more information from Clerk. -You can do so by navigating to the "Sessions" section in the nav on the left, then clicking on "Customize session token": +You can do so by navigating to the "Sessions" section in the nav on the left, then clicking on "Edit" in the "Customize session token" box: ![clerk_customize_session_token](https://github.com/redwoodjs/redwood/assets/32992335/6d30c616-b4d2-4b44-971b-8addf3b79e5a) @@ -112,10 +112,10 @@ This means that there's some duplication between the features in the SDK and the For example, the SDK ha a `SignedOut` component that redirects a user away from a private page—very much like wrapping a route with Redwood's `Private` component. We recommend you use Redwood's way of doing things as much as possible since it's much more likely to get along with the rest of the framework. -## Deep dive: the ClerkStatusUpdater component +## Deep dive: the `ClerkStatusUpdater` component -For Clerk, there's a bit more going on in the `web/src/auth.tsx` file than other auth providers. +With Clerk, there's a bit more going on in the `web/src/auth.tsx` file than other auth providers. This is because Clerk is a bit unlike the other auth providers Redwood integrates with in that it puts an instance of its client SDK on the browser's `window` object. That means Redwood has to wait for it to be ready. -With other providers, Redwood instantiate their client SDK in `web/src/auth.ts{x}`, then passes it to `createAuth`. +With other providers, Redwood instantiates their client SDK in `web/src/auth.ts{x}`, then passes it to `createAuth`. With Clerk, instead Redwood uses Clerk components and hooks, like `ClerkLoaded` and `useUser`, to update Redwood's auth context with the client when it's ready. From 32e707c9eac7802b0ff5776dd16f1727c535e4b7 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Thu, 22 Jun 2023 15:26:43 -0700 Subject: [PATCH 14/14] rename to clerkAuthDecoder --- .../auth-providers/clerk/api/src/__tests__/clerk.test.ts | 8 ++++---- packages/auth-providers/clerk/api/src/decoder.ts | 4 ++-- packages/auth-providers/clerk/api/src/index.ts | 2 +- packages/auth-providers/clerk/setup/src/setupHandler.ts | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/auth-providers/clerk/api/src/__tests__/clerk.test.ts b/packages/auth-providers/clerk/api/src/__tests__/clerk.test.ts index 4c870eb95545..d80fe627d223 100644 --- a/packages/auth-providers/clerk/api/src/__tests__/clerk.test.ts +++ b/packages/auth-providers/clerk/api/src/__tests__/clerk.test.ts @@ -1,6 +1,6 @@ import type { APIGatewayProxyEvent, Context as LambdaContext } from 'aws-lambda' -import { authDecoder, jwtAuthDecoder } from '../decoder' +import { authDecoder, clerkAuthDecoder } from '../decoder' const req = { event: {} as APIGatewayProxyEvent, @@ -32,9 +32,9 @@ describe('deprecated authDecoder', () => { }) }) -describe('jwtAuthDecoder', () => { +describe('clerkAuthDecoder', () => { test('returns null for unsupported type', async () => { - const decoded = await jwtAuthDecoder('token', 'netlify', req) + const decoded = await clerkAuthDecoder('token', 'netlify', req) expect(decoded).toBe(null) }) @@ -43,7 +43,7 @@ describe('jwtAuthDecoder', () => { process.env.CLERK_JWT_KEY = 'jwt-key' await expect( - jwtAuthDecoder('invalid-token', 'clerk', req) + clerkAuthDecoder('invalid-token', 'clerk', req) ).rejects.toThrow() }) }) diff --git a/packages/auth-providers/clerk/api/src/decoder.ts b/packages/auth-providers/clerk/api/src/decoder.ts index 37a9109a3337..cb329c89a487 100644 --- a/packages/auth-providers/clerk/api/src/decoder.ts +++ b/packages/auth-providers/clerk/api/src/decoder.ts @@ -1,7 +1,7 @@ import { Decoder } from '@redwoodjs/api' /** - * @deprecated This function will be removed; it uses a rate-limited API. Use `jwtAuthDecoder` instead. + * @deprecated This function will be removed; it uses a rate-limited API. Use `clerkAuthDecoder` instead. */ export const authDecoder: Decoder = async (token: string, type: string) => { if (type !== 'clerk') { @@ -38,7 +38,7 @@ export const authDecoder: Decoder = async (token: string, type: string) => { } } -export const jwtAuthDecoder: Decoder = async (token: string, type: string) => { +export const clerkAuthDecoder: Decoder = async (token: string, type: string) => { if (type !== 'clerk') { return null } diff --git a/packages/auth-providers/clerk/api/src/index.ts b/packages/auth-providers/clerk/api/src/index.ts index 21912411006e..6d1498a92969 100644 --- a/packages/auth-providers/clerk/api/src/index.ts +++ b/packages/auth-providers/clerk/api/src/index.ts @@ -1 +1 @@ -export { authDecoder, jwtAuthDecoder } from './decoder' +export { authDecoder, clerkAuthDecoder } from './decoder' diff --git a/packages/auth-providers/clerk/setup/src/setupHandler.ts b/packages/auth-providers/clerk/setup/src/setupHandler.ts index 865d5bb1281e..f08d9c1406b4 100644 --- a/packages/auth-providers/clerk/setup/src/setupHandler.ts +++ b/packages/auth-providers/clerk/setup/src/setupHandler.ts @@ -13,7 +13,7 @@ export const handler = async ({ force: forceArg }: Args) => { standardAuthHandler({ basedir: __dirname, forceArg, - authDecoderImport: `import { jwtAuthDecoder as authDecoder } from '@redwoodjs/auth-clerk-api'`, + authDecoderImport: `import { clerkAuthDecoder as authDecoder } from '@redwoodjs/auth-clerk-api'`, provider: 'clerk', webPackages: [ '@clerk/clerk-react@^4',