Skip to content

feat: single authentication per connection - #7166

Merged
LesnyRumcajs merged 1 commit into
mainfrom
single-auth-conn
Jun 11, 2026
Merged

feat: single authentication per connection#7166
LesnyRumcajs merged 1 commit into
mainfrom
single-auth-conn

Conversation

@LesnyRumcajs

@LesnyRumcajs LesnyRumcajs commented Jun 11, 2026

Copy link
Copy Markdown
Member

Summary of changes

Changes introduced in this pull request:

  • check JWT once per connection

Reference issue to close (if applicable)

Closes #7164

Other information and links

Change checklist

  • I have performed a self-review of my own code,
  • I have made corresponding changes to the documentation. All new code adheres to the team's documentation standards,
  • I have added tests that prove my fix is effective or that my feature works (if possible),
  • I have made sure the CHANGELOG is up-to-date. All user-facing changes should be reflected in this document.

Outside contributions

  • I have read and agree to the CONTRIBUTING document.
  • I have read and agree to the AI Policy document. I understand that failure to comply with the guidelines will lead to rejection of the pull request.

Summary by CodeRabbit

  • Changed
    • JSON-RPC authentication is now performed once per connection rather than for each request, improving performance
    • Token expiry checking is no longer re-evaluated during an active connection

@LesnyRumcajs
LesnyRumcajs requested a review from a team as a code owner June 11, 2026 09:28
@LesnyRumcajs
LesnyRumcajs requested review from hanabi1224 and sudo-shashank and removed request for a team June 11, 2026 09:28
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

AuthLayer now caches JWT token verification and permission claims at connection setup instead of per-request. New helpers resolve_claims and is_method_allowed perform the verification once; the Auth service stores the cached result and enforces it for all subsequent calls, reducing overhead on long-lived connections.

Changes

JWT Authentication Caching

Layer / File(s) Summary
Claim resolution and authorization helpers
src/rpc/auth_layer.rs
resolve_claims verifies the JWT and returns claims or an error code; is_method_allowed checks whether a method is permitted by the cached claims; check_permissions is refactored as test-only to compose these helpers.
Per-connection claim caching in AuthLayer
src/rpc/auth_layer.rs
AuthLayer::layer resolves claims once from the connection authorization header and caches the result in the Auth service. Auth struct replaces headers and keystore fields with a cached claims result, eliminating per-request token verification.
Test coverage for claim caching
src/rpc/auth_layer.rs
Tests validate that claims are resolved once at connection setup and consistently applied to subsequent authorization checks, and that failed-token results are cached across calls.
Changelog
CHANGELOG.md
Documents that JSON-RPC authentication now occurs once per connection instead of per-request, and token expiry is no longer re-checked for the connection lifetime.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • ChainSafe/forest#6468: Modifies Auth::authorize to add warning logs on authorization failure alongside the main PR's refactoring of the auth caching mechanism.

Suggested labels

RPC

Suggested reviewers

  • hanabi1224
  • sudo-shashank
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: implementing single authentication per connection instead of per request, which is the primary objective of this pull request.
Linked Issues check ✅ Passed The code changes successfully implement JWT validation once per connection by resolving and caching authorization claims at service construction time, directly meeting the requirement specified in issue #7164.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing per-connection authentication: CHANGELOG documentation, AuthLayer refactoring to cache claims, and supporting tests align with issue #7164 objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch single-auth-conn
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch single-auth-conn

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/rpc/auth_layer.rs (2)

179-183: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Normalize the Bearer scheme before stripping it.

trim_start_matches("Bearer ") only accepts the title-case form, but the HTTP auth scheme is case-insensitive. A client that sends authorization: bearer <token> will be rejected here, and that InvalidRequest then gets cached for the whole connection.

Suggested fix
-            let token = token
-                .to_str()
-                .map_err(|_| ErrorCode::ParseError)?
-                .trim_start_matches("Bearer ");
+            let token = token.to_str().map_err(|_| ErrorCode::ParseError)?;
+            let token = match token.split_once(' ') {
+                Some((scheme, value)) if scheme.eq_ignore_ascii_case("Bearer") => value,
+                _ => token,
+            };
🤖 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/rpc/auth_layer.rs` around lines 179 - 183, The code currently strips the
"Bearer " prefix with trim_start_matches("Bearer ") which fails for case
variants; update the token parsing so you first convert the header string (from
token.to_str()) into an &str and then perform a case-insensitive check for the
"bearer " scheme (e.g., using eq_ignore_ascii_case on the prefix or compare a
lowercase slice) before slicing it off and returning the token; modify the chain
around token.to_str() → .trim_start_matches to do a case-insensitive prefix
check and only strip the first 7 bytes when the scheme matches, otherwise return
the appropriate ParseError/InvalidRequest path.

184-184: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not log bearer tokens.

This writes a replayable credential to logs. With the new per-connection flow, every authenticated WebSocket session will leak its JWT whenever debug logging is enabled.

Suggested fix
-            debug!("JWT from HTTP Header: {}", token);
+            debug!("JWT received from HTTP header");
🤖 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/rpc/auth_layer.rs` at line 184, Remove the debug log that prints the raw
JWT value ("JWT from HTTP Header: {}") and replace it with a non-sensitive
message — e.g. log that a JWT was received or log only non-secret metadata such
as its presence or length. Locate the debug! call that references the token
variable (the "JWT from HTTP Header" log) in the auth layer and update it to
avoid emitting the token itself (do not print token, claims, or any replayable
credential).
🤖 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.

Outside diff comments:
In `@src/rpc/auth_layer.rs`:
- Around line 179-183: The code currently strips the "Bearer " prefix with
trim_start_matches("Bearer ") which fails for case variants; update the token
parsing so you first convert the header string (from token.to_str()) into an
&str and then perform a case-insensitive check for the "bearer " scheme (e.g.,
using eq_ignore_ascii_case on the prefix or compare a lowercase slice) before
slicing it off and returning the token; modify the chain around token.to_str() →
.trim_start_matches to do a case-insensitive prefix check and only strip the
first 7 bytes when the scheme matches, otherwise return the appropriate
ParseError/InvalidRequest path.
- Line 184: Remove the debug log that prints the raw JWT value ("JWT from HTTP
Header: {}") and replace it with a non-sensitive message — e.g. log that a JWT
was received or log only non-secret metadata such as its presence or length.
Locate the debug! call that references the token variable (the "JWT from HTTP
Header" log) in the auth layer and update it to avoid emitting the token itself
(do not print token, claims, or any replayable credential).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 178dc99a-32c8-404e-9548-d9bb72b7f859

📥 Commits

Reviewing files that changed from the base of the PR and between 2c1f7e6 and 63c3eab.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • src/rpc/auth_layer.rs
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • filecoin-project/lotus (manual)

@LesnyRumcajs
LesnyRumcajs enabled auto-merge June 11, 2026 09:37
@LesnyRumcajs
LesnyRumcajs added this pull request to the merge queue Jun 11, 2026
Merged via the queue into main with commit be7fba3 Jun 11, 2026
42 checks passed
@LesnyRumcajs
LesnyRumcajs deleted the single-auth-conn branch June 11, 2026 10:04
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.

JWT auth once per connection

3 participants