From 3376d8162ef9117f1d253f7bbda538a9b3c3d3ab Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Mon, 16 Feb 2026 03:41:50 -0600 Subject: [PATCH] fix(#410): skip CSRF guard on auth catch-all route The global CsrfGuard blocks POST /auth/sign-in/oauth2 with 403 because unauthenticated users have no session and therefore no CSRF token. BetterAuth handles its own CSRF protection via toNodeHandler(). Co-Authored-By: Claude Opus 4.6 --- apps/api/src/auth/auth.controller.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/api/src/auth/auth.controller.ts b/apps/api/src/auth/auth.controller.ts index c632bbc..c3f98b6 100644 --- a/apps/api/src/auth/auth.controller.ts +++ b/apps/api/src/auth/auth.controller.ts @@ -5,6 +5,7 @@ import type { AuthUser, AuthSession } from "@mosaic/shared"; import { AuthService } from "./auth.service"; import { AuthGuard } from "./guards/auth.guard"; import { CurrentUser } from "./decorators/current-user.decorator"; +import { SkipCsrf } from "../common/decorators/skip-csrf.decorator"; interface RequestWithSession { user?: AuthUser; @@ -88,6 +89,7 @@ export class AuthController { * Rate limiting and logging are applied to mitigate abuse (SEC-API-10). */ @All("*") + @SkipCsrf() @Throttle({ strict: { limit: 10, ttl: 60000 } }) async handleAuth(@Req() req: ExpressRequest, @Res() res: ExpressResponse): Promise { // Extract client IP for logging