Fix magic login behind CDNs that strip Set-Cookie headers#82
Fix magic login behind CDNs that strip Set-Cookie headers#82bourafai wants to merge 1 commit intoaaemnnosttv:masterfrom
Conversation
f097c13 to
f4be744
Compare
There was a problem hiding this comment.
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 thelogin_inithook - Modified
run()to use the new handoff redirect instead of logging in directly - Replaced
loginUser()andloginRedirect()methods withhandoffRedirect()that creates a transient-based handoff token
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * @throws BadMagic | ||
| * |
There was a problem hiding this comment.
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.
| delete_transient('wp_cli_login/handoff/' . $token); | ||
|
|
||
| if (! $data || ! ($user = new \WP_User($data['user_id'])) || ! $user->exists()) { |
There was a problem hiding this comment.
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.
7060ede to
6163c35
Compare
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>
6163c35 to
c2b69b8
Compare
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-Cookieheaders from the magic login response. The user gets redirected towp-adminbut is never logged in because the auth cookies never reach the browser.This happens regardless of origin
Cache-Controlheaders — CDN configurations like Cloudflare's Edge Cache TTL override them entirely.Solution
Use a two-step handoff through
wp-login.php:wp-login.php?wp_cli_login_token=<token>. No cookies set here.login_inithandler reads the transient, sets auth cookies, fires hooks, redirects to the final destination.This works because
wp-login.phpis universally excluded from CDN caching (cf-cache-status: DYNAMICon Cloudflare), soSet-Cookieheaders pass through.What's preserved
All existing behavior is maintained in the new
handle_login_handoff()function:wp_set_auth_cookie()callwp_cli_login/loginandwp_loginaction hookslogin_redirectandwp_cli_login/login_redirectfiltersTested with