From f9fb0f695a255feb93594c87deeb34411a6562f6 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Tue, 29 Apr 2025 19:47:05 -0300 Subject: [PATCH 1/3] Introduce `treatPendingAsSignedOut` to `getAuth` --- packages/astro/src/server/get-auth.ts | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/astro/src/server/get-auth.ts b/packages/astro/src/server/get-auth.ts index 7444db0657c..38056103385 100644 --- a/packages/astro/src/server/get-auth.ts +++ b/packages/astro/src/server/get-auth.ts @@ -1,6 +1,7 @@ import type { AuthObject } from '@clerk/backend'; import { AuthStatus, signedInAuthObject, signedOutAuthObject } from '@clerk/backend/internal'; import { decodeJwt } from '@clerk/backend/jwt'; +import type { PendingSessionOptions } from '@clerk/types'; import type { APIContext } from 'astro'; import { getSafeEnv } from './get-safe-env'; @@ -9,7 +10,11 @@ import { getAuthKeyFromRequest } from './utils'; export type GetAuthReturn = AuthObject; export const createGetAuth = ({ noAuthStatusMessage }: { noAuthStatusMessage: string }) => { - return (req: Request, locals: APIContext['locals'], opts?: { secretKey?: string }): GetAuthReturn => { + return ( + req: Request, + locals: APIContext['locals'], + { treatPendingAsSignedOut = true, ...opts }: { secretKey?: string } & PendingSessionOptions = {}, + ): GetAuthReturn => { // When the auth status is set, we trust that the middleware has already run // Then, we don't have to re-verify the JWT here, // we can just strip out the claims manually. @@ -31,13 +36,21 @@ export const createGetAuth = ({ noAuthStatusMessage }: { noAuthStatusMessage: st authReason, }; + let authObject; + if (authStatus !== AuthStatus.SignedIn) { - return signedOutAuthObject(options); + authObject = signedOutAuthObject(options); } const jwt = decodeJwt(authToken as string); - // @ts-expect-error - TODO: Align types - return signedInAuthObject(options, jwt.raw.text, jwt.payload); + // @ts-expect-error -- Restrict parameter type of options to only list what's needed + authObject = signedInAuthObject(options, jwt.raw.text, jwt.payload); + + if (treatPendingAsSignedOut && authObject.sessionStatus === 'pending') { + authObject = signedOutAuthObject(options); + } + + return authObject; }; }; From d952599c9be6cadc6dc31ceda48ca77b5ffb6bd0 Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Wed, 30 Apr 2025 12:33:17 -0300 Subject: [PATCH 2/3] Pass `treatPendingAsSignedOut` to `auth` on `clerkMiddleware` --- .changeset/sixty-carpets-stare.md | 20 +++++++++++++++++++ packages/astro/src/server/clerk-middleware.ts | 5 +++-- packages/astro/src/server/get-auth.ts | 10 ++++------ 3 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 .changeset/sixty-carpets-stare.md diff --git a/.changeset/sixty-carpets-stare.md b/.changeset/sixty-carpets-stare.md new file mode 100644 index 00000000000..dd9a9939638 --- /dev/null +++ b/.changeset/sixty-carpets-stare.md @@ -0,0 +1,20 @@ +--- +'@clerk/astro': patch +--- + +Introduce `treatPendingAsSignedOut` option to `getAuth` and `auth` from `clerkMiddleware` + +```ts +const { userId } = getAuth(req, locals, { treatPendingAsSignedOut: false }) +``` + +```ts +clerkMiddleware((auth, context) => { + const { redirectToSignIn, userId } = auth({ treatPendingAsSignedOut: false }) + + // Both `active` and `pending` sessions will be treated as authenticated when `treatPendingAsSignedOut` is false + if (!userId && isProtectedRoute(context.request)) { + return redirectToSignIn() + } +}) +``` diff --git a/packages/astro/src/server/clerk-middleware.ts b/packages/astro/src/server/clerk-middleware.ts index d4aa1cb64ea..9aa91a5ee5d 100644 --- a/packages/astro/src/server/clerk-middleware.ts +++ b/packages/astro/src/server/clerk-middleware.ts @@ -5,6 +5,7 @@ import { isDevelopmentFromSecretKey } from '@clerk/shared/keys'; import { handleNetlifyCacheInDevInstance } from '@clerk/shared/netlifyCacheHandler'; import { isHttpOrHttps } from '@clerk/shared/proxy'; import { handleValueOrFn } from '@clerk/shared/utils'; +import type { PendingSessionOptions } from '@clerk/types'; import type { APIContext } from 'astro'; import { authAsyncStorage } from '#async-local-storage'; @@ -244,8 +245,8 @@ function decorateAstroLocal(clerkRequest: ClerkRequest, context: APIContext, req context.locals.authStatus = status; context.locals.authMessage = message; context.locals.authReason = reason; - context.locals.auth = () => { - const authObject = getAuth(clerkRequest, context.locals); + context.locals.auth = ({ treatPendingAsSignedOut }: PendingSessionOptions = {}) => { + const authObject = getAuth(clerkRequest, context.locals, { treatPendingAsSignedOut }); const clerkUrl = clerkRequest.clerkUrl; diff --git a/packages/astro/src/server/get-auth.ts b/packages/astro/src/server/get-auth.ts index 38056103385..0f6e45162ee 100644 --- a/packages/astro/src/server/get-auth.ts +++ b/packages/astro/src/server/get-auth.ts @@ -36,18 +36,16 @@ export const createGetAuth = ({ noAuthStatusMessage }: { noAuthStatusMessage: st authReason, }; - let authObject; - if (authStatus !== AuthStatus.SignedIn) { - authObject = signedOutAuthObject(options); + return signedOutAuthObject(options); } const jwt = decodeJwt(authToken as string); - // @ts-expect-error -- Restrict parameter type of options to only list what's needed - authObject = signedInAuthObject(options, jwt.raw.text, jwt.payload); + // @ts-expect-error - TODO: Align types + const authObject = signedInAuthObject(options, jwt.raw.text, jwt.payload); if (treatPendingAsSignedOut && authObject.sessionStatus === 'pending') { - authObject = signedOutAuthObject(options); + return signedOutAuthObject(options); } return authObject; From 3e4719fd583be64a80ce2472b4a4285117c8e0ac Mon Sep 17 00:00:00 2001 From: Laura Beatris <48022589+LauraBeatris@users.noreply.github.com> Date: Mon, 5 May 2025 16:57:13 -0300 Subject: [PATCH 3/3] Update changeset --- .changeset/sixty-carpets-stare.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.changeset/sixty-carpets-stare.md b/.changeset/sixty-carpets-stare.md index dd9a9939638..3d2cd74eead 100644 --- a/.changeset/sixty-carpets-stare.md +++ b/.changeset/sixty-carpets-stare.md @@ -1,10 +1,18 @@ --- -'@clerk/astro': patch +'@clerk/astro': minor --- Introduce `treatPendingAsSignedOut` option to `getAuth` and `auth` from `clerkMiddleware` +By default, `treatPendingAsSignedOut` is set to `true`, which means pending sessions are treated as signed-out. You can set this option to `false` to treat pending sessions as authenticated. + +```ts +// `pending` sessions will be treated as signed-out by default +const { userId } = getAuth(req, locals) +``` + ```ts +// Both `active` and `pending` sessions will be treated as authenticated when `treatPendingAsSignedOut` is false const { userId } = getAuth(req, locals, { treatPendingAsSignedOut: false }) ```