惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
爱范儿
爱范儿
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
月光博客
月光博客
腾讯CDC
Last Week in AI
Last Week in AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园_首页
量子位
博客园 - 聂微东
Jina AI
Jina AI
小众软件
小众软件
The Cloudflare Blog
有赞技术团队
有赞技术团队
V
V2EX
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
大猫的无限游戏
大猫的无限游戏
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
阮一峰的网络日志
阮一峰的网络日志
B
Blog
MongoDB | Blog
MongoDB | Blog
L
LangChain Blog
宝玉的分享
宝玉的分享
C
Check Point Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
IT之家
IT之家
N
Netflix TechBlog - Medium
I
InfoQ
J
Java Code Geeks
S
SegmentFault 最新的问题
V
Visual Studio Blog
Microsoft Security Blog
Microsoft Security Blog
博客园 - 叶小钗
D
DataBreaches.Net
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
B
Blog RSS Feed
S
Schneier on Security
Webroot Blog
Webroot Blog
P
Proofpoint News Feed
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threatpost
Project Zero
Project Zero
Scott Helme
Scott Helme
C
CERT Recently Published Vulnerability Notes
P
Privacy International News Feed
T
The Exploit Database - CXSecurity.com
D
Darknet – Hacking Tools, Hacker News & Cyber Security

Supabase Blog

AI Agents Know About Supabase. They Don't Always Use It Right. Custom OIDC Providers for Supabase Auth 100,000 GitHub stars Supabase docs over SSH Navigating Regional Network Blocks Supabase Joins the Stripe Projects Developer Preview Log Drains: Now available on Pro Supabase Storage: major performance, security, and reliability updates Supabase incident on February 12, 2026 Hydra joins Supabase X / Twitter OAuth 2.0 is now available for Supabase Auth BKND joins Supabase Supabase is now an official Claude connector Supabase PrivateLink is now available Introducing: Postgres Best Practices When to use Read Replicas vs. bigger compute Introducing TRAE SOLO integration with Supabase Supabase Security Retro: 2025 Sync Stripe Data to Your Supabase Database in One Click Building ChatGPT Apps with Supabase Edge Functions and mcp-use Own Your Observability: Supabase Metrics API Introducing iceberg-js: A JavaScript Client for Apache Iceberg Introducing Supabase for Platforms Adding Async Streaming to Postgres Foreign Data Wrappers Build "Sign in with Your App" using Supabase Auth Introducing Seven New Email Templates for Supabase Auth The new Supabase power for Kiro Introducing Supabase ETL Introducing Analytics Buckets Introducing Vector Buckets Snap, Inc. Launches Snap Cloud, Powered by Supabase Triplit joins Supabase Supabase Series E 1000 Y Combinator Founders Choose Supabase gm 👋 web3, welcome aboard to Sign in with Web3 (Solana, Ethereum) Announcing the Supabase Remote MCP Server Enterprise speed, enterprise standards with Bolt Cloud + Supabase PostgREST 13 Lovable Cloud + Supabase: The Default Platform for AI Builders Processing large jobs with Edge Functions, Cron, and Queues Defense in Depth for MCP Servers OrioleDB Patent: now freely available to the Postgres community Supabase Launch Week 15 Hackathon Winner Announcement The Vibe Coder's Guide to Supabase Environments Testing for Vibe Coders: From Zero to Production Confidence The Vibe Coding Master Checklist Vibe Coding: Best Practices for Prompting Supabase Auth: Build vs. Buy Top 10 Launches of Launch Week 15 Supabase Launch Week 15 Hackathon Storage: 10x Larger Uploads, 3x Cheaper Cached Egress, and 2x Egress Quota Persistent Storage and 97% Faster Cold Starts for Edge Functions Algolia Connector for Supabase New Observability Features in Supabase Improved Security Controls and A New Home for Security Introducing Branching 2.0 Stripe-To-Postgres Sync Engine as standalone Library Supabase Analytics Buckets with Iceberg Support Create a Supabase backend using Figma Make Introducing JWT Signing Keys Supabase UI: Platform Kit Build a Personalized AI Assistant with Postgres Announcing Multigres: Vitess for Postgres Building on open table formats Open Data Standards: Postgres, OTel, and Iceberg Simplifying back-end complexity with Supabase Data APIs PostgreSQL Event Triggers without superuser access Top 10 Launches of Launch Week 14 Supabase MCP Server Data API Routes to Nearest Read Replica Declarative Schemas for Simpler Database Management Realtime: Broadcast from Database Keeping Tabs on What's New in Supabase Studio Edge Functions: Deploy from the Dashboard + Deno 2.1 Automatic Embeddings in Postgres Introducing the Supabase UI Library Supabase Auth: Bring Your Own Clerk Postgres Language Server: Initial Release Migrating from Fauna to Supabase Migrating from the MongoDB Data API to Supabase Dedicated Poolers Postgres as a Graph Database: (Ab)using pgRouting AI Hackathon at Y Combinator Calendars in Postgres using Foreign Data Wrappers Supabase Launch Week 13 Hackathon Winners How to Hack the Base! Running Durable Workflows in Postgres using DBOS database.build v2: Bring-your-own-LLM Restore to a New Project Hack the Base! with Supabase Top 10 Launches of Launch Week 13 Supabase Queues High Performance Disk Supabase Cron Supabase CLI v2: Config as Code Supabase Edge Functions: Introducing Background Tasks, Ephemeral Storage, and WebSockets Supabase AI Assistant v2 OrioleDB Public Alpha Executing Dynamic JavaScript Code on Supabase with Edge Functions ClickHouse Partnership, improved Postgres Replication, and Disk Management
Multi-factor Authentication via Row Level Security Enforcement
Joel Lee, Kang Ming Tay, Stojan Dimitrovski · 2022-12-14 · via Supabase Blog

