<?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: Chris Boulionis</title>
    <description>The latest articles on DEV Community by Chris Boulionis (@chris_b).</description>
    <link>https://dev.to/chris_b</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4213777%2F3a9af061-baec-46ae-b365-25fecc2e7dbe.jpg</url>
      <title>DEV Community: Chris Boulionis</title>
      <link>https://dev.to/chris_b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chris_b"/>
    <language>en</language>
    <item>
      <title>Supabase Auth in Next.js: 5 reasons users get logged out (and how to fix each)</title>
      <dc:creator>Chris Boulionis</dc:creator>
      <pubDate>Thu, 29 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/chris_b/supabase-auth-in-nextjs-5-reasons-users-get-logged-out-and-how-to-fix-each-19fj</link>
      <guid>https://dev.to/chris_b/supabase-auth-in-nextjs-5-reasons-users-get-logged-out-and-how-to-fix-each-19fj</guid>
      <description>&lt;p&gt;Auth bugs in Next.js with Supabase are rarely random. These are five causes that come up again and again.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The session is never refreshed
&lt;/h2&gt;

&lt;p&gt;With @supabase/ssr the session cookie has to be refreshed on the server. Add middleware that calls supabase.auth.getUser() on each request and writes the updated cookies back to the response. Without it, users get logged out when the access token expires.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Trusting getSession() on the server
&lt;/h2&gt;

&lt;p&gt;getSession() reads the cookie without verifying it. For anything that decides access, call getUser(), which asks the Auth server to validate the token.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Email links that expire immediately
&lt;/h2&gt;

&lt;p&gt;Some email security scanners open the link before the user does and use up the one-time token. A common fix is to send the user to a page of your own that asks for a click, and only then call verifyOtp with the token hash.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. OAuth only works on localhost
&lt;/h2&gt;

&lt;p&gt;Check the Site URL and the Redirect URLs allow-list in the Supabase dashboard. If your production URL is not listed, sign-in falls back or fails after deploy.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Cached routes that read cookies
&lt;/h2&gt;

&lt;p&gt;A route handler or page that reads auth cookies must be dynamic. If it gets cached, one user's state can show up for another or go stale.&lt;/p&gt;

&lt;h2&gt;
  
  
  More fixes
&lt;/h2&gt;

&lt;p&gt;I wrote a guide that covers 26 common sign-in, session, email-link and OAuth bugs, each with the symptom, the real cause and a fix: &lt;a href="https://getcodenest.com/products/fix-supabase-auth-next-js" rel="noopener noreferrer"&gt;https://getcodenest.com/products/fix-supabase-auth-next-js&lt;/a&gt;&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>nextjs</category>
      <category>authentication</category>
      <category>webdev</category>
    </item>
    <item>
      <title>3 Supabase RLS mistakes I keep seeing in real projects (and the fix for each)</title>
      <dc:creator>Chris Boulionis</dc:creator>
      <pubDate>Wed, 28 Oct 2026 19:38:42 +0000</pubDate>
      <link>https://dev.to/chris_b/3-supabase-rls-mistakes-i-keep-seeing-in-real-projects-and-the-fix-for-each-5f34</link>
      <guid>https://dev.to/chris_b/3-supabase-rls-mistakes-i-keep-seeing-in-real-projects-and-the-fix-for-each-5f34</guid>
      <description>&lt;p&gt;Row Level Security (RLS) is what stands between your users and each other's data in Supabase. These are three mistakes that show up again and again, with the fix for each.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. RLS was never enabled
&lt;/h2&gt;

&lt;p&gt;A table created with plain SQL has RLS switched off. Turn it on and add a policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;alter&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;notes&lt;/span&gt; &lt;span class="n"&gt;enable&lt;/span&gt; &lt;span class="k"&gt;row&lt;/span&gt; &lt;span class="k"&gt;level&lt;/span&gt; &lt;span class="k"&gt;security&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="nv"&gt;"owner can read"&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;notes&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Views skip RLS
&lt;/h2&gt;

&lt;p&gt;A view runs with its owner's rights unless you create it with security_invoker = true (Postgres 15 and newer). Without it, a view can expose rows the current user should not see.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="n"&gt;my_notes&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;security_invoker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;
  &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Trusting user_metadata in a policy
&lt;/h2&gt;

&lt;p&gt;Users can edit their own user_metadata, so never use it to decide roles or permissions. Use app_metadata or a roles table that only your server can write to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Want more patterns?
&lt;/h2&gt;

&lt;p&gt;I put 31 copy-paste RLS patterns (ownership, teams, roles, sharing, invites, soft delete and testing) into one guide: &lt;a href="https://getcodenest.com/products/supabase-rls-policy-cookbook" rel="noopener noreferrer"&gt;https://getcodenest.com/products/supabase-rls-policy-cookbook&lt;/a&gt;&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>postgres</category>
      <category>nextjs</category>
      <category>security</category>
    </item>
  </channel>
</rss>
