Skip to content

fix host cookie deleting#1011

Merged
BilalG1 merged 5 commits intodevfrom
fix-cookie-deleting
Nov 12, 2025
Merged

fix host cookie deleting#1011
BilalG1 merged 5 commits intodevfrom
fix-cookie-deleting

Conversation

@BilalG1
Copy link
Contributor

@BilalG1 BilalG1 commented Nov 11, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Cookie deletion now respects the browser's secure context when domains are specified, ensuring consistent removal across secure and non-secure connections.
    • Session refresh logic now removes redundant default cookies after setting a custom refresh cookie, preventing duplicate cookies and conflicts.
  • Tests

    • End-to-end tests updated to expect the default refresh cookie to be absent and to read payloads from the custom cookie.

@vercel
Copy link

vercel bot commented Nov 11, 2025

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

Project Deployment Preview Comments Updated (UTC)
stack-backend Ready Ready Preview Comment Nov 11, 2025 10:00pm
stack-dashboard Ready Ready Preview Comment Nov 11, 2025 10:00pm
stack-demo Ready Ready Preview Comment Nov 11, 2025 10:00pm
stack-docs Ready Ready Preview Comment Nov 11, 2025 10:00pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 11, 2025

Walkthrough

Cookie deletion and client refresh-cookie handling were adjusted to respect the client-side secure context. Deletion now includes a secure flag when appropriate, and the client implementation removes the default secure refresh cookie after writing a domain-specific custom cookie.

Changes

Cohort / File(s) Summary
Cookie deletion logic
packages/template/src/lib/cookie.ts
deleteCookieClientInternal updated so deletions include the secure flag derived from the client context when a domain is specified; general removal path now attaches a secure flag to align with setting behavior.
Client refresh cookie update & cleanup
packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts
After setting the domain-specific refresh cookie in the browser, code now awaits isSecureCookieContext() and deletes the corresponding default secure refresh cookie to avoid redundant cookies.
E2E test expectations adjusted
apps/e2e/tests/js/cookies.test.ts
Tests changed to assert the default refresh cookie is absent and the custom cookie is present; payload is read from the custom cookie and cross-cookie equivalence checks were removed.

Sequence Diagram(s)

sequenceDiagram
    participant Browser
    participant ClientImpl
    participant CookieLib

    rect rgba(200,240,200,0.3)
    Note over ClientImpl,Browser: Client sets domain-specific refresh cookie
    ClientImpl ->> Browser: set custom refresh cookie (domain)
    end

    rect rgba(200,220,240,0.25)
    Note over ClientImpl: Determine secure context and cleanup default cookie
    ClientImpl ->> ClientImpl: isSecureCookieContext()
    alt secure context
        ClientImpl ->> Browser: delete default secure refresh cookie
    else insecure context
        ClientImpl -->> Browser: (no default secure delete)
    end
    end

    rect rgba(240,230,200,0.25)
    Note over CookieLib: Server-side (client) cookie deletion respects secure flag
    Browser ->> CookieLib: deleteCookieClientInternal(options with domain)
    CookieLib ->> Browser: delete cookie with secure flag derived from context
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Inspect deleteCookieClientInternal for correct secure-flag sourcing and combinations with domain/path attributes.
  • Verify timing of isSecureCookieContext() (async) relative to cookie set/delete operations.
  • Check tests in cookies.test.ts properly reflect expected browser cookie state across browsers/contexts.

Possibly related PRs

  • Cookie subdomain sharing #971: touches the same cookie handling code and secure-flag/domain-aware set/delete behavior in cookie.ts and client-app implementation.

Suggested reviewers

  • N2D4

Poem

🐇 I nibble cookies with a careful paw,

Secure or not, I check the law.
Domain crumbs cleared with one swift hop,
Old defaults gone — no extra prop.
A tidy burrow, cookies on top.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description contains only a template comment reminder with no actual description of changes, objectives, or context provided by the author. Add a meaningful description explaining what the PR fixes, why the changes are necessary, and how they address the issue with cookie deletion behavior.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'fix host cookie deleting' is vague and lacks specificity about what issue is being fixed or what the actual changes accomplish. Revise the title to be more descriptive, such as 'Fix cookie deletion with secure flag in client context' or similar to clearly convey the main change.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-cookie-deleting

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.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Nov 11, 2025

Greptile Overview

Greptile Summary

Fixed cookie deletion to properly handle __Host- prefixed cookies by passing the secure flag to Cookies.remove(). When deleting cookies, the same attributes (including secure) must match those used when setting the cookie. Additionally, added cleanup logic to delete the default refresh token cookie when switching to a custom domain cookie, preventing stale cookies from remaining after domain migration.

Confidence Score: 5/5

  • This PR is safe to merge - it fixes a legitimate cookie deletion bug
  • The changes correctly implement the fix for cookie deletion by passing the secure flag, which is required for properly deleting cookies (especially __Host- prefixed ones). The logic is sound and follows browser cookie deletion requirements.
  • No files require special attention

Important Files Changed

File Analysis

Filename Score Overview
packages/template/src/lib/cookie.ts 5/5 Fixed cookie deletion to pass the secure flag when removing cookies, ensuring cookies with __Host- prefix are properly deleted
packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts 5/5 Added cleanup logic to delete the default refresh token cookie when switching to custom domain cookie

Sequence Diagram

sequenceDiagram
    participant App as Client App
    participant Cookie as Cookie Helper
    participant Browser as Browser (js-cookie)
    
    Note over App,Browser: Switching to Custom Domain Cookie
    
    App->>App: _queueCustomRefreshCookieUpdate()
    App->>App: Get trusted parent domain
    App->>Cookie: setCookie(domain, refreshToken)
    Cookie->>Browser: Set custom domain cookie
    
    Note over App,Browser: Delete old default cookie
    
    App->>Cookie: isSecureCookieContext()
    Cookie->>App: Returns secure flag (HTTPS check)
    App->>App: _getRefreshTokenDefaultCookieNameForSecure(isSecure)
    Note right of App: Returns "__Host-stack-refresh-{id}--default"<br/>or "stack-refresh-{id}--default"
    App->>Cookie: setOrDeleteCookie(defaultName, null)
    Cookie->>Cookie: deleteCookieClientInternal(name)
    Note right of Cookie: Now passes secure flag
    Cookie->>Browser: Cookies.remove(name, {secure: true/false})
    Note right of Browser: Secure flag must match<br/>the flag used when setting
    Browser->>Browser: Cookie successfully deleted
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

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.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/template/src/lib/cookie.ts (1)

205-210: LGTM! Secure flag now properly included in cookie deletion.

The addition of secure: determineSecureFromClientContext() ensures cookies are deleted with the same security attributes they were set with, which is required by browser cookie APIs. This aligns with how setCookieClientInternal (line 197) sets cookies based on the secure context.

Optional: Cache the secure context value.

Since determineSecureFromClientContext() is called twice (lines 207 and 209), consider caching the result:

 function deleteCookieClientInternal(name: string, options: DeleteCookieOptions = {}) {
+  const secure = determineSecureFromClientContext();
   if (options.domain !== undefined) {
-    Cookies.remove(name, { domain: options.domain, secure: determineSecureFromClientContext() });
+    Cookies.remove(name, { domain: options.domain, secure });
   }
-  Cookies.remove(name, { secure: determineSecureFromClientContext() });
+  Cookies.remove(name, { secure });
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6763f1a and 8e1092c.

📒 Files selected for processing (2)
  • packages/template/src/lib/cookie.ts (1 hunks)
  • packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts (1)
packages/template/src/lib/cookie.ts (2)
  • isSecure (174-182)
  • setOrDeleteCookie (221-224)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: build (22.x)
  • GitHub Check: restart-dev-and-test
  • GitHub Check: check_prisma_migrations (22.x)
  • GitHub Check: restart-dev-and-test-with-custom-base-port
  • GitHub Check: build (22.x)
  • GitHub Check: setup-tests
  • GitHub Check: docker
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: build (22.x)
  • GitHub Check: all-good
  • GitHub Check: Vercel Agent Review
🔇 Additional comments (1)
packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts (1)

623-624: LGTM! Proper cleanup of default cookie after custom domain cookie update.

After successfully setting a custom domain-based refresh cookie, this code correctly cleans up the default refresh cookie to prevent conflicts. The secure context is properly determined via isSecureCookieContext(), and the appropriate default cookie name (with or without __Host- prefix) is used for deletion.

This change ensures that only one refresh cookie mechanism is active at a time, which prevents confusion and potential race conditions.

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.

Actionable comments posted: 0

Caution

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

⚠️ Outside diff range comments (1)
apps/e2e/tests/js/cookies.test.ts (1)

163-170: Add explicit wait for default cookie deletion to prevent race condition.

The test waits for both cookies to be present (lines 163–167), then immediately asserts the default cookie is absent (line 169). There's no guarantee the deletion triggered by the custom cookie write has completed before line 169 executes, which could cause flaky test failures.

Apply this diff to add an explicit wait for the default cookie to be deleted:

  const customReady = await waitUntil(() => cookieStore.has(customCookieName), 10_000);
  expect(customReady).toBe(true);

+ const defaultDeleted = await waitUntil(() => !cookieStore.has(defaultCookieName), 2_000);
+ expect(defaultDeleted).toBe(true);
+
  expect(cookieStore.has(defaultCookieName)).toBe(false);
  expect(cookieStore.has(customCookieName)).toBe(true);
🧹 Nitpick comments (2)
apps/e2e/tests/js/cookies.test.ts (2)

172-172: Rename variable to reflect it stores the custom cookie value.

The variable defaultValue stores the value from customCookieName, which is misleading.

Apply this diff:

- const defaultValue = cookieStore.get(customCookieName)!;
+ const customValue = cookieStore.get(customCookieName)!;
- const parsedValue = JSON.parse(decodeURIComponent(defaultValue));
+ const parsedValue = JSON.parse(decodeURIComponent(customValue));

185-185: Consider checking expires attribute on the specific custom cookie.

The assertion checks if any refresh cookie has an expires attribute but doesn't verify it's specifically the custom cookie. Since you already extract customAttrs on line 183, consider adding a specific check there.

Example:

  const customAttrs = findCookieAttributes(cookieWrites, customCookieName);
  expect(customAttrs?.get("domain")).toBe("example.com");
+ expect(customAttrs?.has("expires")).toBe(true);
- expect(cookieWrites.some((entry) => entry.toLowerCase().startsWith("stack-refresh-") && entry.toLowerCase().includes("expires="))).toBe(true);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8e1092c and 4e0b96d.

📒 Files selected for processing (1)
  • apps/e2e/tests/js/cookies.test.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Vercel Agent Review
  • GitHub Check: setup-tests
  • GitHub Check: check_prisma_migrations (22.x)
  • GitHub Check: build (22.x)
  • GitHub Check: lint_and_build (latest)
  • GitHub Check: restart-dev-and-test
  • GitHub Check: restart-dev-and-test-with-custom-base-port
  • GitHub Check: docker
  • GitHub Check: all-good
  • GitHub Check: build (22.x)
  • GitHub Check: build (22.x)

@BilalG1 BilalG1 requested a review from N2D4 November 11, 2025 19:04
@BilalG1 BilalG1 merged commit e320385 into dev Nov 12, 2025
21 checks passed
@BilalG1 BilalG1 deleted the fix-cookie-deleting branch November 12, 2025 22:37
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