Skip to content

fix(httpapi): match the Bearer auth scheme case-insensitively - #1754

Merged
Dumbris merged 1 commit into
smart-mcp-proxy:mainfrom
rudycelekli:fix/bearer-scheme-case-20261023-01
Oct 26, 2026
Merged

Dumbris merged 1 commit into
smart-mcp-proxy:mainfrom
rudycelekli:fix/bearer-scheme-case-20261023-01

Conversation

@rudycelekli

Copy link
Copy Markdown
Contributor

Bug

The REST auth middleware only recognises an Authorization header that starts with the exact bytes Bearer . The auth-scheme name is case-insensitive (RFC 7235 §2.1, RFC 6750 §2.1), so a client or proxy that sends bearer <key> or BEARER <key> is rejected with 401 Invalid or missing API key even though the key is valid. Because precedence is decided by header membership, the request never falls back to ?apikey= or the session cookie either.

Trigger

curl -H 'Authorization: bearer <api-key>' http://127.0.0.1:8080/api/v1/status   # 401
curl -H 'Authorization: Bearer <api-key>' http://127.0.0.1:8080/api/v1/status   # 200

Fix

Add a small bearerToken(header) helper in internal/httpapi that compares the scheme with strings.EqualFold, and use it at the three places that parse the header: authenticateBearer, ExtractToken, and sessionCredentialValue (SSE re-check of a bearer JWT). The last one has to match the first, otherwise a JWT accepted with a lowercase scheme would read back as empty during the /events scope check.

Test

TestBearerScheme_CaseInsensitive sends the admin key with Bearer, bearer and BEARER through ExtractToken and through the full ServeHTTP middleware, and checks that Basic still yields no token.

Commands run

  • CGO_ENABLED=0 go test -count=1 ./internal/httpapi — ok
  • CGO_ENABLED=0 go vet ./internal/httpapi — clean
  • With the fix reverted (git stash of server.go and sse_scope.go): go test -count=1 -run TestBearerScheme ./internal/httpapi — FAIL (the bearer and BEARER subtests: token mismatch and 401)
  • gofmt -l on the edited files — no output

Co-authored-by: Cursor <cursoragent@cursor.com>
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Dumbris Dumbris left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified: the PR test fails on main for the reason described and passes on this branch merged with main; race tests for the touched packages and CI lint (bare and server tags) are clean. Also built and tested together with the rest of this batch, independently reviewed, and cross-reviewed with a second model.

@Dumbris
Dumbris merged commit a2ac978 into smart-mcp-proxy:main Oct 26, 2026
48 checks passed
Dumbris pushed a commit that referenced this pull request Oct 26, 2026
…ser JWTs (#1755)

## Bug

`ServerEditionAuthMiddleware.authenticateFromBearer` only recognises an
`Authorization` header that starts with the exact bytes `Bearer `. The
auth-scheme name is case-insensitive (RFC 7235 §2.1, RFC 6750 §2.1), so
a valid user JWT sent as `bearer <jwt>` or `BEARER <jwt>` is ignored and
the request gets `401 Authentication required` on the server edition.

## Trigger

Build with `-tags server`, log in, mint a JWT with `POST
/api/v1/auth/token`, then:

```
curl -H 'Authorization: bearer <jwt>' http://host/api/v1/servers   # 401
curl -H 'Authorization: Bearer <jwt>' http://host/api/v1/servers   # 200
```

## Fix

Compare the scheme prefix with `strings.EqualFold` instead of
`strings.HasPrefix`. Nothing else changes: empty tokens and agent tokens
are still skipped, and the JWT is validated exactly as before.

This is the server-edition counterpart of #1754 (which fixes the core
`internal/httpapi` parser). The two are independent and can land in
either order.

## Test

`TestMiddleware_ValidJWT_SchemeCaseInsensitive` sends a valid JWT with
the `bearer` and `BEARER` schemes through `Middleware()` and checks for
200 and the right `user_id`.

## Commands run

- `CGO_ENABLED=0 go test -count=1 -tags server
./internal/serveredition/auth`: ok on 3 of 4 runs. The one failing run
was `TestHandleCallback_Unavailable_ProviderErrorRenders503`, an
OAuth-callback timing test that does not go through this middleware. It
passes alone (`-count=3`) and passes on the other three full runs.
- `CGO_ENABLED=0 go test -count=1 -tags server -skip
TestHandleCallback_Unavailable_ProviderErrorRenders503
./internal/serveredition/auth`: ok
- `CGO_ENABLED=0 go vet -tags server ./internal/serveredition/auth`:
clean
- With the fix reverted (`git stash` of `middleware.go`), `-run
SchemeCaseInsensitive` fails with `bearer: expected 200 ..., got 401`
and `BEARER: expected 200 ..., got 401`.
- `gofmt -l` on the edited files: no output

Co-authored-by: Cursor <cursoragent@cursor.com>
@Dumbris

Dumbris commented Oct 26, 2026

Copy link
Copy Markdown
Member

Merged. Thank you, @rudycelekli! The REST API accepts the Bearer scheme in any case, as RFC 7235/6750 require.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants