fix(auth): accept a raw token on the Otari-Key header, not just Bearer#323
Conversation
|
Warning Review limit reached
Next review available in: 19 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
WalkthroughBranded API key headers now accept raw tokens and optional ChangesAPI key header authentication
Estimated code review effort: 3 (Moderate) | ~15 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/gateway/api/deps.py (1)
77-92: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider using
str.removeprefix().Since this codebase uses Python 3.10+ (as indicated by the
|union type syntax in other functions), you can optionally simplify the prefix stripping by utilizing the built-inremoveprefixmethod. It's a clean, pythonic way to replace the.startswith()condition and string slicing.💡 Proposed refactor
- for header in (API_KEY_HEADER, *LEGACY_API_KEY_HEADERS): - value = request.headers.get(header) - if value: - return value[7:] if value.startswith("Bearer ") else value + for header in (API_KEY_HEADER, *LEGACY_API_KEY_HEADERS): + value = request.headers.get(header) + if value: + return value.removeprefix("Bearer ")🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/gateway/api/deps.py` around lines 77 - 92, Update the prefix handling in the API key extraction loop of the request-header function to use Python’s str.removeprefix() for removing "Bearer ". Preserve the existing behavior for raw tokens and legacy headers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/gateway/api/deps.py`:
- Around line 77-92: Update the prefix handling in the API key extraction loop
of the request-header function to use Python’s str.removeprefix() for removing
"Bearer ". Preserve the existing behavior for raw tokens and legacy headers.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: c5f0fbdb-5850-4779-a059-a781583296e6
📒 Files selected for processing (3)
src/gateway/api/deps.pytests/integration/test_key_management.pytests/unit/test_extract_bearer_token.py
|
Reviewed — LGTM, no blocking issues. Checked correctness, the security posture, tests, and docs:
Optional nit (non-blocking): the helper is still named Review created by Claude Code. |
There was a problem hiding this comment.
Pull request overview
Aligns gateway authentication with the dashboard’s generated curl snippet by allowing the branded API key headers (Otari-Key and legacy aliases) to carry a raw token directly, while preserving backward compatibility for Bearer <token> on those headers and keeping Authorization: Bearer <token> behavior unchanged.
Changes:
- Updated
_extract_bearer_tokento accept raw tokens onOtari-Key/ legacy key headers (optionally stripping a leadingBearer). - Added/updated unit and integration tests to cover raw-header authentication and back-compat Bearer form.
- Updated docs examples to show
Otari-Key: <token>(no Bearer prefix required).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/gateway/api/deps.py |
Adjusts header parsing so branded key headers accept raw tokens (Bearer prefix optional). |
tests/unit/test_extract_bearer_token.py |
Adds unit coverage for raw-token extraction on canonical/legacy key headers. |
tests/integration/test_key_management.py |
Adds end-to-end test proving Otari-Key: <token> authenticates, and Bearer form remains supported. |
docs/quickstart.md |
Updates curl examples to use raw Otari-Key: <token>. |
docs/files.md |
Updates file upload and chat examples to use raw Otari-Key: <token>. |
docs/api-reference.md |
Updates auth header guidance to prefer raw Otari-Key: <token> while noting Bearer back-compat. |
02522cc to
922ebba
Compare
The branded key headers (Otari-Key and the legacy AnyLLM-Key / X-AnyLLM-Key aliases) now carry the token directly. A "Bearer " prefix is still accepted and stripped for back-compat, but is no longer required, so the dashboard's copy-paste snippet (Otari-Key: gw-...) authenticates. This matches the raw x-api-key convention already supported for Anthropic-native clients. The standard Authorization header still requires the Bearer scheme. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The gateway now accepts a raw token on the branded Otari-Key header (a Bearer prefix is still accepted for back-compat), so drop the surprising Bearer prefix from the docs examples to match the header's naming and the snippet the dashboard hands out. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A trailing space inside an inline-code span renders inconsistently across Markdown renderers; the prefix reads fine without it.
f8c296d to
96f0825
Compare
Description
The dashboard's copy-paste curl snippet sends
-H "Otari-Key: gw-..."(noBearerprefix), but the gateway requiredBeareron that header and rejected it with401 {"detail":"Invalid header format. Expected 'Bearer <token>'"}. Requiring theBearerscheme inside a header literally namedOtari-Keyis also surprising.This makes the branded key headers (the canonical
Otari-Key, and the legacyAnyLLM-Key/X-AnyLLM-Keyaliases) carry the token directly: aBearerprefix is accepted and stripped for back-compat, but is no longer required. It matches the rawx-api-keypath already supported for Anthropic-native clients (added in #315). The standardAuthorizationheader still requires theBearerscheme, and header precedence is unchanged.Net effect:
Otari-Key: gw-...now authenticates (what the dashboard hands out), andOtari-Key: Bearer gw-...keeps working.PR Type
Relevant issues
Checklist
tests/unit,tests/integration).make lint,make typecheck; the extract-token unit tests and a new end-to-end raw-header integration test; integration runs isolated on SQLite in the sandbox, so Postgres CI is the real signal).AI Usage
AI Model/Tool used: Claude Code (Opus 4.8, 1M context)
Any additional AI details you'd like to share: Diagnosed from @njbrake hitting the 401 with the dashboard's own snippet against a live gateway; he chose the fix direction (make the branded header accept a raw token rather than change the snippet to require Bearer). Reasoning and decision are his; the code and prose are the agent's.
🤖 Generated with Claude Code
Summary
Bearer-prefixed values.Authorizationvalidation and header precedence unchanged.This aligns authentication with the dashboard’s generated curl commands while preserving backward compatibility.