Skip to content

Harden authentication sessions and recovery - #210

Merged
BASIC-BIT merged 1 commit into
mainfrom
codex/auth-session-hardening
Jul 27, 2026
Merged

Harden authentication sessions and recovery#210
BASIC-BIT merged 1 commit into
mainfrom
codex/auth-session-hardening

Conversation

@BASIC-BIT

@BASIC-BIT BASIC-BIT commented Jul 27, 2026

Copy link
Copy Markdown
Owner

[AGENT]

Summary

This completes the security and operational follow-up to the remembered-session lifetime fix on main.

  • enforce active VRDex sessions across protected Convex functions and browser-authenticated server routes
  • add account session inventory, single-session revocation, sign out other sessions, and sign out everywhere
  • require a completed, challenge-bound password proof for sensitive browser actions after the 15-minute recent-auth window
  • atomically rotate successful step-up onto one replacement session, revoke the original session, and converge concurrent tabs safely
  • bound session inventory, global revocation, and refresh-token cleanup so long histories cannot exceed Convex function limits
  • preserve bounded non-secret form drafts without storing or replaying bearer credentials
  • add sanitized auth lifecycle telemetry, PostHog Terraform views, and isolated staging/production smoke workflows
  • enforce first-attempt browser reliability while retaining retry traces for diagnosis

Session contract

The ordinary remembered-session contract remains:

  • 30-day inactivity window with a persistent refresh cookie
  • 90-day absolute maximum session lifetime
  • 1-hour JWTs with silent refresh and rotation
  • explicit sign-out revokes the current session; global revocation invalidates every session
  • OAuth provider access-token expiry does not determine VRDex login lifetime
  • preview, staging, and production credentials remain isolated

Recent authentication is a non-sliding 15-minute window measured from successful completion of a server-side challenge and bound to the replacement VRDex session. Password proof claiming stores only a SHA-256 proof hash, consumes the proof once, atomically creates at most one replacement session, and removes the original session and refresh-token tree. Concurrent challenges converge on that replacement. Because this is a full reauthentication, the replacement begins a new 90-day absolute lifetime.

Discord and Google remain ordinary sign-in methods, but ordinary OAuth sign-in cannot satisfy step-up because the installed auth stack does not bind provider freshness to the resulting VRDex session. OAuth-only step-up remains tracked in #202.

Security and recovery

  • bearer and refresh credentials remain in HttpOnly cookies and are never written to localStorage
  • active-session guards validate ownership, revocation, absolute expiry, and account existence
  • sensitive actions fail closed with RECENT_AUTH_REQUIRED; their original writes are never stored or replayed automatically
  • challenge completion is account-bound, same-origin, expiration-checked, and idempotent for the exact replacement session
  • interrupted or overlapping challenges preserve unrelated, unbound, and already-completed sessions
  • completion and failure transport errors clear only challenge state, not unconfirmed browser credentials
  • explicit sign-out failures re-enable later revocation convergence
  • ordinary anonymous visits are excluded from restoration-failure telemetry unless auth cookies are present
  • single-session revocation deletes the session immediately, then removes refresh-token history in durable 128-row batches
  • global revocation snapshots the authorized account scope, deletes at most 16 session records per mutation, and durably continues cleanup
  • production authenticated smoke remains manual, one-shot, and fail-closed

Verification

  • backend tests: 331 passed
  • web tests: 237 passed
  • complete desktop Chromium flow suite: 26 passed
  • account-session browser flow: 5 passed
  • three-browser auth matrix: 10/10 consecutive clean runs; slowest run 35.3 seconds
  • web/backend typechecks, web lint, Markdown lint, production web build, and docs build: passed
  • Terraform format/validation and local Convex generated-API/health verification: passed
  • all twelve review threads dispositioned and resolved
  • independent auth-race and bounded-revocation re-reviews: no remaining code-level blocker

Owner follow-up

After deployment:

  1. Configure recurring staging auth helpers if not already present:
    VRDEX_HOSTED_E2E_AUTH_HELPERS=true and
    VRDEX_HOSTED_E2E_BROWSER_TOKEN.
  2. Import, plan, and apply the documented PostHog Terraform changes. Review
    the baseline on August 10, 2026 or after 14 complete deployed days,
    whichever is later.
  3. For a production one-shot check, freshly export disposable-account storage
    state and invoke the workflow with production_auth=true. Do not retain or
    reuse that state.
  4. Add a challenge-bound step-up method for OAuth-only accounts under Confirm consequential account and developer actions #202.

Addresses #202
Closes #203
Closes #204
Closes #205
Closes #206

Copilot AI review requested due to automatic review settings July 27, 2026 10:27
@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
vr-dex-web Ready Ready Preview, Comment Jul 27, 2026 10:27am

Request Review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@BASIC-BIT
BASIC-BIT force-pushed the codex/auth-session-hardening branch from fcb1070 to 57ba421 Compare July 27, 2026 10:31
Copilot AI review requested due to automatic review settings July 27, 2026 10:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fcb107079c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/app/developers/tokens/developer-tokens-panel.tsx Outdated
Comment thread apps/web/src/app/sign-in/sign-in-form.tsx Outdated
Comment thread apps/web/src/app/sign-in/sign-in-form.tsx Outdated
Comment thread convex/accountSessions.ts Outdated
Comment thread apps/web/src/app/auth/reauth/complete/route.ts
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown

