Back to Guides
Guide2 October 2026

How to securely implement Supabase Auth in a web app

Decloak is an AI-powered web security intelligence platform that scans a site's HTTP/TLS posture, JavaScript, and third-party scripts to produce a report anyone can read. This guide is part of Decloak's library of practical, source-backed security guidance.

In this guide
  1. Key takeaways
  2. What is Supabase Auth and why does it matter?
  3. How do I create a Supabase client safely?
  4. How do I sign up and sign in users?
  5. How do I access the JWT and use it for authorized requests?
  6. How do I protect my tables with Row - Level Security?
  7. How do I persist and restore sessions securely?
  8. How do I log out a user?
  9. What security pitfalls should I watch out for?
  10. How can I verify my configuration with Decloak?
  11. Example: Fixing a leaked service_role key
  12. Summary

Key takeaways

What is Supabase Auth and why does it matter?

Supabase Auth is a built - in authentication service that issues JSON Web Tokens (JWTs) for each signed - in user, and those tokens are automatically attached to all Supabase client requests. This allows you to enforce fine - grained access control via Row - Level Security (RLS) on your database tables. Using Auth correctly prevents unauthenticated users from reading or modifying data, which is the first line of defense against data leaks.

How do I create a Supabase client safely?

First, install the Supabase JavaScript library:

npm install @supabase/supabase-js

Then create the client with the project URL and the public anon key (never embed the service_role key in client - side code):

import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
 'https://YOUR-PROJECT.supabase.co',
 'PUBLIC-ANON-KEY'
)

The anon key is safe to expose because it only allows operations that are permitted by your RLS policies.

How do I sign up and sign in users?

Supabase provides several authentication flows. Below are the most common password - based methods.

// Sign - up
const { user, session, error } = await supabase.auth.signUp({
 email: 'user@example.com',
 password: 'secret-password'
})

// Sign - in
const { user, session, error } = await supabase.auth.signInWithPassword({
 email: 'user@example.com',
 password: 'secret-password'
})

Other flows such as magic links, OTP, and social OAuth are available via signInWithMagicLink, signInWithOtp, and signInWithOAuth.

How do I access the JWT and use it for authorized requests?

After sign - in, Supabase stores the session automatically. You can read the access token like this:

const accessToken = supabase.auth.session()?.access_token

All subsequent calls (e.g., supabase.from('todos').select()) automatically include the JWT in the Authorization header, so the database can enforce RLS based on the user’s identity.

How do I protect my tables with Row - Level Security?

  1. Enable RLS on the target table in the Supabase dashboard or via SQL:
alter table public.todos enable row level security;
  1. Write a policy that ties rows to the authenticated user. The built - in function auth.uid() returns the UUID from the JWT.
create policy "user can read own rows"
 on public.todos
 for select
 using (auth.uid() = user_id);
  1. Add additional policies for insert, update, and delete as needed, always referencing auth.uid().

How do I persist and restore sessions securely?

Supabase stores the session in localStorage by default. On page load you can restore it:

const { data: { session } } = await supabase.auth.getSession()

If you prefer a more secure storage mechanism, you can configure the client to use sessionStorage or a custom storage adapter that encrypts data before writing it to the browser.

How do I log out a user?

Calling signOut clears the stored session and removes the JWT from future requests:

await supabase.auth.signOut()

What security pitfalls should I watch out for?

How can I verify my configuration with Decloak?

Run a free Decloak scan on your site URL. The scan’s core layers include:

  1. HTTP/TLS posture check
  2. Static HTML analysis
  3. Rendered - page network behaviour
  4. JavaScript CVE scanning (detects vulnerable libraries, not secrets)
  5. Tag manager intelligence
  6. Third - party domain mapping
  7. Vibe - coded platform security - this layer will detect if a service_role key is shipped to the client or if a Supabase table is left publicly readable. The report shows any exposed keys and tables, letting you remediate before attackers discover them.

Example: Fixing a leaked service_role key

If Decloak reports a service_role key in your bundled JavaScript, move the key to a server - only environment variable and use it only in server - side functions (e.g., Edge Functions or your own backend). Replace any client - side references with the public anon key.

Summary

Implementing Supabase Auth securely involves creating a client with the public anon key, using the built - in sign - up/sign - in flows, enabling RLS on every data table, writing policies that reference auth.uid(), persisting sessions safely, and ensuring privileged keys never reach the browser. A quick Decloak scan can confirm that no secrets are exposed and that your RLS policies are effective.

Free security scan

See what's actually exposed on your site.

Decloak's free scan runs in about 15 seconds, no account required, and covers:

  • HTTP/TLS security posture
  • JavaScript CVEs
  • Exposed Supabase/Lovable/Base44 misconfigurations
  • AI-written executive summary