diff --git a/apps/api/src/common/guards/csrf.guard.spec.ts b/apps/api/src/common/guards/csrf.guard.spec.ts index 82c9685..50aa121 100644 --- a/apps/api/src/common/guards/csrf.guard.spec.ts +++ b/apps/api/src/common/guards/csrf.guard.spec.ts @@ -87,6 +87,17 @@ describe("CsrfGuard", () => { }); describe("State-changing methods requiring CSRF", () => { + it("should allow POST with Bearer auth without CSRF token", () => { + const context = createContext( + "POST", + {}, + { authorization: "Bearer api-token" }, + false, + "user-123" + ); + expect(guard.canActivate(context)).toBe(true); + }); + it("should reject POST without CSRF token", () => { const context = createContext("POST", {}, {}, false, "user-123"); expect(() => guard.canActivate(context)).toThrow(ForbiddenException); diff --git a/apps/api/src/common/guards/csrf.guard.ts b/apps/api/src/common/guards/csrf.guard.ts index 805a224..82e0156 100644 --- a/apps/api/src/common/guards/csrf.guard.ts +++ b/apps/api/src/common/guards/csrf.guard.ts @@ -57,6 +57,11 @@ export class CsrfGuard implements CanActivate { return true; } + const authHeader = request.headers.authorization; + if (typeof authHeader === "string" && authHeader.startsWith("Bearer ")) { + return true; + } + // Get CSRF token from cookie and header const cookies = request.cookies as Record | undefined; const cookieToken = cookies?.["csrf-token"];