PR verification report

All configured preview and verification checks passed.

Check Result Evidence
Mutation data flow PASSED Open artifact
Hosted data flow PASSED Open artifact
Public route screenshots PASSED Open artifact
Public route image diff PASSED Open artifact
Storybook screenshots PASSED Open artifact
Storybook image diff PASSED Open artifact

Changed visual baselines: none.

Updated from Baseline Checks run 30301794113, attempt 1 for 1fd3fe1. This comment is updated in place.

Copilot AI review requested due to automatic review settings July 27, 2026 11:46
@BASIC-BIT
BASIC-BIT force-pushed the codex/auth-session-hardening branch from 57ba421 to 39499ee Compare July 27, 2026 11:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39499eebe5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/app/ConvexClientProvider.tsx
Comment thread apps/web/src/app/sign-in/sign-in-form.tsx Outdated
Comment thread infra/terraform/posthog/main.tf
Copilot AI review requested due to automatic review settings July 27, 2026 12:02
@BASIC-BIT
BASIC-BIT force-pushed the codex/auth-session-hardening branch from 39499ee to 4ba25a4 Compare July 27, 2026 12:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4ba25a4379

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread convex/_accountSessionLifecycle.ts Outdated
Copilot AI review requested due to automatic review settings July 27, 2026 16:18
@BASIC-BIT
BASIC-BIT force-pushed the codex/auth-session-hardening branch from 4ba25a4 to 0e7135c Compare July 27, 2026 16:18

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@BASIC-BIT
BASIC-BIT force-pushed the codex/auth-session-hardening branch from 0e7135c to 9d4598f Compare July 27, 2026 16:21
Copilot AI review requested due to automatic review settings July 27, 2026 16:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d4598f4c9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/app/auth/reauth/fail/route.ts Outdated
Copilot AI review requested due to automatic review settings July 27, 2026 19:31
@BASIC-BIT
BASIC-BIT force-pushed the codex/auth-session-hardening branch from 9d4598f to 3505de7 Compare July 27, 2026 19:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3505de7c18

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread convex/recentAuthChallenges.ts
Comment thread convex/recentAuthChallenges.ts
Comment thread convex/accountSessions.ts Outdated
@BASIC-BIT
BASIC-BIT force-pushed the codex/auth-session-hardening branch from 3505de7 to 1fd3fe1 Compare July 27, 2026 20:15
Copilot AI review requested due to automatic review settings July 27, 2026 20:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@BASIC-BIT

Copy link
Copy Markdown
Owner Author

[AGENT] @codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@BASIC-BIT
BASIC-BIT merged commit db14085 into main Jul 27, 2026
31 checks passed
@BASIC-BIT
BASIC-BIT deleted the codex/auth-session-hardening branch July 27, 2026 23:43
BASIC-BIT added a commit that referenced this pull request Jul 28, 2026
`#210` replaced the account-helper auth model with `_browserSessionAuthority`
and added a boundary test enforcing it. The claim platform predates that, so
this integrates rather than reverting either side:

- New `convex/_claimSession.ts` wraps the session authority with the structured
  claim codes this branch exists to provide. A `ConvexError` from the guard is
  rethrown untouched, so the `AUTH_SESSION_INVALID` signal the web app
  converges sessions on still reaches it; only the plain-`Error` cases become
  `SIGN_IN_REQUIRED` / `EMAIL_NOT_VERIFIED`, which Convex would otherwise
  redact to one generic string in production.
- `profileClaims`, `profileConnections`, `discordVerification`,
  `vrclinkingCredentials`, and `_accountFeatures` now authorize through it
  instead of the legacy account helpers or a direct identity read.
- `_browserSessionAuthority` itself is left exactly as main wrote it; an
  earlier attempt to change its error contract broke main's own tests, which
  assert the plain messages.
- Registered the new Discord OAuth action module and its two Next routes in the
  boundary inventories, with the markers those files actually use.
- Test identities now insert a real `authSessions` row: the guard resolves the
  session named by the subject, so a fabricated `|web-session` suffix no longer
  authenticates.
- Kept both new crons.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
BASIC-BIT added a commit that referenced this pull request Jul 28, 2026
`#210` replaced the account-helper auth model with `_browserSessionAuthority`
and added a boundary test enforcing it. The claim platform predates that, so
this integrates rather than reverting either side:

- New `convex/_claimSession.ts` wraps the session authority with the structured
  claim codes this branch exists to provide. A `ConvexError` from the guard is
  rethrown untouched, so the `AUTH_SESSION_INVALID` signal the web app
  converges sessions on still reaches it; only the plain-`Error` cases become
  `SIGN_IN_REQUIRED` / `EMAIL_NOT_VERIFIED`, which Convex would otherwise
  redact to one generic string in production.
- `profileClaims`, `profileConnections`, `discordVerification`,
  `vrclinkingCredentials`, and `_accountFeatures` now authorize through it
  instead of the legacy account helpers or a direct identity read.
- `_browserSessionAuthority` itself is left exactly as main wrote it; an
  earlier attempt to change its error contract broke main's own tests, which
  assert the plain messages.
- Registered the new Discord OAuth action module and its two Next routes in the
  boundary inventories, with the markers those files actually use.
- Test identities now insert a real `authSessions` row: the guard resolves the
  session named by the subject, so a fabricated `|web-session` suffix no longer
  authenticates.
- Kept both new crons.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants