Skip to content

Fix magic login behind CDNs that strip Set-Cookie headers#82

Open
bourafai wants to merge 1 commit intoaaemnnosttv:masterfrom
bourafai:fix/cdn-set-cookie-stripping
Open

Fix magic login behind CDNs that strip Set-Cookie headers#82
bourafai wants to merge 1 commit intoaaemnnosttv:masterfrom
bourafai:fix/cdn-set-cookie-stripping

Conversation

@bourafai
Copy link

@bourafai bourafai commented Feb 17, 2026

Problem

When a site is behind a CDN configured to cache aggressively (e.g. Cloudflare with a "Cache Everything" page rule), the CDN strips Set-Cookie headers from the magic login response. The user gets redirected to wp-admin but is never logged in because the auth cookies never reach the browser.

This happens regardless of origin Cache-Control headers — CDN configurations like Cloudflare's Edge Cache TTL override them entirely.

Solution

Use a two-step handoff through wp-login.php:

  1. Magic URL → validates the token, creates a short-lived transient (30s), redirects to wp-login.php?wp_cli_login_token=<token>. No cookies set here.
  2. wp-login.phplogin_init handler reads the transient, sets auth cookies, fires hooks, redirects to the final destination.

This works because wp-login.php is universally excluded from CDN caching (cf-cache-status: DYNAMIC on Cloudflare), so Set-Cookie headers pass through.

What's preserved

All existing behavior is maintained in the new handle_login_handoff() function:

  • wp_set_auth_cookie() call
  • wp_cli_login/login and wp_login action hooks
  • login_redirect and wp_cli_login/login_redirect filters
  • Multisite capability-based redirect logic

Tested with

  • Cloudflare with "Cache Everything" page rule (the exact setup that triggers the bug)
  • Varnish reverse proxy
  • Direct access (no CDN)

Copilot AI review requested due to automatic review settings February 17, 2026 10:36
@bourafai bourafai force-pushed the fix/cdn-set-cookie-stripping branch from f097c13 to f4be744 Compare February 17, 2026 10:41
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes an issue where magic login links fail when the site is behind a CDN that strips Set-Cookie headers from responses. The solution implements a two-step authentication handoff: the magic URL validates the token and redirects to wp-login.php with a short-lived handoff token, where the actual authentication cookies are set. Since CDNs universally exclude wp-login.php from caching, the cookies are guaranteed to reach the browser.

Changes:

  • Added handle_login_handoff() function to complete authentication on wp-login.php via the login_init hook
  • Modified run() to use the new handoff redirect instead of logging in directly
  • Replaced loginUser() and loginRedirect() methods with handoffRedirect() that creates a transient-based handoff token

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 205 to 206
* @throws BadMagic
*
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

The existing Behat test "It can redirect the user to an alternate URL on successful login" (features/login-create.feature:169) checks for the Set-Cookie header in the response from the magic link URL. With the new two-step redirect approach, the Set-Cookie header will now be set in the wp-login.php response (the second redirect), not the initial magic URL response. This test will likely fail and needs to be updated to follow redirects or check the final response for the Set-Cookie header.

Copilot uses AI. Check for mistakes.
Comment on lines +44 to +46
delete_transient('wp_cli_login/handoff/' . $token);

if (! $data || ! ($user = new \WP_User($data['user_id'])) || ! $user->exists()) {
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

The code checks if $data is falsy but doesn't validate that it's an array or contains the expected keys (user_id, redirect_url). If the transient data is corrupted or unexpectedly structured, accessing $data['user_id'] on line 57 or $data['redirect_url'] on line 76 could cause PHP warnings or errors. Consider adding explicit validation such as is_array($data) && isset($data['user_id']) to ensure the data structure is as expected before proceeding.

Copilot uses AI. Check for mistakes.
@bourafai bourafai force-pushed the fix/cdn-set-cookie-stripping branch 3 times, most recently from 7060ede to 6163c35 Compare February 17, 2026 10:47
CDNs configured to cache aggressively (e.g. Cloudflare with "Cache
Everything") strip Set-Cookie headers from the magic login response,
preventing users from being authenticated.

Use a two-step handoff: the magic URL now creates a short-lived
transient and redirects to wp-login.php, which CDNs universally
exclude from caching. The auth cookies are set there instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bourafai bourafai force-pushed the fix/cdn-set-cookie-stripping branch from 6163c35 to c2b69b8 Compare February 17, 2026 10:50
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