Description
GET /api/0/auth/ returns 400 Bad Request when called with a valid Authorization: Bearer <token> header. The token is valid — Django middleware successfully resolves it (visible as DB spans in the trace) — but DRF's authentication pipeline does not recognize it because BaseAuthIndexEndpoint overrides authentication_classes to exclude UserAuthTokenAuthentication.
Root Cause
In src/sentry/api/endpoints/auth_index.py line 50:
class BaseAuthIndexEndpoint(Endpoint):
authentication_classes = (QuietBasicAuthentication, SessionAuthentication)
This excludes UserAuthTokenAuthentication (which handles Bearer tokens) and OrgAuthTokenAuthentication. When the CLI sends Authorization: Bearer <oauth-token>:
QuietBasicAuthentication.authenticate() — sees "Bearer" (not "Basic") → returns None
SessionAuthentication.authenticate() — no session cookie → returns None
- DRF falls through to
AnonymousUser
get() checks request.user.is_authenticated → False → returns Response(status=400)
The token DB lookups visible in the trace are from Django middleware before DRF's pipeline — DRF doesn't carry them over (no __from_api_client__ flag).
Impact
This affects external API clients using Bearer token auth to call GET /api/0/auth/. The Sentry CLI uses this endpoint for the sentry auth whoami command.
In practice, the CLI's response cache often masks this — users see the bug only on cache misses or first-time calls.
Connected trace: https://sentry.sentry.io/issues/trace/eca083e61dbf4404a19fbb1db271ae73/?node=span-942aff1d7909b9a7
Suggested Fix
Add UserAuthTokenAuthentication to the authentication classes:
from sentry.api.authentication import QuietBasicAuthentication, UserAuthTokenAuthentication
class BaseAuthIndexEndpoint(Endpoint):
authentication_classes = (UserAuthTokenAuthentication, QuietBasicAuthentication, SessionAuthentication)
UserAuthTokenAuthentication should come first so Bearer tokens are resolved before falling through to basic/session auth.
Secondary issue
Org-scoped tokens would still fail because /api/0/auth/ (sentry-api-0-auth) is not in the org-endpoint allowlist checked by UserAuthTokenAuthentication.authenticate_token(). That URL name may also need to be added to the allowlist for full compatibility.
Description
GET /api/0/auth/returns 400 Bad Request when called with a validAuthorization: Bearer <token>header. The token is valid — Django middleware successfully resolves it (visible as DB spans in the trace) — but DRF's authentication pipeline does not recognize it becauseBaseAuthIndexEndpointoverridesauthentication_classesto excludeUserAuthTokenAuthentication.Root Cause
In
src/sentry/api/endpoints/auth_index.pyline 50:This excludes
UserAuthTokenAuthentication(which handlesBearertokens) andOrgAuthTokenAuthentication. When the CLI sendsAuthorization: Bearer <oauth-token>:QuietBasicAuthentication.authenticate()— sees "Bearer" (not "Basic") → returnsNoneSessionAuthentication.authenticate()— no session cookie → returnsNoneAnonymousUserget()checksrequest.user.is_authenticated→False→ returnsResponse(status=400)The token DB lookups visible in the trace are from Django middleware before DRF's pipeline — DRF doesn't carry them over (no
__from_api_client__flag).Impact
This affects external API clients using Bearer token auth to call
GET /api/0/auth/. The Sentry CLI uses this endpoint for thesentry auth whoamicommand.In practice, the CLI's response cache often masks this — users see the bug only on cache misses or first-time calls.
Connected trace: https://sentry.sentry.io/issues/trace/eca083e61dbf4404a19fbb1db271ae73/?node=span-942aff1d7909b9a7
Suggested Fix
Add
UserAuthTokenAuthenticationto the authentication classes:UserAuthTokenAuthenticationshould come first so Bearer tokens are resolved before falling through to basic/session auth.Secondary issue
Org-scoped tokens would still fail because
/api/0/auth/(sentry-api-0-auth) is not in the org-endpoint allowlist checked byUserAuthTokenAuthentication.authenticate_token(). That URL name may also need to be added to the allowlist for full compatibility.