{"record":{"id":"093c53c7adc42981","repo":"amir20/dozzle","slug":"unauthorized","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"http","errorClass":null,"httpStatus":401,"severity":"error","filePath":"internal/auth/users.go","lineNumber":198,"sourceCode":"// request. Both providers resolve the user themselves: proxy auth from the request\n// headers, simple auth from users.yml keyed by the verified token's username. Roles\n// deliberately are not read back out of the JWT, because a bitmask frozen at login\n// goes stale the moment the role set grows or users.yml changes.\nfunc UserFromContext(ctx context.Context) *User {\n\tif user, ok := ctx.Value(remoteUser).(User); ok {\n\t\treturn &user\n\t}\n\n\treturn nil\n}\n\nfunc RequireAuthentication(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tuser := UserFromContext(r.Context())\n\t\tif user != nil {\n\t\t\tnext.ServeHTTP(w, r)\n\t\t} else {\n\t\t\thttp.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)\n\t\t}\n\t})\n}\n","sourceCodeStart":180,"sourceCodeEnd":202,"githubUrl":"https://github.com/amir20/dozzle/blob/d9463cbe21874e44ab79db6fa63e746ca7d22928/internal/auth/users.go#L180-L202","documentation":"RequireAuthentication middleware checks the request context for a User; if none is present the request is rejected with 401 Unauthorized. It means no authenticated session/JWT was established before reaching a protected route.","triggerScenarios":"Hitting any route wrapped in RequireAuthentication without a valid JWT cookie, an expired token, or when auth is configured (simple mode) but the client never logged in.","commonSituations":"JWT expired after TTL; browser deleted cookies; API/script calls missing the login step; clock skew invalidating tokens; calling protected endpoints before POST /api/auth/... token creation.","solutions":["Log in to obtain a JWT cookie before calling protected endpoints","Clear cookies and re-authenticate if the token expired","Include the JWT cookie when calling the API from scripts/curl","Check DOZZLE_LEVEL=debug logs to see why user was not populated (bad signature, missing cookie)"],"exampleFix":"// before\ncurl http://dozzle/api/containers\n// after\ncurl -c cookies.txt -d 'user=admin&password=...' http://dozzle/api/token\ncurl -b cookies.txt http://dozzle/api/containers","handlingStrategy":"retry","validationCode":"const hasJwt = document.cookie.split(';').some(c => c.trim().startsWith('jwt='));\nif (!hasJwt) location.href = '/login';","typeGuard":null,"tryCatchPattern":"const res = await fetch(url, {credentials: 'include'});\nif (res.status === 401) {\n  await login(); // re-authenticate, then retry once\n  return fetch(url, {credentials: 'include'});\n}","preventionTips":["Re-authenticate before long-running scripts hit protected APIs","Include credentials: 'include' on cross-origin calls","Monitor JWT TTL and refresh proactively in long sessions"],"tags":["auth","unauthorized","jwt","middleware"],"backgroundTag":"authentication-required","analyzedSha":"d9463cbe21874e44ab79db6fa63e746ca7d22928","analyzedAt":"2026-09-07T10:08:55.855Z","contentChangedAt":"2026-09-07T10:08:55.855Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}