Back to all articles

Flutter + Supabase Auth: Secure by Default or Security Theatre?

Published on March 4, 2025

FlutterSupabaseAuthenticationApp SecurityMobile Development
Flutter + Supabase Auth: Secure by Default or Security Theatre?

Flutter + Supabase Auth: Secure by Default or Security Theatre?

Supabase markets itself as the "open-source Firebase alternative." Its Auth module promises OAuth, email magic links, social sign-ins, row-level security, and more—usually wired up in a dozen lines of Dart. But developers still ask us:

"If it's that easy, what's the catch? Are the defaults actually safe, or am I just staging security theatre?"

After integrating Supabase Auth in three production Flutter apps and pen-testing two of them, our verdict is:

  • Yes—Supabase is secure by default for most consumer use-cases.
  • But—you need half-a-dozen extra steps to guard against token abuse, environment leaks, and broken access controls.

Below is the full breakdown, including what we tighten in every client retainer at THE USEFUL APPS.


Table of Contents

  1. What Supabase Auth Does Out of the Box
  2. Five Hidden Risks We Discovered
  3. Lock-Down Checklist for Production
  4. OAuth Social Sign-Ins the Right Way
  5. Row-Level Security Rules — Common Pitfalls
  6. Secure Storage of JWTs in Flutter
  7. CI/CD and Secrets Management
  8. Real-World Benchmarks vs Firebase Auth
  9. When Supabase Isn't Enough
  10. Conclusion & Next Steps

1. What Supabase Auth Does Out of the Box

Capability Default behaviour
Postgres roles & JWT Generates a short-lived (60 min) access token + refresh token signed with project's jwt_secret.
Row-Level Security Enabled, but all tables are public until you add policies.
OAuth providers Google, Apple, GitHub, Facebook pre-configured; you bring client IDs.
Magic links One-time links via Supabase SMTP relay (disabled in "Free Tier").
MFA Off (as of Supabase 2.36) but TOTP in beta.
Rate-limiting 6 requests/sec per IP for /auth/v1/** endpoints.

Take-away: Great starting posture, except row-level security is effectively open unless you write policies.


2. Five Hidden Risks We Discovered

  1. Leaky Service Key in Flutter code Many tutorials embed the service-role key (full DB admin privileges) in mobile builds—if reversed, your DB is toast.
  2. Refresh tokens stored in Shared Preferences The community package flutter_secure_storage defaults to plaintext on some Android OEMs prior to API 23.
  3. No webhook signature verification If you rely on user.updated or user.deleted webhooks for internal logic, you must check the HMAC header.
  4. Open social-login redirect URI Misconfigured deep links allow credential phishing ("Sign in with Google" popup to attacker domain).
  5. Missing Content Security Policy on WebView logins Hybrid apps exposing Supabase's hosted login page can be hit by XSS if CSP headers aren't set.

3. Lock-Down Checklist for Production

Action Fix
Rotate jwt_secret after staging Use Dashboard ➜ Settings ➜ API ➜ "Rotate".
Store only the anon key on device Keep service key in Cloud Functions or AWS Lambda.
Custom RLS policies Start with auth.uid() = id on user tables.
Tighten CORS & allowlist-domains Prevent rogue web origin token exchange.
Set up log retention + anomaly alerts Supabase logs stream to your own Grafana.

We bake these tasks into our Care Plan; see our pricing page for details.


4. OAuth Social Sign-Ins the Right Way

  • Use Apple Sign-In on iOS (App Store Guideline 4.8).
  • Always enforce verified email (identity.email_confirmed_at IS NOT NULL).
  • For Google: request "select_account" prompt to avoid silent rogue account linking.
  • Store provider ID in a dedicated profiles table—don't rely on raw_user_meta_data.

For more on Apple's requirements, see Apple Dev Doc App Store Review Guidelines §4.8 .


5. Row-Level Security Rules — Common Pitfalls

-- ❌ TOO OPEN: anyone can read others' messages
CREATE POLICY "Read messages" ON messages
  FOR SELECT USING (auth.role() = 'authenticated');

-- ✅ Tight: only sender or recipient
CREATE POLICY "Read own thread" ON messages
  FOR SELECT USING (
    auth.uid() IN (sender_id, recipient_id)
  );

Enable ALTER TABLE ... FORCE ROW LEVEL SECURITY; so future tables inherit your strictness.


6. Secure Storage of JWTs in Flutter

Option iOS Android
flutter_secure_storage Keychain ✔ Keystore ✔ (API 23+)
shared_preferences Plaintext ❌ Plaintext ❌
Our choice flutter_appauth + AuthFlow → Short-lived token in memory, refresh in background.

Tip: Use supabase_flutter 2.0 and pass a custom LocalStorage implementation that wraps Keychain/Keystore only.


7. CI/CD and Secrets Management

  • Store SUPABASE_URL, SUPABASE_ANON_KEY as GitHub Secrets.
  • Service key lives in AWS Parameter Store, fetched by backend functions.
  • Run supabase db diff in PRs to CI-check RLS rules.
  • Add Snyk to scan dependencies for JWT and crypto lib CVEs.

8. Real-World Benchmarks vs Firebase Auth

Test (1 000 logins) Supabase Firebase
Median sign-in latency 280 ms 190 ms
Cold-start SDK size (Flutter) 1.6 MB 2.1 MB
Pricing (10 000 MAU) $0 (free tier) $0 (free tier)
Enterprise SSO In beta GA

Unless you need phone auth at scale or multi-tenant SAML today, Supabase matches Firebase for most indie + SME apps.


9. When Supabase Isn't Enough

  • SOC 2 / HIPAA projects—Supabase compliance roadmap still "coming."
  • > 1 000 write QPS — Postgres row-level security can add latency; consider partitioning.
  • Offline-first apps — Supabase Sync is alpha; we pair it with Hive or Drift for local cache.

10. Conclusion & Next Steps

Supabase Auth is secure by default—as long as you know what "default" actually covers. Harden the RLS rules, keep service keys off devices, and store tokens in secure enclaves—then you have enterprise-grade auth without Firebase lock-in.

Need help auditing your Supabase Flutter app? Book a free security review or explore how our Growth Plan folds continuous security checks into monthly maintenance.


Share this article

Let's turn your app idea into revenue

Schedule a 30-minute strategy call. Walk away with a clear roadmap, ballpark budget, and the next three steps to grow your iOS or Android product.

Illustration of mobile app growth