{"record":{"id":"a4187a38cf8d9a7e","repo":"coder/code-server","slug":"unauthorized","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"http","errorClass":"HttpError","httpStatus":401,"severity":"error","filePath":"src/node/http.ts","lineNumber":107,"sourceCode":"\n/**\n * Return true if proxy is enabled.\n */\nexport const proxyEnabled = (req: express.Request): boolean => {\n  return !req.args[\"disable-proxy\"]\n}\n\n/**\n * Throw an error if not authorized. Call `next` if provided.\n */\nexport const ensureAuthenticated = async (\n  req: express.Request,\n  _?: express.Response,\n  next?: express.NextFunction,\n): Promise<void> => {\n  const isAuthenticated = await authenticated(req)\n  if (!isAuthenticated) {\n    throw new HttpError(\"Unauthorized\", HttpCode.Unauthorized)\n  }\n  if (next) {\n    next()\n  }\n}\n\n/**\n * Return true if authenticated via cookies.\n */\nexport const authenticated = async (req: express.Request): Promise<boolean> => {\n  switch (req.args.auth) {\n    case AuthType.None: {\n      return true\n    }\n    case AuthType.Password: {\n      // The password is stored in the cookie after being hashed.\n      const hashedPasswordFromArgs = req.args[\"hashed-password\"]\n      const passwordMethod = getPasswordMethod(hashedPasswordFromArgs)","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/coder/code-server/blob/51f90a376b42e217b38937410fe2855e0c1db87e/src/node/http.ts#L89-L125","documentation":"ensureAuthenticated (http.ts:107) is the auth middleware for protected routes. It awaits authenticated(req), which validates the session cookie against the configured auth method; if validation fails it throws HttpError 401 Unauthorized. This is the primary gate for non-login pages when auth is enabled.","triggerScenarios":"Any request to a protected route without a valid session cookie: expired cookie, never logged in, cookie cleared, or session invalidated by a restart with a new COOKIE_KEY.","commonSituations":"Sessions expiring mid-work; restarting code-server in a way that rotates the signing key; browsers with aggressive cookie cleanup; clock skew breaking cookie expiry.","solutions":["Redirect the user to /login to obtain a fresh session cookie","Ensure PASSWORD/HASHED_PASSWORD is stable across restarts so the cookie stays valid","Check that the system clock is correct (significant skew can invalidate cookies)"],"exampleFix":"// before: hitting a protected route with no/expired cookie -> 401\n\n// after: redirect to login, then re-request\nfetch('/login', { method: 'POST', body: 'password=...' })\n  .then(() => fetch('/api/protected'))","handlingStrategy":"try-catch","validationCode":"// Client-side: check auth before protected calls\nasync function isAuthenticated(): Promise<boolean> {\n  const r = await fetch(\"/api/status\")\n  return r.ok\n}\nif (!await isAuthenticated()) window.location.href = \"/login\"","typeGuard":"import { HttpError, HttpCode } from \"../../common/http\"\nfunction isUnauthorizedError(e: unknown): boolean {\n  return e instanceof HttpError && e.status === HttpCode.Unauthorized\n}","tryCatchPattern":"try {\n  await ensureAuthenticated(req, res, next)\n} catch (e) {\n  if (e instanceof HttpError && e.status === HttpCode.Unauthorized) {\n    redirect(req, res, \"login\", { to: req.originalUrl })\n  } else throw e\n}","preventionTips":["Keep PASSWORD/HASHED_PASSWORD stable across restarts to preserve cookies","Handle 401 in clients by redirecting to /login","Avoid rotating the cookie signing key unnecessarily"],"tags":["http","auth","middleware","session","unauthorized"],"backgroundTag":null,"analyzedSha":"51f90a376b42e217b38937410fe2855e0c1db87e","analyzedAt":"2026-08-12T11:27:34.273Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}