Skip to content

Dataroom session invalidation#2108

Open
mfts wants to merge 2 commits intomainfrom
cursor/dataroom-session-invalidation-9c3a
Open

Dataroom session invalidation#2108
mfts wants to merge 2 commits intomainfrom
cursor/dataroom-session-invalidation-9c3a

Conversation

@mfts
Copy link
Owner

@mfts mfts commented Mar 11, 2026

Replaced strict IP-based session validation with an enriched browser fingerprint and removed IP validation from link sessions to prevent frequent logouts for users with dynamic IPs.

Previously, dataroom sessions were invalidated if the user's IP address changed, leading to frequent re-verification for users on VPNs or mobile networks. This change uses a more stable browser fingerprint (User-Agent, Accept-Language, Sec-CH-UA headers) to bind sessions to a device, improving user experience without compromising security. IP addresses are still stored for analytics.

Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Added fingerprint-based session validation using browser characteristics for enhanced security in dataroom access.
  • Bug Fixes

    • Replaced IP-based session verification with browser fingerprinting to improve session stability when users change networks, especially important for mobile users.
  • Improvements

    • Sessions now remain valid across IP changes while maintaining backward compatibility with legacy sessions.

cursoragent and others added 2 commits March 10, 2026 13:19
…om sessions

Sessions were being invalidated whenever a visitor's IP address changed,
which happens frequently with VPNs, mobile networks, and carrier-grade NAT.
This caused visitors to be logged out after 1-2 minutes and forced
re-verification via OTP.

Changes:
- dataroom-auth.ts: Add browser fingerprint (SHA-256 of User-Agent +
  Accept-Language) as the primary session binding factor. IP address is
  still stored for analytics/watermarking but no longer used for session
  validation. Legacy sessions without a fingerprint fall back to IP check
  for a smooth rollout.
- link-session.ts: Remove IP address validation since User-Agent is
  already validated and provides the same device-binding guarantee without
  breaking on IP changes.
- All createDataroomSession callers updated to pass the fingerprint.

Security model:
- Session tokens remain cryptographically strong (32/48 random bytes)
- Cookies are httpOnly + sameSite preventing XSS/CSRF extraction
- Browser fingerprint (UA + Accept-Language) prevents session sharing
  across different devices/browsers
- IP is retained in session data for audit/watermarking purposes

Co-authored-by: Marc Seitz <mfts@users.noreply.github.com>
Strengthens the browser fingerprint by including Sec-CH-UA, Sec-CH-UA-Platform,
and Sec-CH-UA-Mobile headers in the hash. These client hints:
- Include exact browser brand + version (harder to guess than User-Agent alone)
- Are automatically sent by Chromium-based browsers
- Require explicit effort to spoof (not captured by cookie-copy tools)

Also refactors fingerprint collection into a shared collectFingerprintHeaders()
helper to avoid duplicating header extraction logic across callers.

Co-authored-by: Marc Seitz <mfts@users.noreply.github.com>
@cursor
Copy link

cursor bot commented Mar 11, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@vercel
Copy link

vercel bot commented Mar 11, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
papermark Ready Ready Preview, Comment Mar 11, 2026 0:10am

Request Review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 11, 2026

Walkthrough

Introduces fingerprint-based session handling for dataroom sessions by adding functions to generate session fingerprints from request headers (User-Agent, Accept-Language, Sec-CH-UA), updating dataroom session creation to accept and store fingerprints, and modifying multiple API routes to compute and pass fingerprints during session creation. Also removes IP address verification from link session validation.

Changes

Cohort / File(s) Summary
Dataroom Session Core Module
lib/auth/dataroom-auth.ts
Introduces generateSessionFingerprint() and collectFingerprintHeaders() functions for deriving SHA-256 fingerprints from request headers. Extends DataroomSessionSchema with optional fingerprint field. Updates createDataroomSession() signature to accept fingerprint parameter and stores it in session data. Adds fingerprint-based session validation with fallback to IP-based checks for legacy sessions.
Dataroom Session API Routes
app/(ee)/api/workflow-entry/domains/[...domainSlug]/route.ts, app/(ee)/api/workflow-entry/link/[entryLinkId]/access/route.ts, app/api/views-dataroom/route.ts, pages/api/links/download/verify.ts
Updated to import collectFingerprintHeaders and generateSessionFingerprint. Compute fingerprint from request headers and pass it as additional argument to createDataroomSession() calls during dataroom session creation.
Link Session Validation
lib/auth/link-session.ts
Removes IP address verification step from verifyLinkSession(). Retains User-Agent verification; session validation now relies on expiration and user-agent consistency only.

Possibly related PRs

  • Dataroom document access authentication #2032: Modifies the same dataroom session call sites in app/api/views-dataroom/route.ts, changing the dataroomId source to link.dataroomId while this PR adds fingerprint generation and passing.
🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.46% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Dataroom session invalidation' is vague and doesn't accurately reflect the primary change, which is replacing IP-based validation with fingerprint-based validation. Consider a more descriptive title such as 'Replace IP-based session validation with browser fingerprint' to better convey the actual technical change.
✅ Passed checks (1 passed)
Check name Status Explanation
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.


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.

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 (1)
lib/auth/link-session.ts (1)

106-111: ⚠️ Potential issue | 🟠 Major

Don’t rely on user-agent alone for link-session validation.

This removes the IP check without replacing it with the new fingerprint that dataroom sessions now use. A copied pm_ls_* cookie from another machine on the same browser/version will still pass this check, so protected link sessions get materially easier to replay. Please persist and compare a fingerprint here as well.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/auth/link-session.ts` around lines 106 - 111, The current check only
compares currentUserAgent vs sessionData.userAgent, which allows cookie replay
across machines with the same UA; modify this link-session validation to also
compare a stored fingerprint: compute a fingerprint from the incoming request
(e.g., client IP from X-Forwarded-For or connection, relevant headers and
user-agent) and compare it to sessionData.fingerprint, and if they differ call
deleteLinkSession(sessionToken, sessionData.viewerId) and return null; ensure
when creating the session you persist that same fingerprint into
sessionData.fingerprint (update the session creation code path that writes
link-session records) so the stored fingerprint and this comparison use the
identical fingerprinting function/logic.
🧹 Nitpick comments (1)
lib/auth/dataroom-auth.ts (1)

71-83: Keep request-to-fingerprint derivation behind one shared helper.

getFingerprintFromPagesRequest and getFingerprintFromNextRequest already define the auth-relevant header projection, but pages/api/links/download/verify.ts Lines 190-196 still recreate the pages-router adapter inline. I’d reuse a single request-level helper for session creation too so future header tweaks can’t make creation and verification drift apart.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/auth/dataroom-auth.ts` around lines 71 - 83, The two existing helpers
getFingerprintFromNextRequest and getFingerprintFromPagesRequest both project
the same auth headers and call collectFingerprintHeaders +
generateSessionFingerprint; extract that logic into a single shared helper
(e.g., getFingerprintFromRequest or normalizeRequestFingerprint) that accepts a
headers-like accessor (object with get(name): string | null) or a
NextRequest/NextApiRequest and returns the fingerprint via
collectFingerprintHeaders + generateSessionFingerprint, then update
getFingerprintFromNextRequest and getFingerprintFromPagesRequest to delegate to
that new helper and replace the inline pages-router adapter in
pages/api/links/download/verify.ts with a call to the new helper so header
projection is centralized and cannot drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@lib/auth/link-session.ts`:
- Around line 106-111: The current check only compares currentUserAgent vs
sessionData.userAgent, which allows cookie replay across machines with the same
UA; modify this link-session validation to also compare a stored fingerprint:
compute a fingerprint from the incoming request (e.g., client IP from
X-Forwarded-For or connection, relevant headers and user-agent) and compare it
to sessionData.fingerprint, and if they differ call
deleteLinkSession(sessionToken, sessionData.viewerId) and return null; ensure
when creating the session you persist that same fingerprint into
sessionData.fingerprint (update the session creation code path that writes
link-session records) so the stored fingerprint and this comparison use the
identical fingerprinting function/logic.

---

Nitpick comments:
In `@lib/auth/dataroom-auth.ts`:
- Around line 71-83: The two existing helpers getFingerprintFromNextRequest and
getFingerprintFromPagesRequest both project the same auth headers and call
collectFingerprintHeaders + generateSessionFingerprint; extract that logic into
a single shared helper (e.g., getFingerprintFromRequest or
normalizeRequestFingerprint) that accepts a headers-like accessor (object with
get(name): string | null) or a NextRequest/NextApiRequest and returns the
fingerprint via collectFingerprintHeaders + generateSessionFingerprint, then
update getFingerprintFromNextRequest and getFingerprintFromPagesRequest to
delegate to that new helper and replace the inline pages-router adapter in
pages/api/links/download/verify.ts with a call to the new helper so header
projection is centralized and cannot drift.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c5666467-e9f0-4300-84be-9747ed640b5c

📥 Commits

Reviewing files that changed from the base of the PR and between 3cf4458 and d76396f.

📒 Files selected for processing (6)
  • app/(ee)/api/workflow-entry/domains/[...domainSlug]/route.ts
  • app/(ee)/api/workflow-entry/link/[entryLinkId]/access/route.ts
  • app/api/views-dataroom/route.ts
  • lib/auth/dataroom-auth.ts
  • lib/auth/link-session.ts
  • pages/api/links/download/verify.ts

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.

2 participants