nicolargo/glances · error · HTTPException

Incorrect authentication

Error message

Incorrect authentication

What it means

During FastAPI dependency authentication, a client sent an 'Authorization: Bearer <token>' header, but the JWT verification either failed (verify_token returned None — expired/invalid signature/token) or the verified subject doesn't equal the configured args.username. Glances rejects immediately with 401 and WWW-Authenticate: Bearer rather than falling back to Basic auth.

Source

Thrown at glances/outputs/glances_restful_api.py:458

        basic_creds: Annotated[HTTPBasicCredentials | None, Depends(security)] = None,
    ):
        """Check if a username/password combination or JWT token is valid.

        Supports both HTTP Basic Auth and Bearer Token (JWT) authentication.
        JWT Bearer tokens are checked first (manually from header) to avoid
        HTTPBasic(auto_error=True) rejecting Bearer Authorization headers.
        If no Bearer token is found, HTTPBasic handles the browser auth dialog.
        """
        # Try JWT Bearer token first (manually from request header)
        if self._jwt_handler is not None and self._jwt_handler.is_available:
            auth_header = request.headers.get("Authorization", "")
            if auth_header.lower().startswith("bearer "):
                token = auth_header.split(" ", 1)[1]
                username = self._jwt_handler.verify_token(token)
                if username is not None and username == self.args.username:
                    return username
                # Invalid Bearer token - reject immediately
                raise HTTPException(
                    status.HTTP_401_UNAUTHORIZED,
                    "Incorrect authentication",
                    {"WWW-Authenticate": "Bearer"},
                )

        # Fall back to Basic Auth
        # If no credentials provided (basic_creds is None), trigger browser dialog
        if basic_creds is None:
            # Force HTTPBasic auto_error behavior to trigger browser auth dialog
            raise HTTPException(
                status.HTTP_401_UNAUTHORIZED,
                "Not authenticated",
                {"WWW-Authenticate": "Basic"},
            )

        if basic_creds.username == self.args.username:
            if self._password.check_password(self.args.password, self._password.get_hash(basic_creds.password)):
                return basic_creds.username

View on GitHub (pinned to a240d8dfb3)

Solutions

  1. POST to /api/4/token with username/password to obtain a fresh Bearer token and retry.
  2. If tokens suddenly all fail, check whether the JWT secret changed (secret file/config) — tokens signed by the old secret are permanently invalid; restart clients to re-auth.
  3. Make sure the token's username matches glances' configured --username.

Example fix

# before
curl -H 'Authorization: Bearer <stale-token>' http://host:61208/api/4/cpu
# 401 Incorrect authentication

# after
TOKEN=$(curl -s -X POST http://host:61208/api/4/token -d '{"username":"nicolargo","password":"pass"}' | jq -r .access_token)
curl -H "Authorization: Bearer $TOKEN" http://host:61208/api/4/cpu
Defensive patterns

Strategy: try-catch

Validate before calling

resp = requests.post(f'{base}/api/4/token', json=creds)
if resp.status_code != 200:
    raise SystemExit('refresh credentials')
token = resp.json()['access_token']

Try / catch

r = requests.get(url, headers={'Authorization': f'Bearer {token}'})
if r.status_code == 401:
    token = requests.post(f'{base}/api/4/token', json=creds).json()['access_token']
    r = requests.get(url, headers={'Authorization': f'Bearer {token}'})

Prevention

When it happens

Trigger: curl -H 'Authorization: Bearer xxx' against a --password protected Glances REST API with an expired token, a token minted with a different secret (e.g. after regenerating the JWT secret), or a token whose sub is not the configured username.

Common situations: Long-running scripts holding tokens past expiry; containers recreated losing the persisted JWT secret so old tokens no longer verify; proxies injecting stale Authorization headers.

Understand the failure class

Related errors


AI-assisted analysis of nicolargo/glances@a240d8dfb3 (2026-08-27). Data as JSON: /api/errors/6c2cc58ba8c78096. Report an issue: GitHub.