feat: migrate from Clerk to Auth0 authentication#355
feat: migrate from Clerk to Auth0 authentication#355saddlepaddle wants to merge 1 commit intomainfrom
Conversation
- Create @superset/auth0 package with server/client exports - Update all apps (web, api, admin, marketing) to use Auth0 - Replace ClerkProvider with Auth0Provider in layouts - Update middleware to use auth0.middleware() - Replace Clerk env vars with Auth0 env vars in turbo.jsonc - Update GitHub workflows with Auth0 secrets - Rename users.clerkId to users.auth0Id in schema - Remove Clerk webhook handler - Remove sso-callback pages (Auth0 handles callbacks internally) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
WalkthroughThis pull request performs a comprehensive migration of the codebase's authentication system from Clerk to Auth0. The changes span all applications (admin, api, marketing, web), introduce a new Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Areas requiring extra attention during review:
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/trpc/src/router/organization.ts (1)
60-77: Add error handling for missing user lookup.The type safety concern is resolved—
ctx.session.user.subis properly typed as a non-nullable string becauseprotectedProcedureguarantees aSignedInSessioncontext.However, the silent failure issue is valid. Other procedures in the codebase (e.g.,
taskRouter.create,adminProcedure) explicitly throw an error when the user lookup fails. Currently, the organization creation proceeds without a corresponding member relationship if the user is not found, leaving an orphaned organization.Add the missing error check to align with existing patterns:
const user = await db.query.users.findFirst({ where: eq(users.auth0Id, ctx.session.user.sub), }); +if (!user) { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: "User not found in database.", + }); +}
🧹 Nitpick comments (8)
apps/api/src/env.ts (1)
8-9: Consider adding runtime validation for Auth0 environment variables.While the
@auth0/nextjs-auth0SDK reads these variables directly, unvalidated env vars mean misconfigurations won't be caught at startup. The SDK will fail at runtime when authentication is first attempted.The current approach is acceptable since Auth0 provides its own error messaging, but for consistency with other validated variables (like
DATABASE_URL), you could optionally add these as validated server keys with a comment noting they're also read by the SDK.apps/web/src/app/(auth)/sign-up/[[...sign-up]]/page.tsx (1)
21-32: Consider using Next.jsLinkfor internal navigation.The
/api/auth/loginroute is an internal API route. While the<a>tag works, using Next.jsLinkwould be more idiomatic and provide prefetching benefits where applicable.Additionally, nesting a
<Button>inside an<a>can cause accessibility concerns with nested interactive elements. Consider usingasChildpattern if the Button component supports it, or apply button styling directly to the Link.- <a href="/api/auth/login?connection=google-oauth2&screen_hint=signup"> - <Button variant="outline" className="w-full"> + <Link href="/api/auth/login?connection=google-oauth2&screen_hint=signup"> + <Button variant="outline" className="w-full" asChild> <Image src="/assets/social/google.svg" alt="Google" width={16} height={16} className="mr-2" /> Sign up with Google </Button> - </a> + </Link>Note: If the Button doesn't support
asChild, verify the Link behavior is correct for this Auth0 route, as API routes may require a full page navigation rather than client-side routing.apps/web/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx (1)
19-30: Consider usingasChildprop for cleaner markup.The Button component likely supports the
asChildprop (used elsewhere in this codebase). This would produce cleaner HTML without nested interactive elements.- <a href="/api/auth/login?connection=google-oauth2"> - <Button variant="outline" className="w-full"> - <Image - src="/assets/social/google.svg" - alt="Google" - width={16} - height={16} - className="mr-2" - /> - Sign in with Google - </Button> - </a> + <Button variant="outline" className="w-full" asChild> + <a href="/api/auth/login?connection=google-oauth2"> + <Image + src="/assets/social/google.svg" + alt="Google" + width={16} + height={16} + className="mr-2" + /> + Sign in with Google + </a> + </Button>apps/web/src/app/page.tsx (1)
67-72: Consider usingasChildfor the logout link.Similar to the sign-in page, wrapping
DropdownMenuItemaround an anchor creates nested interactive elements. UsingasChildwould be cleaner.- <a href="/api/auth/logout"> - <DropdownMenuItem className="cursor-pointer"> - <LogOut className="mr-2 size-4" /> - Sign out - </DropdownMenuItem> - </a> + <DropdownMenuItem className="cursor-pointer" asChild> + <a href="/api/auth/logout"> + <LogOut className="mr-2 size-4" /> + Sign out + </a> + </DropdownMenuItem>apps/web/src/env.ts (1)
16-17: Consider validating Auth0 environment variables for consistency.While @auth0/nextjs-auth0 reads these variables directly, other apps in this PR (admin, marketing) explicitly validate Auth0 variables in their env schemas. Skipping validation here means missing/malformed Auth0 vars will only fail at runtime rather than at startup.
For consistency and earlier error detection, consider adding the Auth0 vars to the server schema:
server: { DATABASE_URL: z.string().url(), DATABASE_URL_UNPOOLED: z.string().url(), - // Auth0 env vars are read directly by @auth0/nextjs-auth0: - // AUTH0_SECRET, AUTH0_BASE_URL, AUTH0_ISSUER_BASE_URL, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET + AUTH0_SECRET: z.string().min(1), + AUTH0_BASE_URL: z.string().url(), + AUTH0_ISSUER_BASE_URL: z.string().url(), + AUTH0_CLIENT_ID: z.string().min(1), + AUTH0_CLIENT_SECRET: z.string().min(1), },packages/trpc/src/router/admin.ts (1)
43-52: LGTM!The TODO and error message correctly reflect the Auth0 migration. The
NOT_IMPLEMENTEDplaceholder is appropriate for now—full implementation will require integrating with the Auth0 Management API to delete users from Auth0's identity store.Would you like me to help draft the Auth0 user deletion implementation using the Management API, or open an issue to track this work?
apps/admin/src/env.ts (1)
16-19: Auth0 environment configuration looks correct.The required Auth0 environment variables are properly defined. Consider adding a minimum length constraint for
AUTH0_SECRET(Auth0 recommends at least 32 characters for session encryption security):- AUTH0_SECRET: z.string(), + AUTH0_SECRET: z.string().min(32),apps/admin/src/proxy.ts (1)
33-47: Verify redirect responses preserve Auth0 cookies.The authorization logic is correct. However, when redirecting unauthenticated/unauthorized users, any cookies set by
auth0.middleware()(e.g., session refresh) may be lost. Consider preserving cookies fromauthResponse:if (!session?.user) { - return NextResponse.redirect(new URL(env.NEXT_PUBLIC_WEB_URL)); + const redirect = NextResponse.redirect(new URL(env.NEXT_PUBLIC_WEB_URL)); + // Preserve any cookies set by Auth0 middleware + authResponse.cookies.getAll().forEach((cookie) => { + redirect.cookies.set(cookie.name, cookie.value); + }); + return redirect; }The same pattern would apply to the domain check redirect on line 46.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (42)
.env.example(1 hunks).github/workflows/deploy-preview.yml(4 hunks).github/workflows/deploy-production.yml(4 hunks)apps/admin/package.json(1 hunks)apps/admin/src/app/(dashboard)/components/AppSidebar/components/NavUser/NavUser.tsx(1 hunks)apps/admin/src/app/(dashboard)/users/deleted/components/DeletedUsersTable/DeletedUsersTable.tsx(1 hunks)apps/admin/src/app/layout.tsx(3 hunks)apps/admin/src/env.ts(1 hunks)apps/admin/src/proxy.ts(1 hunks)apps/api/package.json(1 hunks)apps/api/src/app/api/webhooks/clerk/route.ts(0 hunks)apps/api/src/env.ts(1 hunks)apps/api/src/proxy.ts(3 hunks)apps/api/src/trpc/context.ts(1 hunks)apps/marketing/package.json(1 hunks)apps/marketing/src/app/components/CTAButtons/CTAButtons.tsx(1 hunks)apps/marketing/src/app/layout.tsx(3 hunks)apps/marketing/src/env.ts(1 hunks)apps/marketing/src/proxy.ts(1 hunks)apps/web/package.json(1 hunks)apps/web/src/app/(auth)/sign-in/[[...sign-in]]/page.tsx(1 hunks)apps/web/src/app/(auth)/sign-up/[[...sign-up]]/page.tsx(1 hunks)apps/web/src/app/(auth)/sso-callback/layout.tsx(0 hunks)apps/web/src/app/(auth)/sso-callback/page.tsx(0 hunks)apps/web/src/app/download/page.tsx(1 hunks)apps/web/src/app/layout.tsx(2 hunks)apps/web/src/app/page.tsx(3 hunks)apps/web/src/env.ts(1 hunks)apps/web/src/proxy.ts(1 hunks)packages/auth0/package.json(1 hunks)packages/auth0/src/client.ts(1 hunks)packages/auth0/src/server.ts(1 hunks)packages/auth0/src/types.ts(1 hunks)packages/auth0/tsconfig.json(1 hunks)packages/db/src/schema/schema.ts(2 hunks)packages/trpc/package.json(1 hunks)packages/trpc/src/router/admin.ts(1 hunks)packages/trpc/src/router/organization.ts(1 hunks)packages/trpc/src/router/task.ts(1 hunks)packages/trpc/src/router/user.ts(1 hunks)packages/trpc/src/trpc.ts(4 hunks)turbo.jsonc(1 hunks)
💤 Files with no reviewable changes (3)
- apps/web/src/app/(auth)/sso-callback/layout.tsx
- apps/api/src/app/api/webhooks/clerk/route.ts
- apps/web/src/app/(auth)/sso-callback/page.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx,js,jsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Use Biome for code formatting and linting, running at root level for speed
Files:
apps/admin/src/app/layout.tsxpackages/trpc/package.jsonapps/api/src/trpc/context.tspackages/trpc/src/router/organization.tspackages/auth0/src/client.tsapps/marketing/package.jsonapps/admin/src/app/(dashboard)/users/deleted/components/DeletedUsersTable/DeletedUsersTable.tsxapps/marketing/src/app/components/CTAButtons/CTAButtons.tsxapps/api/src/env.tsapps/api/package.jsonpackages/trpc/src/router/admin.tsapps/marketing/src/env.tsapps/web/src/app/(auth)/sign-up/[[...sign-up]]/page.tsxpackages/auth0/src/server.tsapps/admin/package.jsonpackages/trpc/src/router/user.tsapps/web/package.jsonpackages/db/src/schema/schema.tsapps/marketing/src/proxy.tspackages/trpc/src/router/task.tspackages/auth0/tsconfig.jsonapps/admin/src/proxy.tsapps/web/src/app/download/page.tsxapps/web/src/env.tspackages/trpc/src/trpc.tsapps/web/src/app/page.tsxapps/api/src/proxy.tsapps/admin/src/app/(dashboard)/components/AppSidebar/components/NavUser/NavUser.tsxapps/web/src/app/layout.tsxapps/web/src/app/(auth)/sign-in/[[...sign-in]]/page.tsxapps/marketing/src/app/layout.tsxpackages/auth0/src/types.tsapps/web/src/proxy.tspackages/auth0/package.jsonapps/admin/src/env.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Avoid
anytype and prioritize type safety in TypeScript code
Files:
apps/admin/src/app/layout.tsxapps/api/src/trpc/context.tspackages/trpc/src/router/organization.tspackages/auth0/src/client.tsapps/admin/src/app/(dashboard)/users/deleted/components/DeletedUsersTable/DeletedUsersTable.tsxapps/marketing/src/app/components/CTAButtons/CTAButtons.tsxapps/api/src/env.tspackages/trpc/src/router/admin.tsapps/marketing/src/env.tsapps/web/src/app/(auth)/sign-up/[[...sign-up]]/page.tsxpackages/auth0/src/server.tspackages/trpc/src/router/user.tspackages/db/src/schema/schema.tsapps/marketing/src/proxy.tspackages/trpc/src/router/task.tsapps/admin/src/proxy.tsapps/web/src/app/download/page.tsxapps/web/src/env.tspackages/trpc/src/trpc.tsapps/web/src/app/page.tsxapps/api/src/proxy.tsapps/admin/src/app/(dashboard)/components/AppSidebar/components/NavUser/NavUser.tsxapps/web/src/app/layout.tsxapps/web/src/app/(auth)/sign-in/[[...sign-in]]/page.tsxapps/marketing/src/app/layout.tsxpackages/auth0/src/types.tsapps/web/src/proxy.tsapps/admin/src/env.ts
**/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/components/**/*.{ts,tsx}: Structure project folders as one folder per component with PascalCase naming (ComponentName/ComponentName.tsx + index.ts barrel export)
Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them
Use one component per file (no multi-component files)
Files:
apps/admin/src/app/(dashboard)/users/deleted/components/DeletedUsersTable/DeletedUsersTable.tsxapps/marketing/src/app/components/CTAButtons/CTAButtons.tsxapps/admin/src/app/(dashboard)/components/AppSidebar/components/NavUser/NavUser.tsx
packages/db/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use Drizzle ORM for all database operations in the
packages/dbpackage
Files:
packages/db/src/schema/schema.ts
**/tsconfig.json
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript config from packages/typescript-config for all workspaces
Files:
packages/auth0/tsconfig.json
🧠 Learnings (6)
📚 Learning: 2025-12-12T05:45:09.672Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T05:45:09.672Z
Learning: Applies to packages/ui/**/*.{ts,tsx} : Use React + TailwindCSS v4 + shadcn/ui for UI components in `packages/ui`
Applied to files:
apps/admin/src/app/layout.tsxapps/marketing/src/app/layout.tsx
📚 Learning: 2025-12-12T05:45:09.672Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T05:45:09.672Z
Learning: Applies to **/components/**/*.{ts,tsx} : Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them
Applied to files:
apps/marketing/package.json
📚 Learning: 2025-12-12T05:45:09.673Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T05:45:09.673Z
Learning: Applies to **/tsconfig.json : Use TypeScript config from packages/typescript-config for all workspaces
Applied to files:
packages/auth0/tsconfig.json
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : Please use alias as defined in `tsconfig.json` when possible
Applied to files:
packages/auth0/tsconfig.json
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.{ts,tsx,js,jsx} : For Electron interprocess communication, ALWAYS use tRPC as defined in `src/lib/trpc`
Applied to files:
packages/trpc/src/trpc.ts
📚 Learning: 2025-12-12T05:45:09.673Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T05:45:09.673Z
Learning: Applies to apps/desktop/src/main/index.ts : Load environment variables in apps/desktop/src/main/index.ts with override: true before any imports
Applied to files:
apps/admin/src/env.ts
🧬 Code graph analysis (18)
apps/admin/src/app/layout.tsx (1)
packages/auth0/src/client.ts (1)
Auth0Provider(3-3)
apps/api/src/trpc/context.ts (1)
packages/auth0/src/server.ts (1)
getSession(21-27)
packages/trpc/src/router/organization.ts (1)
packages/db/src/schema/schema.ts (1)
users(15-35)
apps/marketing/src/app/components/CTAButtons/CTAButtons.tsx (1)
packages/auth0/src/server.ts (1)
auth0(15-15)
apps/web/src/app/(auth)/sign-up/[[...sign-up]]/page.tsx (2)
packages/ui/src/components/ui/button.tsx (1)
Button(60-60)packages/ui/src/components/ai-elements/image.tsx (1)
Image(9-24)
packages/auth0/src/server.ts (1)
packages/auth0/src/types.ts (1)
AppSession(11-11)
packages/trpc/src/router/user.ts (2)
packages/db/src/index.ts (1)
eq(1-1)packages/db/src/schema/schema.ts (1)
users(15-35)
packages/trpc/src/router/task.ts (1)
packages/db/src/schema/schema.ts (1)
users(15-35)
apps/admin/src/proxy.ts (4)
packages/auth0/src/server.ts (1)
auth0(15-15)packages/db/src/index.ts (2)
db(2-2)eq(1-1)packages/db/src/schema/schema.ts (1)
users(15-35)packages/shared/src/constants.ts (1)
COMPANY(2-7)
apps/web/src/app/download/page.tsx (1)
packages/ui/src/components/ui/button.tsx (1)
Button(60-60)
packages/trpc/src/trpc.ts (2)
packages/auth0/src/types.ts (3)
AppSession(11-11)isSignedIn(21-23)SignedInSession(16-16)packages/db/src/schema/schema.ts (1)
users(15-35)
apps/web/src/app/page.tsx (3)
packages/shared/src/names/names.ts (1)
getInitials(14-28)packages/ui/src/components/ui/avatar.tsx (3)
Avatar(53-53)AvatarImage(53-53)AvatarFallback(53-53)packages/ui/src/components/ui/dropdown-menu.tsx (5)
DropdownMenuTrigger(251-251)DropdownMenuContent(252-252)DropdownMenuLabel(254-254)DropdownMenuSeparator(259-259)DropdownMenuItem(255-255)
apps/api/src/proxy.ts (3)
apps/admin/src/proxy.ts (1)
middleware(18-50)apps/marketing/src/proxy.ts (1)
middleware(5-18)apps/web/src/proxy.ts (1)
middleware(13-42)
apps/admin/src/app/(dashboard)/components/AppSidebar/components/NavUser/NavUser.tsx (1)
packages/ui/src/components/ui/dropdown-menu.tsx (1)
DropdownMenuItem(255-255)
apps/web/src/app/layout.tsx (3)
packages/auth0/src/client.ts (1)
Auth0Provider(3-3)apps/admin/src/app/providers.tsx (1)
Providers(9-24)apps/web/src/app/providers.tsx (1)
Providers(9-24)
apps/marketing/src/app/layout.tsx (1)
packages/auth0/src/client.ts (1)
Auth0Provider(3-3)
packages/auth0/src/types.ts (1)
packages/auth0/src/server.ts (1)
auth0(15-15)
apps/web/src/proxy.ts (4)
apps/admin/src/proxy.ts (1)
middleware(18-50)apps/api/src/proxy.ts (1)
middleware(20-54)apps/marketing/src/proxy.ts (1)
middleware(5-18)packages/auth0/src/server.ts (1)
auth0(15-15)
🪛 dotenv-linter (4.0.0)
.env.example
[warning] 14-14: [UnorderedKey] The AUTH0_BASE_URL key should go before the AUTH0_SECRET key
(UnorderedKey)
[warning] 15-15: [UnorderedKey] The AUTH0_ISSUER_BASE_URL key should go before the AUTH0_SECRET key
(UnorderedKey)
[warning] 16-16: [UnorderedKey] The AUTH0_CLIENT_ID key should go before the AUTH0_ISSUER_BASE_URL key
(UnorderedKey)
[warning] 17-17: [UnorderedKey] The AUTH0_CLIENT_SECRET key should go before the AUTH0_ISSUER_BASE_URL key
(UnorderedKey)
🔇 Additional comments (33)
apps/admin/src/app/(dashboard)/components/AppSidebar/components/NavUser/NavUser.tsx (1)
104-109: Verify Auth0 logout endpoint configuration.The logout implementation uses a direct anchor link to
/api/auth/logout, which will trigger a full page navigation. Ensure the Auth0 logout endpoint is properly configured to clear session cookies and redirect appropriately after logout.apps/admin/src/app/(dashboard)/users/deleted/components/DeletedUsersTable/DeletedUsersTable.tsx (1)
271-271: LGTM!The text update from "Clerk" to "Auth0" is consistent with the authentication migration and accurately reflects the new provider.
packages/auth0/tsconfig.json (1)
1-5: LGTM!The TypeScript configuration correctly extends the shared workspace config from
@superset/typescript/internal-package.json, following the project's coding guidelines. Based on learnings, this aligns with the convention to use TypeScript config frompackages/typescript-configfor all workspaces.packages/auth0/src/client.ts (1)
1-3: LGTM!The client module correctly uses the
"use client"directive and exports exactly what is needed. BothAuth0ProvideranduseUserare actively used across the codebase (apps/web, apps/marketing, and apps/admin), and no other client-side utilities from@auth0/nextjs-auth0are required.apps/web/src/app/layout.tsx (1)
1-1: LGTM! Auth0Provider correctly integrated.The Auth0Provider properly wraps the application content, maintaining the correct provider hierarchy. This aligns with the pattern used across other apps in this migration.
Also applies to: 49-54
.env.example (1)
11-17: Auth0 environment variables correctly configured.All required Auth0 variables are present with helpful generation instructions for the secret. The current ordering (secret → URLs → client credentials) is logical and preferable to strict alphabetical ordering.
.github/workflows/deploy-preview.yml (1)
124-127: Ensure Auth0 tenant allows preview deployment callback URLs.Preview deployments use dynamic URLs (e.g.,
web-pr-{number}-superset.vercel.app). The Auth0 tenant needs to have these callback URLs allowed. Consider either:
- Adding a wildcard callback URL pattern in Auth0 (e.g.,
https://*.vercel.app/api/auth/callback)- Or documenting that preview auth testing requires manual Auth0 configuration
Also applies to: 198-201
apps/web/src/app/page.tsx (1)
3-3: LGTM! Auth0 user data correctly integrated.The migration properly maps Auth0 user claims (
name,picture) to the UI. ThefirstNameextraction andgetInitialsusage handle nullable values safely.Also applies to: 23-28
apps/api/src/proxy.ts (2)
1-2: LGTM! Auth0 import and typing.The import from
@superset/auth0/serverand explicitNextRequesttyping are correct.
29-46: Verify theauthResponse.status !== 200condition logic.This proxy checks both
authResponse.status !== 200andpathname.startsWith("/api/auth"), while other proxies in this PR (marketing, admin, web) only check the pathname.The status check could cause unintended behavior if Auth0 middleware returns a non-200 status for reasons other than handling auth routes (e.g., internal errors). Consider aligning with the pattern used in other proxies for consistency.
.github/workflows/deploy-production.yml (1)
75-78: Verify ifAUTH0_BASE_URLis needed in production deployments.The
.env.exampledefinesAUTH0_BASE_URLbut it's not passed to the deployment jobs. The Auth0 SDK typically requires this for callback URL construction. If Vercel automatically sets this viaVERCEL_URLor similar, this may be fine. Otherwise, each app may needAUTH0_BASE_URLset to its production URL.Does @auth0/nextjs-auth0 require AUTH0_BASE_URL environment variable?apps/web/src/proxy.ts (1)
1-42: LGTM!The Auth0 middleware implementation follows the same pattern as the admin and marketing apps. The
isPublicPathhelper correctly handles both exact path matches and prefix matches, and the authentication flow properly:
- Runs Auth0 middleware for all requests
- Returns Auth0 response for
/api/auth/*routes- Redirects authenticated users away from sign-in/sign-up pages
- Protects non-public routes by redirecting unauthenticated users
apps/admin/src/app/layout.tsx (1)
1-1: LGTM!The Auth0Provider is correctly imported from the shared
@superset/auth0/clientpackage and wraps the entire application at the root level. The removal of the env import is appropriate since Auth0Provider doesn't require the cookie domain configuration that ClerkProvider needed.Also applies to: 41-41, 56-56
apps/marketing/package.json (1)
16-16: LGTM!Clean dependency swap from
@clerk/nextjsto the internal@superset/auth0workspace package. This aligns with the other apps in the monorepo making the same migration.apps/api/src/trpc/context.ts (1)
1-7: LGTM! Clean migration to Auth0 session handling.The replacement of Clerk's
auth()with Auth0'sgetSession()is correctly implemented. The session retrieval properly handles errors (returningnullon failure as shown in packages/auth0/src/server.ts), and the context creation remains compatible with the updated session type.apps/admin/package.json (1)
14-14: LGTM! Dependency correctly migrated to Auth0.The replacement of
@clerk/nextjswith the workspace-local@superset/auth0package aligns with the authentication migration across the monorepo.packages/trpc/package.json (1)
17-17: LGTM! TRPC package dependency correctly updated.The swap from
@clerk/backendto the workspace-local@superset/auth0package is consistent with the authentication migration.packages/trpc/src/router/task.ts (1)
75-78: LGTM! Proper error handling for missing user.The migration from
clerkIdtoauth0Idis correctly implemented, and the explicit error throw when the user is not found (line 78) is good practice. This ensures data integrity by preventing task creation with an invalid creator reference.turbo.jsonc (1)
7-11: Auth0 environment variables are correctly configured.The Auth0 environment variables are properly set up. Both
AUTH0_BASE_URL(your application's base URL, e.g.,http://localhost:3000) andAUTH0_ISSUER_BASE_URL(your Auth0 tenant URL, e.g.,https://your-tenant.auth0.com) are required and serve distinct purposes—they are not interchangeable.The variables
AUTH0_AUDIENCEandAUTH0_SCOPEare optional and only needed if your application requires API authorization; they are not required for basic authentication.apps/web/package.json (1)
14-14: LGTM! Clean dependency migration.The replacement of Clerk with the workspace-based Auth0 package is correctly implemented.
apps/api/package.json (1)
14-14: LGTM! Consistent with migration pattern.The Auth0 workspace dependency addition aligns with the broader authentication migration.
apps/marketing/src/app/components/CTAButtons/CTAButtons.tsx (2)
1-1: LGTM! Correct import for Auth0 migration.The import correctly uses the new Auth0 server integration.
8-10: Correction: ImportisSignedInfrom types.Since
isSignedInis exported frompackages/auth0/src/types.tsrather thanserver.ts, the import should be:import { auth0 } from "@superset/auth0/server"; +import { isSignedIn } from "@superset/auth0/types"; import { DOWNLOAD_URL_MAC_ARM64 } from "@superset/shared/constants";apps/marketing/src/proxy.ts (1)
1-18: LGTM! Middleware correctly implements Auth0 integration.The async middleware properly:
- Runs Auth0 middleware for all requests
- Returns Auth0's response for
/api/auth/*routes- Allows public access to marketing routes
The explicit typing with
NextRequestand the logical flow are correct.packages/auth0/src/server.ts (1)
1-29: LGTM! Server integration is well-structured.The Auth0 client singleton and
getSession()helper are correctly implemented. The function properly handles errors by returningnullfor unauthenticated states, which aligns with theAppSessiontype definition that allowsnull.The JSDoc correctly documents the required environment variables.
packages/auth0/src/types.ts (1)
1-30: LGTM! Excellent type safety implementation.The type definitions demonstrate strong TypeScript practices:
- Proper inference from the Auth0 SDK
- Clear distinction between nullable (
AppSession) and non-null (SignedInSession) states- Type guard
isSignedIncorrectly checkssession?.user?.sub != nullfor robust authentication validationgetUserIdsafely accessesuser.subonly when guaranteed non-nullThis provides a solid foundation for type-safe Auth0 integration across the codebase.
apps/marketing/src/env.ts (1)
22-26: LGTM! Runtime environment correctly configured.The
experimental__runtimeEnvappropriately exposes only public client-side variables and excludes server-only Auth0 secrets.packages/auth0/package.json (1)
6-19: LGTM! Export configuration correct for TypeScript workspace package.The exports correctly map server, client, and types modules to their TypeScript source files. This pattern is appropriate for a monorepo where consuming packages handle TypeScript compilation.
apps/admin/src/proxy.ts (1)
21-27: Auth0 middleware response handling looks correct.The pattern of running
auth0.middleware(req)first and returning its response for/api/authroutes is the correct approach for Auth0 Next.js SDK v2.packages/trpc/src/trpc.ts (4)
1-2: LGTM!Imports are correctly updated to use Auth0 types from the new shared package.
20-28: Context type definitions are well-structured.The
AppSessiontype correctly models the nullable session state for unauthenticated users, and the documentation comments clearly explain the session types.
50-64: Protected procedure pattern is correct.The
isSignedIntype guard properly validates the session, and the cast toSignedInSessionis safe after the guard check. The narrowed context ensures downstream procedures have access to authenticated session data.
66-93: Admin procedure correctly implements defense-in-depth.The domain check in
adminProcedureprovides an additional authorization layer beyond the middleware, which is appropriate since tRPC routers could be shared across apps. Theauth0Idextraction fromsession.user.subaligns with Auth0's JWT structure, and the database query uses the correctly indexedauth0Idcolumn.
| const session = await auth0.getSession(); | ||
|
|
||
| if (userId) { | ||
| if (session?.user) { |
There was a problem hiding this comment.
Use the isSignedIn type guard for stricter authentication.
The condition session?.user is weaker than the previous userId check. According to packages/auth0/src/types.ts, the actual user identifier is user.sub, and a dedicated isSignedIn() type guard exists that checks session?.user?.sub != null.
This matters because session?.user could theoretically be an object without a valid sub, potentially allowing access without a proper user ID.
Apply this diff to use the stricter type guard:
-import { auth0 } from "@superset/auth0/server";
+import { auth0, isSignedIn } from "@superset/auth0/server";
import { DOWNLOAD_URL_MAC_ARM64 } from "@superset/shared/constants"; export async function CTAButtons() {
const session = await auth0.getSession();
- if (session?.user) {
+ if (isSignedIn(session)) {
return (🤖 Prompt for AI Agents
In apps/marketing/src/app/components/CTAButtons/CTAButtons.tsx around lines 8 to
10, replace the weak check `if (session?.user)` with the stricter type guard `if
(isSignedIn(session))`; import the `isSignedIn` helper from packages/auth0 (or
its exported path) if not already imported, and update the condition to call
`isSignedIn(session)` so the code verifies `session?.user?.sub != null` before
treating the user as signed in.
| @@ -1,12 +1,10 @@ | |||
| import { ClerkProvider } from "@clerk/nextjs"; | |||
| import { Auth0Provider } from "@superset/auth0/client"; | |||
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n apps/marketing/src/app/layout.tsx | head -70Repository: superset-sh/superset
Length of output: 2277
🏁 Script executed:
cat apps/marketing/src/env.tsRepository: superset-sh/superset
Length of output: 836
🏁 Script executed:
rg "NEXT_PUBLIC_COOKIE_DOMAIN" apps/marketingRepository: superset-sh/superset
Length of output: 46
🏁 Script executed:
rg "Auth0Provider" apps/marketing --type tsxRepository: superset-sh/superset
Length of output: 91
🏁 Script executed:
rg "export.*Auth0Provider" --type ts --type tsx -A 10Repository: superset-sh/superset
Length of output: 91
🌐 Web query:
Auth0 React SDK Auth0Provider configuration requirements and props
💡 Result:
Summary — Auth0Provider (auth0-react)
Required / must-provide
- domain — your Auth0 tenant domain (or custom domain). [1]
- clientId — the Auth0 Application Client ID. [1]
- authorizationParams.redirect_uri — the post-login redirect URI (commonly window.location.origin). The quickstart warns this must be provided or login will fail. [2]
Common/important optional props
- authorizationParams — object for authorization parameters (audience, scope, redirect_uri, prompt, etc.). [1][2]
- audience — (can be passed inside authorizationParams) the API identifier when requesting access tokens. [1]
- onRedirectCallback — callback to run after redirect (useful with custom routers). [1]
- cacheLocation — "memory" (default) or "localstorage" for token caching. [1]
- useRefreshTokens — boolean to enable refresh token rotation (requires cacheLocation/local storage and tenant settings). [1]
- children — your app (Auth0Provider must wrap the root App). [2]
- onBeforeAuthorize / advanced options — see SDK docs for other props and lifecycle flags. [1]
Behavior / integration notes
- Auth0Provider wraps the app and exposes useAuth0() hook and context (isLoading, error, login/logout, getAccessTokenSilently, etc.). [1]
- Always wrap the root App (not a single component). [2]
- If calling APIs, set audience and scope when requesting tokens (either in Auth0Provider authorizationParams or per call). [1][3]
References
[1] Auth0 React SDK docs (Auth0Provider usage and props).
[2] Auth0 React Quickstart — React SPA (importance of authorizationParams.redirect_uri and wrapping root App).
[3] Auth0 React GitHub / SDK site (examples and additional config notes).
🏁 Script executed:
find . -type f -name "*.ts" -o -name "*.tsx" -o -name "*.json" | xargs grep -l "@superset/auth0/client" | head -20Repository: superset-sh/superset
Length of output: 189
🏁 Script executed:
fd "auth0" --type d | head -20Repository: superset-sh/superset
Length of output: 79
🏁 Script executed:
fd "client" packages -type f | grep -i auth0Repository: superset-sh/superset
Length of output: 234
🏁 Script executed:
ls -la packages/auth0/Repository: superset-sh/superset
Length of output: 347
🏁 Script executed:
find packages/auth0 -type f -name "*.ts" -o -name "*.tsx" | head -20Repository: superset-sh/superset
Length of output: 149
🏁 Script executed:
cat packages/auth0/package.jsonRepository: superset-sh/superset
Length of output: 705
🏁 Script executed:
cat packages/auth0/src/client.tsRepository: superset-sh/superset
Length of output: 140
🏁 Script executed:
cat packages/auth0/src/types.tsRepository: superset-sh/superset
Length of output: 764
🌐 Web query:
@auth0/nextjs-auth0 Auth0Provider configuration props environment variables
💡 Result:
Summary — key configuration props and environment variables for @auth0/nextjs-auth0
Required environment variables (common names used by the SDK)
- AUTH0_DOMAIN (or AUTH0_ISSUER_BASE_URL) — your tenant or custom domain. [1][2]
- AUTH0_CLIENT_ID — Auth0 application client ID. [1][2]
- AUTH0_CLIENT_SECRET — Auth0 application client secret (or use client assertion key). [1][2]
- AUTH0_SECRET (aka secret) — 32-byte hex secret used to encrypt session cookies. Generate with openssl rand -hex 32. [1][2]
- APP_BASE_URL (aka appBaseUrl / AUTH0_BASE_URL in some docs) — your app base URL (e.g. http://localhost:3000). Register callback/logout URLs in Auth0 accordingly. [1][2][3]
Optional / session / advanced environment variables
- AUTH0_COOKIE_DOMAIN, AUTH0_COOKIE_PATH, AUTH0_COOKIE_TRANSIENT, AUTH0_COOKIE_SECURE, AUTH0_COOKIE_SAME_SITE — cookie settings. [1][2]
- AUTH0_AUDIENCE, AUTH0_SCOPE — for requesting API access / access tokens. [3]
- AUTH0_CLIENT_ASSERTION_SIGNING_KEY / AUTH0_CLIENT_ASSERTION_SIGNING_ALG — for private_key_jwt clients (alternative to client secret). [2]
- AUTH0_DPOP_PUBLIC_KEY, AUTH0_DPOP_PRIVATE_KEY, AUTH0_DPOP_CLOCK_SKEW, AUTH0_DPOP_CLOCK_TOLERANCE — DPoP support keys/options. [1][2]
Main programmatic configuration options (Auth0Client / SDK init)
- domain (string) — falls back to AUTH0_DOMAIN / AUTH0_ISSUER_BASE_URL. [2]
- clientId (string) — falls back to AUTH0_CLIENT_ID. [2]
- clientSecret (string) — falls back to AUTH0_CLIENT_SECRET (or use clientAssertionSigningKey). [2]
- appBaseUrl / appBaseUrl (string) — falls back to APP_BASE_URL / AUTH0_BASE_URL. [2]
- secret (string) — falls back to AUTH0_SECRET. [2]
- authorizationParameters / authorizationParams — object passed to /authorize (scope, audience, redirect_uri, prompt, etc.). [2]
- useDPoP / dpopKeyPair / dpopOptions — enable DPoP and pass keys/options. [1]
Client-side provider (UserProvider / Auth0Provider) notes
- The Next.js SDK exposes UserProvider (or Auth0Provider in other Auth0 libs) to wrap your app and provide useUser()/useAuth hooks. For SPA-style SDKs (auth0-react) Auth0Provider takes domain, clientId and authorizationParams (redirect_uri, scope). For nextjs-auth0 you typically configure server-side via env vars and wrap with UserProvider on the client. [1][3]
Where to configure
- Put env vars in .env.local (or your hosting platform’s environment settings). The SDK will read env vars on server-side init; you can also pass the same options programmatically to Auth0Client/initAuth0. [1][2][3]
Quick links (official docs)
- SDK docs / API reference (auth0.github.io/nextjs-auth0). [1]
- GitHub README (required env vars and options). [2]
- Auth0 Next.js quickstart (setup examples and .env.local). [3]
If you want, I can show a minimal .env.local and an example auth0 client/init file for Next.js.
Sources: [1] SDK docs site, [2] GitHub README, [3] Auth0 Next.js quickstart.
🏁 Script executed:
rg "APP_BASE_URL|AUTH0_BASE_URL" packages appsRepository: superset-sh/superset
Length of output: 342
🏁 Script executed:
rg "NEXT_PUBLIC_COOKIE_DOMAIN" --type ts --type jsonRepository: superset-sh/superset
Length of output: 46
🏁 Script executed:
find . -name ".env*" -type f | head -10Repository: superset-sh/superset
Length of output: 78
🏁 Script executed:
cat .env.exampleRepository: superset-sh/superset
Length of output: 1034
🏁 Script executed:
cat packages/auth0/src/server.tsRepository: superset-sh/superset
Length of output: 686
🏁 Script executed:
cat apps/web/src/env.tsRepository: superset-sh/superset
Length of output: 1086
🏁 Script executed:
cat apps/admin/src/env.tsRepository: superset-sh/superset
Length of output: 948
Auth0Provider is correctly configured for Next.js environment-based setup.
The Auth0Provider from @auth0/nextjs-auth0 requires no configuration props (correct implementation). All required environment variables are properly defined in env.ts: AUTH0_SECRET, AUTH0_ISSUER_BASE_URL, AUTH0_CLIENT_ID, and AUTH0_CLIENT_SECRET.
However, note that AUTH0_BASE_URL is required by the @auth0/nextjs-auth0 SDK per the official documentation and is shown in .env.example, but it's missing from the env.ts validation schema for this app. This validation gap should be added for consistency (matching apps/admin).
The removal of NEXT_PUBLIC_COOKIE_DOMAIN is appropriate—@auth0/nextjs-auth0 handles cookie configuration via AUTH0_COOKIE_DOMAIN and related environment variables if needed, rather than requiring client-side constants.
🤖 Prompt for AI Agents
In apps/marketing/src/app/layout.tsx around lines 1 to 1, the review notes that
the AUTH0_BASE_URL env var (required by @auth0/nextjs-auth0) is missing from
this app's env.ts validation schema; update apps/marketing/src/env.ts to add
AUTH0_BASE_URL as a required string (mirror the validation used in apps/admin),
ensure it's reflected in the app's .env.example if present, and run
type/validation checks to confirm the schema change is accepted.
| AUTH0_SECRET: z.string(), | ||
| AUTH0_ISSUER_BASE_URL: z.string().url(), | ||
| AUTH0_CLIENT_ID: z.string(), | ||
| AUTH0_CLIENT_SECRET: z.string(), |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's check the content of the server.ts file mentioned in the comment
find . -path "*/packages/auth0/src/server.ts" -type fRepository: superset-sh/superset
Length of output: 94
🏁 Script executed:
# Also check the env.ts file in marketing app
find . -path "*/apps/marketing/src/env.ts" -type fRepository: superset-sh/superset
Length of output: 91
🌐 Web query:
@auth0/nextjs-auth0 version 4.13.1 required environment variables configuration
💡 Result:
Required environment variables for @auth0/nextjs-auth0 v4.13.1 (minimum):
- AUTH0_DOMAIN (or ISSUER URL) — your Auth0 tenant domain/issuer. [1][2]
- AUTH0_CLIENT_ID — your Auth0 application client ID. [1][2]
- AUTH0_CLIENT_SECRET — your Auth0 application client secret (or use AUTH0_CLIENT_ASSERTION_SIGNING_KEY instead). [1]
- AUTH0_SECRET — 32-byte hex secret used to encrypt session cookies. [1][2]
- APP_BASE_URL (or AUTH0_BASE_URL / AUTH0_APP_BASE_URL variants shown in docs) — your app’s root URL (e.g. http://localhost:3000). [1][2]
Common/optional environment variables (used for cookies, DPoP, routes, etc.):
- AUTH0_COOKIE_DOMAIN, AUTH0_COOKIE_PATH, AUTH0_COOKIE_TRANSIENT, AUTH0_COOKIE_SECURE, AUTH0_COOKIE_SAME_SITE. [1]
- AUTH0_CLIENT_ASSERTION_SIGNING_KEY (private key alternative to client secret). [1]
- AUTH0_DPOP_PUBLIC_KEY, AUTH0_DPOP_PRIVATE_KEY, AUTH0_DPOP_CLOCK_SKEW, AUTH0_DPOP_CLOCK_TOLERANCE (for DPoP). [1]
- NEXT_PUBLIC_BASE_PATH (if using Next.js basePath). [1]
- AUTH0_AUDIENCE, AUTH0_SCOPE (when requesting API access). [2][3]
Notes:
- The SDK requires domain, clientId, appBaseUrl, and secret; and either clientSecret or clientAssertionSigningKey — if missing, initialization will warn. [1]
- Exact variable names shown in docs: see Auth0 Next.js SDK v4.13.1 documentation for full list and examples. [1][2]
Sources: Auth0 Next.js SDK v4.13.1 docs and quickstart. [1] https://auth0.github.io/nextjs-auth0/ (v4.13.1) [2] Auth0 blog/quickstart.
🏁 Script executed:
# Check the JSDoc in packages/auth0/src/server.ts around line 10
head -n 30 ./packages/auth0/src/server.tsRepository: superset-sh/superset
Length of output: 686
🏁 Script executed:
# Check the full env schema in apps/marketing/src/env.ts
cat -n ./apps/marketing/src/env.tsRepository: superset-sh/superset
Length of output: 1032
Add AUTH0_BASE_URL to the server env schema.
The JSDoc in packages/auth0/src/server.ts correctly lists AUTH0_BASE_URL as a required configuration variable. The Auth0 Next.js SDK (v4.13.1) requires this variable to specify the application's base URL for authentication callbacks. It is currently missing from the env schema in apps/marketing/src/env.ts.
server: {
AUTH0_SECRET: z.string(),
+ AUTH0_BASE_URL: z.string().url(),
AUTH0_ISSUER_BASE_URL: z.string().url(),
AUTH0_CLIENT_ID: z.string(),
AUTH0_CLIENT_SECRET: z.string(),
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| AUTH0_SECRET: z.string(), | |
| AUTH0_ISSUER_BASE_URL: z.string().url(), | |
| AUTH0_CLIENT_ID: z.string(), | |
| AUTH0_CLIENT_SECRET: z.string(), | |
| AUTH0_SECRET: z.string(), | |
| AUTH0_BASE_URL: z.string().url(), | |
| AUTH0_ISSUER_BASE_URL: z.string().url(), | |
| AUTH0_CLIENT_ID: z.string(), | |
| AUTH0_CLIENT_SECRET: z.string(), |
🤖 Prompt for AI Agents
In apps/marketing/src/env.ts around lines 13 to 16, the server env schema is
missing AUTH0_BASE_URL required by the Auth0 Next.js SDK; add an AUTH0_BASE_URL
entry to the zod schema (as a required URL string, e.g. AUTH0_BASE_URL:
z.string().url()) alongside the other AUTH0_* entries so the type/schema and
runtime validation include this required configuration variable.
| <a href="/api/auth/logout"> | ||
| <Button variant="outline" size="sm"> | ||
| Sign Out | ||
| </Button> | ||
| </SignOutButton> | ||
| </a> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find the logout API route handler
find apps -name "*logout*" -type f 2>/dev/null | head -20Repository: superset-sh/superset
Length of output: 46
🏁 Script executed:
# Search for auth logout endpoint in route handlers
find apps -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \) | xargs grep -l "auth.*logout" | grep -E "(route|api)" | head -20Repository: superset-sh/superset
Length of output: 46
🏁 Script executed:
# Check the structure of the apps directory
ls -la apps/ 2>/dev/null | head -20Repository: superset-sh/superset
Length of output: 558
🏁 Script executed:
# Look for route files in the apps/web directory
find apps/web -type f -name "route.*" | head -20Repository: superset-sh/superset
Length of output: 46
🏁 Script executed:
# Read the download page file mentioned in the review
cat apps/web/src/app/download/page.tsx 2>/dev/null | head -50Repository: superset-sh/superset
Length of output: 1757
🏁 Script executed:
# Search for authentication-related files
find apps/web -type f -name "*.ts" -o -name "*.tsx" | grep -i auth | head -20Repository: superset-sh/superset
Length of output: 210
🏁 Script executed:
# Look for API route handlers in apps/web
find apps/web -path "*/api/*" -type f | head -20Repository: superset-sh/superset
Length of output: 46
🏁 Script executed:
# Check package.json for dependencies
cat apps/web/package.json 2>/dev/null | grep -A 10 -B 2 "auth\|clerk\|Auth0"Repository: superset-sh/superset
Length of output: 478
🏁 Script executed:
# Find the @superset/auth0 package
find . -path "*packages/*" -name "*auth0*" -type d | head -10Repository: superset-sh/superset
Length of output: 80
🏁 Script executed:
# List packages directory
ls -la packages/ 2>/dev/nullRepository: superset-sh/superset
Length of output: 500
🏁 Script executed:
# Search for logout implementation across the codebase
rg -i "logout" --type ts --type tsx --type js --type jsx -g "!node_modules" | head -40Repository: superset-sh/superset
Length of output: 91
🏁 Script executed:
# Check for API routes in apps/api
find apps/api -type f -name "route.*" 2>/dev/null | head -20Repository: superset-sh/superset
Length of output: 105
🏁 Script executed:
# Explore the auth0 package
find packages/auth0 -type f | head -30Repository: superset-sh/superset
Length of output: 206
🏁 Script executed:
# Check the structure of auth0 package
ls -la packages/auth0/Repository: superset-sh/superset
Length of output: 347
🏁 Script executed:
# Read auth0 package files
cat packages/auth0/src/*.ts 2>/dev/null | head -100Repository: superset-sh/superset
Length of output: 1464
🏁 Script executed:
# Search for logout in the entire codebase with correct rg syntax
rg -i "logout" -t js -t ts | head -50Repository: superset-sh/superset
Length of output: 2724
🏁 Script executed:
# Search for route.ts or route.js files
find apps -name "route.ts" -o -name "route.js" 2>/dev/nullRepository: superset-sh/superset
Length of output: 105
🏁 Script executed:
# Check for middleware handling auth
find apps -name "middleware.*" -type fRepository: superset-sh/superset
Length of output: 46
🏁 Script executed:
# Search for dynamic routes or catch-all routes
rg -t js -t ts "\[.*\]" | grep -i "route\|auth" | head -20Repository: superset-sh/superset
Length of output: 1743
🏁 Script executed:
# Check the main layout or app configuration for Auth0 setup
cat apps/web/src/app/layout.tsx 2>/dev/null | head -80Repository: superset-sh/superset
Length of output: 1361
🏁 Script executed:
# Look for actual @auth0/nextjs-auth0 usage patterns
rg -t js -t ts "@auth0/nextjs-auth0" --no-heading | head -30Repository: superset-sh/superset
Length of output: 405
🌐 Web query:
@auth0/nextjs-auth0 /api/auth/logout GET request CSRF protection
💡 Result:
Short answer: The built-in /api/auth/logout route in @auth0/nextjs-auth0 is a simple GET handler and does not implement an explicit CSRF token check for logout; this has raised community concern and requests for guidance. [1][2]
What to do
- Treat logout as a state-changing action and avoid exposing it as an unauthenticated GET link. Replace link-triggered GETs with a POST (form or fetch) and verify a CSRF token or same-site origin on your server before calling handleLogout. (You can implement a custom logout endpoint that calls handleLogout(req,res,opts) after your CSRF/origin check.) [2][3]
- Ensure cookies set for sessions use SameSite=strict or Lax and Secure/HttpOnly where appropriate to reduce CSRF risk.
- If you must keep the default GET route, avoid prefetching/automatic navigation (Next ) so it cannot be triggered unintentionally. Community posts show this is a practical issue. [1][4]
References
- Auth0 Community thread discussing securing logout / CSRF concerns. [Auth0 Community]. [April 30, 2024].
- auth0/nextjs-auth0 README — lists mounted /auth/logout route (no mention of built-in CSRF protection). (GitHub).
- GitHub issue / examples on customizing logout (showing how to implement your own logout handler using handleLogout).
- Community/Reddit reports about accidental/pre-fetch triggered logout when using GET links.
If you want, I can provide a small example: a custom POST /api/auth/logout that validates a CSRF token (or Origin/Referer) and then calls handleLogout(req,res). Which example would you prefer (fetch + CSRF cookie, double-submit cookie, or Origin/Referer check)?
Secure logout with POST form to prevent CSRF attacks.
Using a plain anchor tag with GET request for logout exposes a security vulnerability:
-
CSRF vulnerability: The
/api/auth/logoutroute in@auth0/nextjs-auth0handles GET requests without explicit CSRF protection. Malicious actors can trigger logout via cross-site requests (e.g.,<img src="/api/auth/logout">), logging out users without their consent. This is a documented community concern with the library. -
Auth0 SDK guidance: The official recommendation is to avoid exposing logout as an unauthenticated GET endpoint. Instead, implement logout as a state-changing action with POST method and validate CSRF tokens or same-site origin.
-
Accidental logout: Using a simple GET link risks unintentional logouts if prefetching is enabled or the link is triggered unexpectedly.
Replace with a POST-based form submission:
<form action="/api/auth/logout" method="POST">
<Button variant="outline" size="sm" type="submit">
Sign Out
</Button>
</form>Or create a custom logout endpoint that validates CSRF before calling the SDK's handleLogout().
🤖 Prompt for AI Agents
In apps/web/src/app/download/page.tsx around lines 17 to 21, the logout is
implemented as a GET anchor which is vulnerable to CSRF and accidental/logout
prefetching; change it to submit a POST to /api/auth/logout by replacing the
anchor with an HTML form whose action is /api/auth/logout and method is POST and
render the Button inside that form with type="submit"; optionally, if you need
extra protection, implement a custom logout endpoint that validates a CSRF token
or origin before calling the Auth0 SDK's handleLogout().
| "typecheck": "tsc --noEmit --emitDeclarationOnly false" | ||
| }, | ||
| "dependencies": { | ||
| "@auth0/nextjs-auth0": "^4.13.1" |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
@auth0/nextjs-auth0 latest version npm
💡 Result:
As of December 13, 2025 the latest published version is 4.13.2. [Install with npm:]
npm install @auth0/nextjs-auth0@4.13.2
Sources: Yarn package listing (shows v4.13.2, Dec 4, 2025). [1] GitHub releases for the project. [2]
[1] https://classic.yarnpkg.com/en/package/%40auth0/nextjs-auth0
[2] https://github.com/auth0/nextjs-auth0/releases
🌐 Web query:
@auth0/nextjs-auth0 4.13.1 security vulnerabilities CVE
💡 Result:
Short answer: No known CVEs affecting @auth0/nextjs-auth0 version 4.13.1. The recent CVEs (e.g., CVE-2025-67716, CVE-2025-67490, CVE-2025-48947) affect earlier ranges and were fixed in 4.13.0 or earlier patch releases — upgrade to >=4.13.0 (4.13.1 is fine). [1][2][3][4]
Sources:
- CVE-2025-67716 (input validation / returnTo) — fixed in 4.13.0. [1]
- CVE-2025-67490 (token cache / improper request caching) — affects 4.11.x/4.12.0, patched in 4.11.2/4.12.1. [2]
- CVE-2025-48947 (CDN caching of __session cookies) — affects <4.6.1, patched in 4.6.1. [3]
- Vulnerability database summaries for @auth0/nextjs-auth0. [4]
References:
[1] GitLab advisory / NVD summaries for CVE-2025-67716 (fix in 4.13.0).
[2] Multiple vulnerability reports for CVE-2025-67490 (patched in 4.11.2 / 4.12.1).
[3] Snyk advisory for CVE-2025-48947 (upgrade to 4.6.1+).
[4] Aggregate vuln listings for @auth0/nextjs-auth0 (vuln timelines and affected versions).
Update @auth0/nextjs-auth0 to the latest stable version 4.13.2.
Version 4.13.1 is secure with no known CVEs, but version 4.13.2 (released Dec 4, 2025) is the current latest stable version and should be used.
🤖 Prompt for AI Agents
In packages/auth0/package.json around line 25, the dependency
"@auth0/nextjs-auth0" is pinned to "^4.13.1"; update it to "^4.13.2" to use the
latest stable release, then run your package manager (npm/yarn/pnpm) to update
node_modules and the lockfile (package-lock.json/yarn.lock/pnpm-lock.yaml), and
run the test suite or a build to verify nothing breaks.
| { | ||
| id: uuid().primaryKey().defaultRandom(), | ||
| clerkId: text("clerk_id").notNull().unique(), | ||
| auth0Id: text("auth0_id").notNull().unique(), |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if migration file exists for the clerk to auth0 rename
fd -t f "rename_clerk_to_auth0" packages/dbRepository: superset-sh/superset
Length of output: 46
🏁 Script executed:
#!/bin/bash
# Read the schema file to verify the field names and indices
head -50 packages/db/src/schema/schema.ts | cat -nRepository: superset-sh/superset
Length of output: 1683
🏁 Script executed:
#!/bin/bash
# Look for migration files in packages/db
find packages/db -type f -name "*.sql" -o -name "*.ts" | grep -i migr | head -20Repository: superset-sh/superset
Length of output: 110
🏁 Script executed:
#!/bin/bash
# Read the schema file focusing on lines around 19 and 32
sed -n '1,50p' packages/db/src/schema/schema.ts | cat -nRepository: superset-sh/superset
Length of output: 1683
🏁 Script executed:
#!/bin/bash
# Check git history for changes to clerkId
git log --oneline --all -- packages/db/src/schema/schema.ts | head -20Repository: superset-sh/superset
Length of output: 187
🏁 Script executed:
#!/bin/bash
# Read the initial migration to see the schema
cat packages/db/drizzle/0000_initial_migration.sqlRepository: superset-sh/superset
Length of output: 5073
Migration file is missing for the auth0Id field addition.
The schema definition at line 19 is correct (auth0Id: text("auth0_id").notNull().unique()), and the index at line 32 is properly configured. However, no migration file exists to add this field to the database. The initial migration (0000_initial_migration.sql) does not include the auth0_id column in the users table.
Generate the migration file by running:
bun drizzle-kit generate --name="add_auth0_id"
This will create the necessary migration to add the auth0_id column with the proper constraints to the database schema.
🤖 Prompt for AI Agents
In packages/db/src/schema/schema.ts around line 19, you added auth0Id:
text("auth0_id").notNull().unique() but did not generate a migration; run bun
drizzle-kit generate --name="add_auth0_id" to create the migration, then edit
the generated SQL so it safely adds the auth0_id column and constraints (for
existing data: add column nullable, backfill/populate values or set a temporary
default, create the UNIQUE index, and then ALTER COLUMN to NOT NULL), or
otherwise ensure the migration includes steps to avoid violating NOT NULL/UNIQUE
on existing rows before finalizing the NOT NULL constraint.
| me: protectedProcedure.query(async ({ ctx }) => { | ||
| return db.query.users.findFirst({ | ||
| where: eq(users.clerkId, ctx.session.userId), | ||
| where: eq(users.auth0Id, ctx.session.user.sub), | ||
| }); | ||
| }), |
There was a problem hiding this comment.
Consider error handling for missing user in the me query.
The migration from clerkId to auth0Id is correct. However, the me resolver can return undefined if no user matches the auth0Id, even though the user has a valid authenticated session. This inconsistency could occur if:
- The database migration hasn't run yet
- The user record was deleted but the session is still valid
- There's a mismatch between Auth0 and the database
Compare this with packages/trpc/src/router/task.ts (line 78), which throws "User not found" in a similar scenario. Consider either:
- Throwing an error for consistency
- Documenting that
undefinedis an expected return value
Apply this diff for consistent error handling:
me: protectedProcedure.query(async ({ ctx }) => {
- return db.query.users.findFirst({
+ const user = await db.query.users.findFirst({
where: eq(users.auth0Id, ctx.session.user.sub),
});
+ if (!user) {
+ throw new Error("User not found");
+ }
+ return user;
}),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| me: protectedProcedure.query(async ({ ctx }) => { | |
| return db.query.users.findFirst({ | |
| where: eq(users.clerkId, ctx.session.userId), | |
| where: eq(users.auth0Id, ctx.session.user.sub), | |
| }); | |
| }), | |
| me: protectedProcedure.query(async ({ ctx }) => { | |
| const user = await db.query.users.findFirst({ | |
| where: eq(users.auth0Id, ctx.session.user.sub), | |
| }); | |
| if (!user) { | |
| throw new Error("User not found"); | |
| } | |
| return user; | |
| }), |
🤖 Prompt for AI Agents
In packages/trpc/src/router/user.ts around lines 9 to 13, the me resolver can
return undefined when no user matches the auth0Id; update the handler to mirror
task.ts by checking the query result and throwing a TRPCError (e.g., code
'NOT_FOUND' with message "User not found") when the DB returns no user, and
ensure TRPCError is imported at the top of the file; this makes behavior
consistent rather than returning undefined.
Summary
@superset/auth0shared package with server/client exportsChanges
packages/auth0/- Auth0 client wrapper with typed session helpersclerkId→auth0Id(migration needed)ClerkProviderwithAuth0Provider, updated middlewareTest plan
http://localhost:3000/api/auth/callback.envbun drizzle-kit generate --name="rename_clerk_to_auth0"🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.