Skip to content

fix(api): return 401 and a null auth check instead of a generic 500 when the token is missing - #1445

Merged
benoit-cty merged 5 commits into
masterfrom
fix/auth-401-on-missing-token
Nov 1, 2026
Merged

benoit-cty merged 5 commits into
masterfrom
fix/auth-401-on-missing-token

Conversation

@davidberenstein1957

Copy link
Copy Markdown
Collaborator

Description

Two small changes in the API's authentication path so a missing or rejected token never ends in the catch-all {"detail": "Generic error"} 500:

  • GET /auth/check with no token used to call check_jwt_user(None, create=True), which does None["sub"] and raises TypeError. It now returns {"user": null} straight away, which is what its docstring already promised.
  • A missing token on a mandatory-auth endpoint raised a bare HTTPException(401, "Unauthorized"). It now raises the project's AuthenticationError, so the response is 401 with detail: "Missing or invalid access token" and a WWW-Authenticate: Bearer header, the same shape as an invalid or expired token.

The generic 500 handler is unchanged. The webapp already redirects to login on a 401 (webapp/src/api/errors.ts), so no frontend change is needed.

Related Issue

Fixes #692

Motivation and Context

With an expired or removed token, the dashboard showed a blank page with {"detail": "Generic error"} instead of sending the user to the login screen. The /auth/check call is the first thing the UI makes, so the TypeError there turned every expired session into that page.

How Has This Been Tested?

New tests in carbonserver/tests/api/routers/test_authenticate.py, each written before its fix and failing against the previous code:

  • test_auth_check_without_token_returns_null_user: 500 before, 200 {"user": null} after. The sign-up service is mocked to raise TypeError on None, mirroring the real service.
  • test_protected_endpoint_without_token_returns_401: detail was "Unauthorized", now "Missing or invalid access token" with the WWW-Authenticate header.
  • test_protected_endpoint_with_invalid_token_returns_401: regression guard, passed before and after.

uv run task test-api-unit: 43, 65, 6 and 1 passed, 1 skipped, 1 xpassed. pre-commit passes on the touched files. Not run: the integration tests against Postgres, and the real SignUpService with a None token (covered by the mock only).

Screenshots (if appropriate):

N/A

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

AI Usage Disclosure

Please refer to docs/how-to/ai-policy.md for detailed guidelines on how to disclose AI usage in your PR. Accurately completing this section is mandatory.

  • 🟥 AI-vibecoded: You cannot explain the logic. Car analogy : the car drive by itself, you are outside it and just tell it where to go.
  • 🟠 AI-generated: Car analogy : the car drive by itself, you are inside and give instructions.
  • ⭐ AI-assisted. Car analogy : you drive the car, AI help you find your way.
  • ♻️ No AI used. Car analogy : you drive the car.

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the docs/how-to/contributing.md document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

Commits

  • 6e587df test: protected endpoints return 401 with a clear detail when the token is missing or invalid
  • 86c327d fix: name the problem in the 401 returned when the access token is missing
  • bded5b3 test: auth check without a token should return a null user
  • 69deb9c fix: auth check returns a null user instead of crashing when no token is sent

@davidberenstein1957
davidberenstein1957 requested a review from a team as a code owner October 12, 2026 06:59
@benoit-cty
benoit-cty force-pushed the fix/auth-401-on-missing-token branch from 69deb9c to e32590d Compare October 31, 2026 14:03

Copy link
Copy Markdown
Contributor

Rebased on master and reviewed. Summary:

  • Rebase: one conflict, in carbonserver/tests/api/routers/test_authenticate.py. master had added logout and account-URL tests at the same place where this PR adds its tests. I kept both sets. Your 4 commits are now 9a2d500, 23729a7, 8afe546 and 6751525.
  • Review: the change looks correct and minimal. /auth/check returns {"user": null} when there is no token. A missing token on a protected endpoint now raises AuthenticationError, so it returns 401 with WWW-Authenticate: Bearer. The webapp already redirects to login on a 401. There were no earlier review comments to address.
  • Fix: e32590d test(api): assert the WWW-Authenticate header on the missing-token 401. The PR description says the test checks this header, but it didn't assert it.
  • Tests: uv run task test-api-unit gives 50 passed + 1 xpassed, 73 passed + 1 skipped, 6 passed and 3 passed. pre-commit passes on the touched files.
  • Coverage: all changed source lines are covered (authenticate.py L39-40, auth_service.py L85).
  • Docs: no change needed.
  • Left open: the Postgres integration tests were not run, and the real SignUpService with a None token is only covered by the mock. The AI Usage Disclosure box in the description still needs to be ticked by @davidberenstein1957.

Generated by Claude Code

@benoit-cty
benoit-cty force-pushed the fix/auth-401-on-missing-token branch from e32590d to ea3f27a Compare November 1, 2026 13:41
@benoit-cty
benoit-cty enabled auto-merge November 1, 2026 13:41
@benoit-cty
benoit-cty merged commit 14407e4 into master Nov 1, 2026
8 checks passed
@benoit-cty
benoit-cty deleted the fix/auth-401-on-missing-token branch November 1, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API] Missing token returns Generic error

3 participants