{"record":{"id":"4a03edc4a6d9032e","repo":"toeverything/AFFiNE","slug":"authentication-required-4a03ed","errorCode":"authentication_required","errorMessage":"You must sign in first to access this resource.","messagePattern":"You must sign in first to access this resource\\.","errorType":"exception","errorClass":"AuthenticationRequired","httpStatus":401,"severity":"error","filePath":"packages/backend/server/src/core/auth/guard.ts","lineNumber":115,"sourceCode":"        }\n      }\n      throw new AccessDenied('Invalid internal request');\n    }\n\n    // api is public\n    const isPublic = this.reflector.getAllAndOverride<boolean>(\n      PUBLIC_ENTRYPOINT_SYMBOL,\n      [clazz, handler]\n    );\n\n    const authedUser = await this.signIn(req, res, isPublic);\n\n    if (isPublic) {\n      return true;\n    }\n\n    if (!authedUser) {\n      throw new AuthenticationRequired();\n    }\n\n    return true;\n  }\n\n  async signIn(\n    req: Request,\n    res?: Response,\n    isPublic = false\n  ): Promise<Session | null> {\n    const result = await this.resolveRequestSession(req, res, isPublic);\n    return result?.session ?? null;\n  }\n\n  private async resolveRequestSession(\n    req: Request,\n    res?: Response,\n    isPublic = false","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/packages/backend/server/src/core/auth/guard.ts#L97-L133","documentation":"Thrown by `AuthGuard.canActivate` for a non-`@Public`, non-`@Internal` endpoint when `signIn` resolved to no session (no cookie, no JWT, or both invalid/absent). HTTP 401. This is the primary 'not logged in' gate for the whole HTTP API.","triggerScenarios":"Calling any protected route without a session cookie or Bearer JWT, with an expired cookie session that `getUserSessionFromRequest` could not revive, or with a non-JWT Authorization header that `extractTokenFromHeader` rejected.","commonSituations":"Session expired and the refresh path did not run, the client forgot `credentials: 'include'`, a script/bot hit a protected URL, or a native client used an expired access token without refreshing.","solutions":["Authenticate first (sign in / refresh) and reissue the request with the resulting cookie or Bearer token.","Ensure cookies are sent (`credentials: 'include'`) and the SameSite policy permits them.","For native clients, refresh the access token via `/session/refresh` when it expires."],"exampleFix":"// before\nfetch('/api/auth/methods'); // 401\n\n// after\nfetch('/api/auth/methods', { credentials: 'include' });\n// or\nfetch('/api/auth/methods', {\n  headers: { authorization: `Bearer ${accessToken}` },\n});","handlingStrategy":"validation","validationCode":"async function ensureAuthed(): Promise<void> {\n  const r = await fetch('/api/auth/session', { credentials: 'include' });\n  if (r.status === 401) location.href = '/sign-in';\n}\nawait ensureAuthed();\nawait fetch(protectedUrl, { credentials: 'include' });","typeGuard":null,"tryCatchPattern":"try {\n  await fetch(protectedUrl, { credentials: 'include' });\n} catch (e) {\n  // network error; not auth\n}\n// HTTP 401 handling\nif (res.status === 401) { redirectToLogin(); }","preventionTips":["Check the session before calling protected endpoints.","Send `credentials: 'include'` (browser) or a valid Bearer token (native).","Intercept 401 globally and refresh/re-authenticate once before failing."],"tags":["authentication","guard","unauthorized","session"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}