Auth Users Exposed
Level: WARN
Rationale
Referencing the auth.users
table in a view can inadvertently expose more data than intended.
Why shouldn't you expose auth.users with a view?
auth.users
is the primary table that backs Supabase Auth. It contains detailed information about each of your projects users, their login methods, and other personally identifiable information.
In Postgres, the built in mechanism for controlling access to rows within a table is row level security (RLS). By default, views in Postgres are "security definer" which means they do not respect RLS rules associated with the tables in the view's query. Materialized views similarly don't support RLS.
As a result, a public
security definer view referencing auth.users
exposes all user records to all API users, which is likely not what application developers intended.
How to Resolve
There are 2 recommended solutions for exposing user data to your application.
Trigger on auth.users
This option involves creating a table in the public schema, e.g. public.profiles
, containing a subset of columns from auth.users
that are appropriate for your application's use case. You can then set a trigger on auth.users
to automatically insert the relevant data into public.profiles
any time a new user is inserted into auth.users
.
Note that triggers execute in the same transaction as the insert into auth.users
so you must check the trigger logic carefully as any errors could block user signups to your project.
An additional benefit of this approach is that the public.profiles
table provides a logical place to store any additional user metadata that is needed for the application.
To start we need a location to store public user data in the public
schema:
1 2 3 4 5 6 7 |
|
Next, we create a trigger function to copy the data from auth.users
into public.profiles
when new rows are inserted
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Finally, we can create row level security policies on the public.profiles
schema to restrict access to certain operations:
1 2 3 4 5 6 7 8 9 |
|
For more information on this approach see the auth docs.
Security Invoker View with RLS on auth.users
The second recommended approach to securely exposing auth.users
data is to create a view with the configuration option security_invoker=on
. That setting, introduced in Postgres 15, tells the view to respect the RLS policies associated with the underlying tables from the query. Next, we can enable RLS on auth.users
and create any policy we need to restrict access to the data.
To enable security invoker mode on the view we can use the with (security_invoker=on)
clause:
1 2 3 4 5 6 7 8 9 |
|
Next, grant permissions and enable RLS on auth.users
:
1 2 |
|
and finally, create a policy defining which users should be able to see each record:
1 2 3 |
|