From 6adc9a498a27316ea1e5bcd62780c1e6f7dec110 Mon Sep 17 00:00:00 2001 From: panteliselef Date: Tue, 7 Jan 2025 14:46:21 +0200 Subject: [PATCH] chore(types,nextjs): Handle types in `protect()` --- packages/nextjs/src/app-router/server/auth.ts | 3 +- .../server/__tests__/clerkMiddleware.test.ts | 4 ++ packages/nextjs/src/server/protect.ts | 10 ++++- packages/types/src/session.ts | 40 ++++++++++--------- 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/packages/nextjs/src/app-router/server/auth.ts b/packages/nextjs/src/app-router/server/auth.ts index e8e912cf435..8079e6a8bc1 100644 --- a/packages/nextjs/src/app-router/server/auth.ts +++ b/packages/nextjs/src/app-router/server/auth.ts @@ -52,7 +52,7 @@ export const auth: AuthFn = async () => { return Object.assign(authObject, { redirectToSignIn }); }; -auth.protect = async (...args) => { +auth.protect = async (...args: any[]) => { require('server-only'); const request = await buildRequestLike(); @@ -66,6 +66,5 @@ auth.protect = async (...args) => { redirect, }); - // @ts-expect-error TS flattens all possible combinations of the for AuthProtect signatures in a union. return protect(...args); }; diff --git a/packages/nextjs/src/server/__tests__/clerkMiddleware.test.ts b/packages/nextjs/src/server/__tests__/clerkMiddleware.test.ts index 5d2429fb16b..99bbacd6bee 100644 --- a/packages/nextjs/src/server/__tests__/clerkMiddleware.test.ts +++ b/packages/nextjs/src/server/__tests__/clerkMiddleware.test.ts @@ -117,6 +117,10 @@ describe('ClerkMiddleware type tests', () => { clerkMiddlewareMock(async (auth, _event, _request) => { // @ts-expect-error - system permissions are not allowed (await auth()).has({ permission: 'org:sys_foo' }); + // @ts-expect-error - system permissions are not allowed + await auth.protect(has => has({ permission: 'org:sys_foo' })); + // @ts-expect-error - system permissions are not allowed + await auth.protect({ permission: 'org:sys_foo' }); }); }); diff --git a/packages/nextjs/src/server/protect.ts b/packages/nextjs/src/server/protect.ts index 7e17e37817c..3c683b42216 100644 --- a/packages/nextjs/src/server/protect.ts +++ b/packages/nextjs/src/server/protect.ts @@ -2,8 +2,11 @@ import type { AuthObject } from '@clerk/backend'; import type { RedirectFun, SignedInAuthObject } from '@clerk/backend/internal'; import { constants } from '@clerk/backend/internal'; import type { + CheckAuthorizationFromSessionClaims, + CheckAuthorizationParamsFromSessionClaims, CheckAuthorizationParamsWithCustomPermissions, CheckAuthorizationWithCustomPermissions, + OrganizationCustomPermissionKey, } from '@clerk/types'; import { constants as nextConstants } from '../constants'; @@ -15,10 +18,13 @@ type AuthProtectOptions = { unauthorizedUrl?: string; unauthenticatedUrl?: strin * Throws a Nextjs notFound error if user is not authenticated or authorized. */ export interface AuthProtect { - (params?: CheckAuthorizationParamsWithCustomPermissions, options?: AuthProtectOptions): Promise; +

( + params?: CheckAuthorizationParamsFromSessionClaims

, + options?: AuthProtectOptions, + ): Promise; ( - params?: (has: CheckAuthorizationWithCustomPermissions) => boolean, + params?: (has: CheckAuthorizationFromSessionClaims) => boolean, options?: AuthProtectOptions, ): Promise; diff --git a/packages/types/src/session.ts b/packages/types/src/session.ts index f62bf0d317e..65bc988ab56 100644 --- a/packages/types/src/session.ts +++ b/packages/types/src/session.ts @@ -30,25 +30,6 @@ type DisallowSystemPermissions

= P extends `${OrganizationSyst ? 'System permissions are not included in session claims and cannot be used on the server-side' : P; -/** - * Type guard for server-side authorization checks using session claims. - * System permissions are not allowed since they are not included - * in session claims and cannot be verified on the server side. - */ -export type CheckAuthorizationFromSessionClaims =

( - isAuthorizedParams: WithReverification< - | { - role: OrganizationCustomRoleKey; - permission?: never; - } - | { - role?: never; - permission: DisallowSystemPermissions

; - } - | { role?: never; permission?: never } - >, -) => boolean; - export type CheckAuthorizationFn = (isAuthorizedParams: Params) => boolean; export type CheckAuthorizationWithCustomPermissions = @@ -87,6 +68,27 @@ type CheckAuthorizationParams = WithReverification< } >; +/** + * Type guard for server-side authorization checks using session claims. + * System permissions are not allowed since they are not included + * in session claims and cannot be verified on the server side. + */ +export type CheckAuthorizationFromSessionClaims =

( + isAuthorizedParams: CheckAuthorizationParamsFromSessionClaims

, +) => boolean; + +export type CheckAuthorizationParamsFromSessionClaims

= WithReverification< + | { + role: OrganizationCustomRoleKey; + permission?: never; + } + | { + role?: never; + permission: DisallowSystemPermissions

; + } + | { role?: never; permission?: never } +>; + export interface SessionResource extends ClerkResource { id: string; status: SessionStatus;