Multi-factor Authentication via Row Level Security Enforcement

Today, we’re releasing Multi Factor Authentication for everyone.

Additionally, in preparation for releasing SAML, we're "dogfooding" the feature with the introduction of Single Sign On (SSO) on our dashboard. Contact us at growth@supabase.com if you want to enable this on your Enterprise plan.

Multi-factor authentication (MFA), sometimes called two-factor authentication (2FA), adds an additional layer of security to your application by letting you verify users’ identity through extra steps. This typically consists of something you know, like a password, and something you have, like an authenticator application. We built MFA in response to customer requests - developers wanted enhanced security - be it for compliance, client requirements, or simply for peace of mind. As such, we started by building MFA support for Time-Based One Time Passwords (TOTP).

TOTP works by generating a unique, one-time password that is valid for a limited amount of time, usually 30 seconds or less. This password is generated using a shared secret key that is known only to the device and Supabase Auth, along with the current time. To exchange the shared secret key, a user scans a QR code generated by the server in order to establish a connection. The QR code can be represented by a URI which conforms to the Google Authenticator Key URI format:


_10

otpauth://totp/supabase.io:j@supacats.io?algorithm=SHA1&digits=6&issuer=supabase.io&period=30&secret=BFSXQHFB2BGAZIOQWCDBJUF7B54A52JQ


The first portion of otpauth://totp/supabase.io describes the protocol and issuer while j@supacats.io refers to the user. The remaining parameters refer to specifics around OTP generation. In this case, the OTP code is generated using a SHA1 hash of the secret combined with the timestamp and the OTP code is valid for 30s

In the event that the user faces difficulties entering a QR code the user can also opt to manually type the secret into the authenticator device.

An MFA flow can be broken into two key steps: Enrollment and Verification. During the Enrollment process Supabase Auth exchanges a randomly generated secret with the user’s authenticator application. During the Verification process, the device makes use of the timestamp together with the secret to produce a six digit code that the server can verify.

Enrollment

To generate a QR code, call the /enroll endpoint which returns an SVG encoded QR and the secret. Thereafter, create a challenge by calling the /challenge endpoint. Once the user has entered the six digit TOTP code generated by their authenticator app, call the/verify endpoint with the corresponding factor and challenge details.

You might wonder: why the need for the "challenge" step? This step creates an interval between MFA initiation and the action of making a verification. This is useful in cases like Yubikey authentication where a user might need to request a challenge before placing their finger on the device.

Overview of Enrollment Flow

Verification

On subsequent logins attempts, redirect a user to an MFA verification after they have completed the conventional sign in process. On the verification page, wait for the user to enter the six digit OTP code from the authenticator application and then call the/challenge endpoint followed by the /verify endpoint. If a correct code is submitted, a JWT will be created with a few additional fields.

Overview of Verification Flow

Using MFA without enforcing it is like buying an expensive door and never locking it. We love Postgres RLS at Supabase. To support RLS integration, JWTs issued by Supabase Auth now contain two additional pieces of information:

  1. An Authenticator Assurance Level (AAL) claim. Use this to quickly identify the level of identity checks the user has performed. aal1 is reserved for conventional sign in, while aal2 is issued only after the user has verified with an additional factor.
  2. An Authenticator Method Reference (AMR) claim. Use this to identify all of the authentication methods used by the user. This is also useful if you wish to implement step-up login scenarios.


_18

{

_18

"sub": "8802c1d6-c555-46e3-aacd-b61198b058d9",

_18

"email": "j0@supacats.io",

_18

"aud": "authenticated",

_18

"exp": 1670929371,

_18

"aal": "aal2",

_18

"amr": [

_18

{

_18

"method": "password",

_18

"timestamp": 1670924394

_18

},

_18

{

_18

"method": "totp",

_18

"timestamp": 1670925771

_18

}

_18

],

_18

// ...

_18

}


The information encoded in these claims can be used for both full enforcement and partial enforcement across database queries.


_10

create policy "Enforce MFA for all end users."

_10

on table_name

_10

as restrictive

_10

to authenticated

_10

using ( (select auth.jwt()->>'aal') = 'aal2' );


Enforce MFA for all end users


_14

create policy "Allow access on table only if user has gone through MFA"

_14

on table_name

_14

as restrictive -- very important!

_14

to authenticated

_14

using (

_14

array[auth.jwt()->>'aal'] <@ (

_14

select

_14

case

_14

when count(id) > 0 then array['aal2']

_14

else array['aal1', 'aal2']

_14

end as aal

_14

from auth.mfa_factors

_14

where (select auth.uid()) = user_id and status = 'verified'

_14

));


Enforce MFA for selected users

Note that both RLS policies are restrictive. By default, overlapping policies in PostgreSQL are permissive rather than restrictive. This means that RLS policies are combined with an OR clause and only one policy needs to pass in order for a row to be operated on. Therefore, we set RLS policies as restrictive to enforce the checks from multiple policies.

Be mindful of your user’s preference, though. If a user has enabled MFA, they are expecting a higher level of security for their account. Consequently, we recommend that developers enforce MFA across all operations if a user has MFA enabled. You can check out our MFA guide for more details about MFA enforcement.

For starters, we are looking to support WebAuthn and FIDO2 compliant devices such as Yubikeys. We also hope to allow users to receive email notifications when selected MFA actions are triggered. If you have MFA requirements which are not covered here feel free to write to us at support[at]supabase.io .

We are grateful to our early MFA users for the support and feedback provided throughout this period. In particular, we would like to thank Fabian Beer, Cogram, and Happl whose detailed feedback helped to shape our implementation. We would also like to specially thank the community behind the pquerna/otp and ajstarks/svgo libraries - their work is indispensable to this implementation.