<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adam Gazdiev</title>
    <description>The latest articles on DEV Community by Adam Gazdiev (@maysker).</description>
    <link>https://dev.to/maysker</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3305787%2Fb8207e64-48ed-4480-b7a6-27dd15e4dbf6.jpeg</url>
      <title>DEV Community: Adam Gazdiev</title>
      <link>https://dev.to/maysker</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maysker"/>
    <language>en</language>
    <item>
      <title>WooCommerce + JWT = 🔥 Cookies rejected, sessions lost - here’s why it happens</title>
      <dc:creator>Adam Gazdiev</dc:creator>
      <pubDate>Wed, 29 Oct 2025 16:05:19 +0000</pubDate>
      <link>https://dev.to/maysker/why-jwt-login-breaks-in-woocommerce-and-how-to-fix-it-cleanly-5m2</link>
      <guid>https://dev.to/maysker/why-jwt-login-breaks-in-woocommerce-and-how-to-fix-it-cleanly-5m2</guid>
      <description>&lt;p&gt;You finally get JWT auth working in your App — and then WooCommerce checkout explodes because the browser refuses your cookies&lt;/p&gt;

&lt;p&gt;When integrating an external frontend (in my case, an Angular SaaS app) with a WooCommerce webshop,&lt;br&gt;&lt;br&gt;
I hit a surprisingly common wall: &lt;strong&gt;JWT authentication just didn’t work&lt;/strong&gt; across domains.&lt;/p&gt;

&lt;p&gt;Cookies were rejected, sessions lost, and &lt;code&gt;SameSite=None&lt;/code&gt; turned into a silent killer of cross-domain checkout flows.&lt;br&gt;&lt;br&gt;
Even worse, WordPress refused to authenticate inside an iframe, breaking payment links and embedded logins.&lt;/p&gt;

&lt;h3&gt;
  
  
  The core issue
&lt;/h3&gt;

&lt;p&gt;WordPress and modern SPAs (Angular, React, Vue, etc.) live in different worlds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different &lt;strong&gt;domains&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Different &lt;strong&gt;cookie scopes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Different &lt;strong&gt;CORS / SameSite&lt;/strong&gt; rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Standard JWT or SSO plugins for WordPress usually fail here because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They rely on &lt;code&gt;wp_set_auth_cookie&lt;/code&gt;, which respects &lt;code&gt;SAMEORIGIN&lt;/code&gt; by default
&lt;/li&gt;
&lt;li&gt;They don’t allow &lt;code&gt;SameSite=None; Secure&lt;/code&gt; cookies
&lt;/li&gt;
&lt;li&gt;They assume same-domain requests
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, even if you send a valid JWT, your SPA can’t establish a native WordPress session cookie.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔧 The clean fix
&lt;/h3&gt;

&lt;p&gt;I built a small, dependency-free PHP bridge (~200 lines) that safely &lt;strong&gt;exchanges a verified JWT for real WordPress cookies&lt;/strong&gt;,&lt;br&gt;&lt;br&gt;
configured for modern browsers (&lt;code&gt;SameSite=None; Secure; HttpOnly&lt;/code&gt;) and protected by a strict CORS whitelist.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/Maysker/jwt-login-cookie-bridge" rel="noopener noreferrer"&gt;GitHub Repository — JWT Login Cookie Bridge&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Your app obtains a JWT from your backend (or your own auth service)
&lt;/li&gt;
&lt;li&gt;It calls this plugin endpoint (&lt;code&gt;/jwt-login-cookie.php&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;The plugin verifies the token and sets real WP cookies, as if the user logged in natively
&lt;/li&gt;
&lt;li&gt;Redirects (or iframes) the user back to WooCommerce — now authenticated
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  ✨ Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Direct JWT → WordPress cookie exchange
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SameSite=None; Secure; HttpOnly&lt;/code&gt; compliant
&lt;/li&gt;
&lt;li&gt;Strict CORS whitelist for safe cross-domain auth
&lt;/li&gt;
&lt;li&gt;Optional iframe embedding (&lt;code&gt;CSP&lt;/code&gt; / &lt;code&gt;frame-ancestors&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Works with WooCommerce sessions and REST API
&lt;/li&gt;
&lt;li&gt;No OAuth, no external dependencies — just pure PHP
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🚀 Where it helps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SaaS apps embedding WooCommerce inside external frontends
&lt;/li&gt;
&lt;li&gt;Corporate portals running separate APPs for shop / dashboard
&lt;/li&gt;
&lt;li&gt;Projects without server-level access (CSP or X-Frame-Options)
&lt;/li&gt;
&lt;li&gt;Any cross-domain WooCommerce ↔ SPA integration scenario
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  💡 Why this matters
&lt;/h3&gt;

&lt;p&gt;By default, &lt;strong&gt;WordPress can’t log users in from external origins.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Standard JWT plugins often break due to &lt;code&gt;SameSite=None&lt;/code&gt; restrictions, and OAuth bridges are overkill.&lt;/p&gt;

&lt;p&gt;This plugin provides a &lt;strong&gt;minimal, production-grade bridge&lt;/strong&gt; — clean, transparent, and easy to adapt to your setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lessons learned
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SameSite and Secure flags are critical — ignore them and auth silently fails
&lt;/li&gt;
&lt;li&gt;Simplicity beats complex SSO frameworks for cross-domain setups
&lt;/li&gt;
&lt;li&gt;Sometimes, 200 lines of code can save days of debugging browser cookie logic
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’ve faced similar &lt;code&gt;SameSite&lt;/code&gt; or cross-domain login problems with WooCommerce,&lt;br&gt;&lt;br&gt;
I’d love to hear how you solved them — or whether this approach worked for you.&lt;/p&gt;

&lt;h1&gt;
  
  
  webdev #security #cookies #frontend #samesite
&lt;/h1&gt;

</description>
      <category>javascript</category>
      <category>wordpress</category>
      <category>webdev</category>
      <category>security</category>
    </item>
  </channel>
</rss>
