{"record":{"id":"8cae0e1320d011af","repo":"gitroomhq/postiz-app","slug":"forbidden-8cae0e","errorCode":null,"errorMessage":"Forbidden","messagePattern":"Forbidden","errorType":"http","errorClass":"HttpForbiddenException","httpStatus":403,"severity":"error","filePath":"apps/backend/src/services/auth/auth.middleware.ts","lineNumber":37,"sourceCode":"          sameSite: 'none',\n        }\n      : {}),\n    expires: new Date(0),\n    maxAge: -1,\n  });\n  res.header('logout', 'true');\n};\n\n@Injectable()\nexport class AuthMiddleware implements NestMiddleware {\n  constructor(\n    private _organizationService: OrganizationService,\n    private _userService: UsersService\n  ) {}\n  async use(req: Request, res: Response, next: NextFunction) {\n    const auth = req.headers.auth || req.cookies.auth;\n    if (!auth) {\n      throw new HttpForbiddenException();\n    }\n    try {\n      // Verify the JWT signature only. Never trust authorization-relevant\n      // claims (id, isSuperAdmin, activated) from the token body — always\n      // re-resolve the user from the database using the id.\n      const payload = AuthService.verifyJWT(auth) as User | null;\n      const orgHeader = req.cookies.showorg || req.headers.showorg;\n\n      if (!payload?.id) {\n        throw new HttpForbiddenException();\n      }\n\n      let user = (await this._userService.getUserById(payload.id)) as User | null;\n\n      if (!user) {\n        throw new HttpForbiddenException();\n      }\n","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/apps/backend/src/services/auth/auth.middleware.ts#L19-L55","documentation":"The auth middleware requires a JWT on every authenticated request, read from the auth header or the auth cookie. If neither is present it immediately throws HttpForbiddenException (403 'Forbidden') before any JWT verification happens. This is the missing-credentials gate for the dashboard/API.","triggerScenarios":"Any request to a route guarded by this middleware without an Authorization/auth header and without an auth cookie — e.g. curl/API client forgetting the token, cookie lost after logout or expiry, cross-domain request where cookies are not sent (SameSite), or first request after session clear.","commonSituations":"Scripts calling authenticated endpoints without attaching the JWT; browser cookie blocked by SameSite/None misconfiguration when frontend and backend are on different origins; session cookie expired or cleared; reverse proxy stripping the auth header.","solutions":["Attach the JWT: pass it in the auth header or ensure the auth cookie is sent with the request","For API clients, obtain the token via login and set the header on every request","For browsers, verify cookies survive the cross-origin setup (credentials: 'include', correct SameSite/CORS config)","Check that a proxy/gateway is not dropping the auth header or Cookie"],"exampleFix":"// before\nawait fetch(`${API}/posts`, { method: 'GET' }); // 403\n\n// after\nawait fetch(`${API}/posts`, {\n  method: 'GET',\n  headers: { auth: token },        // or rely on credentials: 'include' for cookies\n  credentials: 'include',\n});","handlingStrategy":"validation","validationCode":"const auth = getAuthCookie() ?? getStoredToken();\nif (!auth) throw new Error('Missing credentials — login before calling authenticated routes');\nawait api.call({ headers: { auth } });","typeGuard":"const hasCredentials = (req: { headers: Record<string, unknown>; cookies: Record<string, unknown> }): boolean =>\n  !!(req.headers?.auth || req.cookies?.auth);","tryCatchPattern":"try {\n  await api.get('/protected');\n} catch (e: any) {\n  if (e?.status === 403 && !getAuthCookie()) {\n    await redirectToLogin(); return;\n  }\n  throw e;\n}","preventionTips":["Centralize token attachment in one HTTP client/interceptor so no call forgets it","For cross-origin browser apps set credentials: 'include' and correct SameSite/CORS","Never assume cookies carry over between domains or after logout"],"tags":["auth","middleware","missing-credentials","http-403"],"backgroundTag":"missing-auth-credentials","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}