{"record":{"id":"80c25e43e78f5d2b","repo":"nicolargo/glances","slug":"not-authenticated","errorCode":null,"errorMessage":"Not authenticated","messagePattern":"Not authenticated","errorType":"http","errorClass":"HTTPException","httpStatus":401,"severity":"warning","filePath":"glances/outputs/glances_restful_api.py","lineNumber":468,"sourceCode":"        if self._jwt_handler is not None and self._jwt_handler.is_available:\n            auth_header = request.headers.get(\"Authorization\", \"\")\n            if auth_header.lower().startswith(\"bearer \"):\n                token = auth_header.split(\" \", 1)[1]\n                username = self._jwt_handler.verify_token(token)\n                if username is not None and username == self.args.username:\n                    return username\n                # Invalid Bearer token - reject immediately\n                raise HTTPException(\n                    status.HTTP_401_UNAUTHORIZED,\n                    \"Incorrect authentication\",\n                    {\"WWW-Authenticate\": \"Bearer\"},\n                )\n\n        # Fall back to Basic Auth\n        # If no credentials provided (basic_creds is None), trigger browser dialog\n        if basic_creds is None:\n            # Force HTTPBasic auto_error behavior to trigger browser auth dialog\n            raise HTTPException(\n                status.HTTP_401_UNAUTHORIZED,\n                \"Not authenticated\",\n                {\"WWW-Authenticate\": \"Basic\"},\n            )\n\n        if basic_creds.username == self.args.username:\n            if self._password.check_password(self.args.password, self._password.get_hash(basic_creds.password)):\n                return basic_creds.username\n\n        # Invalid credentials\n        raise HTTPException(\n            status.HTTP_401_UNAUTHORIZED,\n            \"Incorrect authentication\",\n            {\"WWW-Authenticate\": \"Basic\"},\n        )\n\n    def _logo(self):\n        return rf\"\"\"","sourceCodeStart":450,"sourceCodeEnd":486,"githubUrl":"https://github.com/nicolargo/glances/blob/a240d8dfb3105a38b5964357ec21768594b0e83e/glances/outputs/glances_restful_api.py#L450-L486","documentation":"When the REST API runs with --password and a request carries no Authorization header at all, FastAPI's HTTPBasic yields no credentials, so Glances raises 401 'Not authenticated' with WWW-Authenticate: Basic to trigger the browser login dialog. It's the standard challenge response, not a malfunction — though programmatic clients see it as an error.","triggerScenarios":"Accessing any /api/4/* endpoint (or the web UI) of a password-protected Glances without credentials: plain curl http://host:61208/api/4/version, opening in a browser (dialog appears), or a monitoring scraper that forgot auth.","commonSituations":"Grafana/Netdata-style pollers pointed at Glances without configuring basic auth; browser first visit; scripts after password mode was newly enabled.","solutions":["Send basic auth: curl -u user:pass http://host:61208/api/4/...","Or obtain and send a Bearer token via POST /api/4/token.","Configure credentials in whatever client (browser will prompt and remember)."],"exampleFix":"# before\ncurl http://host:61208/api/4/cpu\n# 401 Not authenticated\n\n# after\ncurl -u nicolargo:secret http://host:61208/api/4/cpu","handlingStrategy":"fallback","validationCode":"if args.password:  # server runs authenticated\n    client = requests.Session()\n    client.auth = (username, password)  # always attach credentials","typeGuard":null,"tryCatchPattern":"r = requests.get(url)\nif r.status_code == 401 and 'WWW-Authenticate: Basic' in r.headers.get('WWW-Authenticate', ''):\n    r = requests.get(url, auth=(user, pwd))","preventionTips":["Configure credentials in every client (curl -u, requests auth=, Grafana datasource auth).","Treat 401 Basic challenge as expected first contact for browsers."],"tags":["authentication","http-401","basic-auth","rest-api"],"backgroundTag":"http-auth-challenge","analyzedSha":"a240d8dfb3105a38b5964357ec21768594b0e83e","analyzedAt":"2026-08-27T19:15:19.178Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}