{{ message }}
fix(server): treat expired HTTP Bearer token as no-auth instead of 401#7196
Open
22f wants to merge 1 commit intosurrealdb:mainfrom
Open
fix(server): treat expired HTTP Bearer token as no-auth instead of 401#719622f wants to merge 1 commit intosurrealdb:mainfrom
22f wants to merge 1 commit intosurrealdb:mainfrom
Conversation
When an HTTP client's Bearer JWT expires, the auth middleware rejected ALL requests with 401 — including signin and invalidate, which are the operations needed to recover. This created a deadlock where the client could not obtain a fresh token without creating a brand new connection. The fix treats an expired Bearer token as equivalent to no token, falling back to an unauthenticated session. This lets recovery endpoints (signin, invalidate) proceed normally while other endpoints still enforce permissions via their handlers. WebSocket connections were unaffected as they handle auth per-RPC-method. Uses the existing `is_expired_token_error()` helper from core::iam. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Thank you for submitting this pull request. We really appreciate you spending the time to work on SurrealDB. 🚀 🎉
What is the motivation?
When an HTTP client's JWT expires, it enters a deadlock:
signin()andinvalidate()— the operations needed to recover — are also rejected with 401 because the auth middleware (SurrealAuth) validates the Bearer token on all incoming requests before the endpoint handler runs.The SDK automatically attaches the
Authorization: Bearer <token>header on every request, including recovery calls. The client has no way to obtain a fresh JWT without creating a brand-new connection (bypassing the stale Bearer header).The deadlock flow:
signin()with valid credentialsAuthorization: Bearer <expired>signinhandler never runsWebSocket is unaffected — WS auth is per-RPC-method, not middleware-based.
Historical context:
What does this change do?
In
check_auth()(surrealdb/server/src/ntw/auth.rs), when Bearer token validation returnsExpiredToken, the middleware now treats it as equivalent to no token — the request proceeds with an unauthenticated (anonymous) session. The endpoint handler then decides what to do:/signin: receives anonymous session + credentials from body → verifies → issues new JWT ✓/sqland other protected endpoints: anonymous session → permissions error (not 401) ✓/invalidate: clears the (already empty) session → succeeds ✓This is not a security downgrade:
Authorizationheader at allUses the existing
is_expired_token_error()helper fromsurrealdb_core::iam.What is your testing strategy?
New integration test
expired_jwt_does_not_block_signinintests/http_integration.rswith three scenarios:POST /signinwith expired JWT in Authorization header → must return 200 (not 401)POST /sqlwith expired JWT → must not return 401 at middleware level (handler decides permissions)All existing tests pass. Fork CI results: 22f/surrealdb#2
access/record/variables.surql(same on upstream main)Is this related to any issues?
Does this change need documentation?
Does this change make any alterations to environment variables or CLI commands?
Have you read the Contributing Guidelines?