diff --git a/web/docs/guides/auth.mdx b/web/docs/guides/auth.mdx
index 45fc7a522b7..38aa8a671b8 100644
--- a/web/docs/guides/auth.mdx
+++ b/web/docs/guides/auth.mdx
@@ -7,58 +7,7 @@ description: Use Supabase to Authenticate and Authorize your users.
import Link from '@docusaurus/Link'
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
-const providers = [
- {
- name: 'Apple',
- // logo: '/img/libraries/dart-icon.svg',
- href: '/docs/guides/auth/auth-apple',
- },
- {
- name: 'Bitbucket',
- // logo: '/img/libraries/dart-icon.svg',
- href: '/docs/guides/auth/auth-bitbucket',
- },
- {
- name: 'Discord',
- // logo: '/img/libraries/dart-icon.svg',
- href: '/docs/guides/auth/auth-discord',
- },
- {
- name: 'Facebook',
- // logo: '/img/libraries/dart-icon.svg',
- href: '/docs/guides/auth/auth-facebook',
- },
- {
- name: 'GitHub',
- // logo: '/img/libraries/dart-icon.svg',
- href: '/docs/guides/auth/auth-github',
- },
- {
- name: 'GitLab',
- // logo: '/img/libraries/dart-icon.svg',
- href: '/docs/guides/auth/auth-gitlab',
- },
- {
- name: 'Google',
- // logo: '/img/libraries/dart-icon.svg',
- href: '/docs/guides/auth/auth-google',
- },
- {
- name: 'Twitter',
- // logo: '/img/libraries/dart-icon.svg',
- href: '/docs/guides/auth/auth-twitter',
- },
- {
- name: 'Twitch',
- // logo: '/img/libraries/dart-icon.svg',
- href: '/docs/guides/auth/auth-twitch',
- },
- {
- name: 'Twilio',
- // logo: '/img/libraries/dart-icon.svg',
- href: '/docs/guides/auth/auth-twilio',
- },
-]
+import providers from '@site/src/data/authProviders'
## User Management
@@ -134,22 +83,6 @@ let user = await supabase.from('users').select('user_id, name')
// Still => { id: 'd0714948', name: 'Jane' }
```
-## Policies Are Like `WHERE` Clauses
-
-Policies are easy to understand once you get the hang of them. You can just think of them as adding a `WHERE` clause to every query. For example if you had a policy like this:
-
-```sql
-create policy "Individuals can view their own todos." on todos for
- select using (auth.uid() = user_id);
-```
-
-It would translate to this whenever a user tries to select from the todos table:
-
-```sql
-select *
-from todos
-where auth.uid() = todos.user_id; -- Policy is implicitly added.
-```
## How It Works
@@ -161,258 +94,9 @@ where auth.uid() = todos.user_id; -- Policy is implicitly added.
Supabase provides a special function in Postgres, `auth.uid()`, which extracts the user's UID from the JWT. This is especially useful when creating policies.
-## Policy Examples
-
-Here are some examples to show you the power of PostgreSQL's RLS. Each policy is attached to a table, and the policy is executed
-every time a table is accessed.
-
-### Allow read access
-
-```sql
--- 1. Create table
-create table profiles (
- id uuid references auth.users,
- avatar_url text
-);
-
--- 2. Enable RLS
-alter table profiles
- enable row level security;
-
--- 3. Create Policy
-create policy "Public profiles are viewable by everyone."
- on profiles for select using (
- true
- );
-```
-
-1. Creates a table called `profiles` in the public schema (default schema).
-2. Enables Row Level Security.
-3. Creates a policy which allows all `select` queries to run.
-
-### Restrict updates
-
-```sql
--- 1. Create table
-create table profiles (
- id uuid references auth.users,
- avatar_url text
-);
-
--- 2. Enable RLS
-alter table profiles
- enable row level security;
-
--- 3. Create Policy
-create policy "Users can update their own profiles."
- on profiles for update using (
- auth.uid() = id
- );
-```
-
-1. Creates a table called `profiles` in the public schema (default schema).
-2. Enables RLS.
-3. Creates a policy which allows logged in users to update their own data.
-
-### Policies with joins
-
-Policies can even include table joins. This example shows how you can query "external" tables to build more advanced rules.
-
-```sql
-create table teams (
- id serial primary key,
- name text
-);
-
--- 2. Create many to many join
-create table members (
- team_id bigint references teams,
- user_id uuid references auth.users
-);
-
--- 3. Enable RLS
-alter table teams
- enable row level security;
-
--- 4. Create Policy
-create policy "Team members can update team details if they belong to the team."
- on teams
- for update using (
- auth.uid() in (
- select user_id from members
- where team_id = id
- )
- );
-```
-
-### Policies with security definer functions
-
-Policies can also make use of `security definer functions`. This is useful in a many-to-many relationship where you want to restrict access to the linking table. Following the `teams` and `members` example from above, this example shows how you can use security definer function in combination with a policy to control access to the `members` table.
-
-```sql
--- 1. Follow example for 'Policies with joins' above
-
--- 2. Enable RLS
-alter table members
- enable row level security
-
--- 3. Create security definer function
-create or replace function get_teams_for_authenticated_user()
-returns setof bigint
-language sql
-security definer
-set search_path = public
-stable
-as $$
- select team_id
- from members
- where user_id = auth.uid()
-$$;
-
--- 4. Create Policy
-create policy "Team members can update team members if they belong to the team."
- on members
- for all using (
- team_id in (
- select get_teams_for_authenticated_user()
- )
- );
-
-```
-
-### Verifying email domains
-
-Postgres has a function `right(string, n)` that returns the rightmost n characters of a string.
-You could use this to match staff member's email domains.
-
-```sql
--- 1. Create table
-create table leaderboard (
- id uuid references auth.users,
- high_score bigint
-);
-
--- 2. Enable RLS
-alter table leaderboard
- enable row level security;
-
--- 3. Create Policy
-create policy "Only Blizzard staff can update leaderboard"
- on leaderboard
- for update using (
- right(auth.email(), 13) = '@blizzard.com'
- );
-```
-
-### Time to live for rows
-
-Policies can also be used to implement TTL or time to live feature that you see in Instagram stories or Snapchat.
-In the following example, rows of `stories` table are available only if they have been created within the last 24 hours.
-
-```sql
--- 1. Create table
-create table if not exists stories (
- id uuid not null primary key DEFAULT uuid_generate_v4(),
- created_at timestamp with time zone default timezone('utc' :: text, now()) not null,
- content text not null
-);
-
--- 2. Enable RLS
-alter table stories
- enable row level security;
-
--- 3. Create Policy
-create policy "Stories are live for a day"
- on stories
- for select using (
- created_at > (current_timestamp - interval '1 day')
- );
-```
-
-### Advanced policies
-
-Use the full power of SQL to build extremely advanced rules.
-
-In this example, we will create a `posts` and `comments` tables and then create a policy that depends on another policy.
-(In this case, the comments policy depends on the posts policy.)
-
-```sql
-create table posts (
- id serial primary key,
- creator_id uuid not null references auth.users(id),
- title text not null,
- body text not null,
- publish_date date not null default now(),
- audience uuid[] null -- many to many table omitted for brevity
-);
-
-create table comments (
- id serial primary key,
- post_id int not null references posts(id) on delete cascade,
- user_id uuid not null references auth.users(id),
- body text not null,
- comment_date date not null default now()
-);
-
-create policy "Creator can see their own posts"
-on posts
-for select
-using (
- auth.uid() = posts.creator_id
-);
-
-create policy "Logged in users can see the posts if they belong to the post 'audience'."
-on posts
-for select
-using (
- auth.uid() = any (posts.audience)
-);
-
-create policy "Users can see all comments for posts they have access to."
-on comments
-for select
-using (
- exists (
- select 1 from posts
- where posts.id = comments.post_id
- )
-);
-```
-
## Tips
-### You don't have to use policies
-
-You can also put your authorization rules in your middleware, similar to how you would create security rules with any other `backend <-> middleware <-> frontend` architecture.
-
-Policies are a tool. In the case of "serverless/Jamstack" setups, they are especially effective because you don't have to deploy any middleware at all.
-
-However, if you want to use another authorization method for your applications, that's also fine. Supabase is "just Postgres", so if your application
-works with Postgres, then it also works with Supabase.
-
-Tip: Make sure to enable RLS for all your tables, so that your tables are inaccessible. Then use the "Service" which we provide, which is designed to bypass RLS.
-
-### Check authentication settings on Supabase
-
-Navigate to Authentication > Settings on [app.supabase.io](https://app.supabase.io), and you'll be able to change settings for things like:
-
-- SITE URL, which is used for determining where to redirect users after they confirm their email addresses or attempt to use a magic link to log in.
-- Disabling email confirmations.
-- Enabling external OAuth providers, such as Google and GitHub.
-
-### Never use a service key on the client
-
-Supabase provides special "Service" keys, which can be used to bypass all RLS.
-These should never be used in the browser or exposed to customers, but they are useful for administrative tasks.
-
-### Managing User Data
-
-For security purposes, the `auth` schema is not exposed on the auto-generated API.
-Even though Supabase provides an `auth.users` table, it can be helpful to create tables in the `public` schema for storing user data.
-
-You can read more about this in the [Managing User Data](/docs/guides/auth/managing-user-data) guide.
-
-### Disable realtime for private tables
+#### Disable realtime for private tables
Our realtime server doesn't provide per-user security. Until we build a more robust auth system for WebSockets, you can disable realtime functionality for any private tables. To do this, you can manage the underlying Postgres replication publication:
@@ -437,9 +121,9 @@ alter publication supabase_realtime add table products;
alter publication supabase_realtime add table posts;
```
-We're in the process of building enhanced realtime security.
+We're in the process of building [enhanced realtime security](https://github.com/supabase/walrus).
## Next Steps
-- Read more about [Row Level Security](https://www.postgresql.org/docs/current/ddl-rowsecurity.html).
+- Read more about Auth in the [Guides](/docs/guides/auth/intro).
- Sign in: [app.supabase.io](https://app.supabase.io)
diff --git a/web/docs/guides/auth/auth-apple.mdx b/web/docs/guides/auth/auth-apple.mdx
index 9ee35962e3a..0391b3d6be6 100644
--- a/web/docs/guides/auth/auth-apple.mdx
+++ b/web/docs/guides/auth/auth-apple.mdx
@@ -1,6 +1,6 @@
---
id: auth-apple
-title: "OAuth with Apple"
+title: "Login with Apple"
description: Add Apple OAuth to your Supabase project
---
diff --git a/web/docs/guides/auth/auth-bitbucket.mdx b/web/docs/guides/auth/auth-bitbucket.mdx
index 625d9df8861..6ffc10c4760 100644
--- a/web/docs/guides/auth/auth-bitbucket.mdx
+++ b/web/docs/guides/auth/auth-bitbucket.mdx
@@ -1,6 +1,6 @@
---
id: auth-bitbucket
-title: "OAuth with Bitbucket"
+title: "Login with Bitbucket"
description: Add Bitbucket OAuth to your Supabase project
---
diff --git a/web/docs/guides/auth/auth-discord.mdx b/web/docs/guides/auth/auth-discord.mdx
index c11ce5b1997..a76631bdae5 100644
--- a/web/docs/guides/auth/auth-discord.mdx
+++ b/web/docs/guides/auth/auth-discord.mdx
@@ -1,6 +1,6 @@
---
id: auth-discord
-title: "OAuth with Discord"
+title: "Login with Discord"
description: Add Discord OAuth to your Supabase project
---
diff --git a/web/docs/guides/auth/auth-facebook.mdx b/web/docs/guides/auth/auth-facebook.mdx
index b0c7e7b1287..8b2c5fb8b9f 100644
--- a/web/docs/guides/auth/auth-facebook.mdx
+++ b/web/docs/guides/auth/auth-facebook.mdx
@@ -1,6 +1,6 @@
---
id: auth-facebook
-title: "OAuth with Facebook"
+title: "Login with Facebook"
description: Add Facebook OAuth to your Supabase project
---
diff --git a/web/docs/guides/auth/auth-github.mdx b/web/docs/guides/auth/auth-github.mdx
index 065271573b1..166a78102a8 100644
--- a/web/docs/guides/auth/auth-github.mdx
+++ b/web/docs/guides/auth/auth-github.mdx
@@ -1,6 +1,6 @@
---
id: auth-github
-title: "OAuth with GitHub"
+title: "Login with GitHub"
description: Add GitHub OAuth to your Supabase project
---
diff --git a/web/docs/guides/auth/auth-gitlab.mdx b/web/docs/guides/auth/auth-gitlab.mdx
index 350b9adf41a..eb3a9252f5f 100644
--- a/web/docs/guides/auth/auth-gitlab.mdx
+++ b/web/docs/guides/auth/auth-gitlab.mdx
@@ -1,6 +1,6 @@
---
id: auth-gitlab
-title: "OAuth with GitLab"
+title: "Login with GitLab"
description: Add GitLab OAuth to your Supabase project
---
diff --git a/web/docs/guides/auth/auth-google.mdx b/web/docs/guides/auth/auth-google.mdx
index ea4d8f46344..481cd653cce 100644
--- a/web/docs/guides/auth/auth-google.mdx
+++ b/web/docs/guides/auth/auth-google.mdx
@@ -1,6 +1,6 @@
---
id: auth-google
-title: "OAuth with Google"
+title: "Login with Google"
description: Add Google OAuth to your Supabase project
---
diff --git a/web/docs/guides/auth/auth-twilio.mdx b/web/docs/guides/auth/auth-twilio.mdx
index 172473afd60..a9ed349931a 100644
--- a/web/docs/guides/auth/auth-twilio.mdx
+++ b/web/docs/guides/auth/auth-twilio.mdx
@@ -1,6 +1,6 @@
---
id: auth-twilio
-title: SMS OTP with Twilio
+title: Phone Auth with Twilio
description: How to set up and use Mobile OTP with Twilio and Supabase.
---
diff --git a/web/docs/guides/auth/auth-twitch.mdx b/web/docs/guides/auth/auth-twitch.mdx
index 98ab85cccf6..4bc9cc7ab9a 100644
--- a/web/docs/guides/auth/auth-twitch.mdx
+++ b/web/docs/guides/auth/auth-twitch.mdx
@@ -1,6 +1,6 @@
---
id: auth-twitch
-title: 'OAuth with Twitch'
+title: 'Login with Twitch'
description: Add Twitch OAuth to your Supabase project
---
diff --git a/web/docs/guides/auth/auth-twitter.mdx b/web/docs/guides/auth/auth-twitter.mdx
index 3cc755cfd24..c422b2cc9ff 100644
--- a/web/docs/guides/auth/auth-twitter.mdx
+++ b/web/docs/guides/auth/auth-twitter.mdx
@@ -1,6 +1,6 @@
---
id: auth-twitter
-title: "OAuth with Twitter"
+title: "Login with Twitter"
description: Add Twitter OAuth to your Supabase project
---
diff --git a/web/docs/guides/auth/intro.mdx b/web/docs/guides/auth/intro.mdx
new file mode 100644
index 00000000000..1d52730c4bf
--- /dev/null
+++ b/web/docs/guides/auth/intro.mdx
@@ -0,0 +1,72 @@
+---
+id: intro
+title: Supabase Auth
+sidebar_label: Introduction
+description: Use Supabase to Authenticate and Authorize your users.
+# hide_table_of_contents: true
+---
+
+import Link from '@docusaurus/Link'
+import Tabs from '@theme/Tabs'
+import TabItem from '@theme/TabItem'
+import providers from '@site/src/data/authProviders'
+
+Supabase Auth is designed to work with Postgres. There are two parts to every Auth system:
+
+- Authentication: should this person be allowed in? If yes, who are they?
+- Authorization: once they are in, what are they allowed to do?
+
+## Authentication
+
+You can authenticate your users in several ways:
+
+- Email & password.
+- Magic links (one-click logins).
+- Social providers.
+- Phone logins.
+
+
+
+
+## Authorization
+
+
+When you need granular authorization rules, nothing beats PostgreSQL's Row Level Security (RLS).
+
+Policies are PostgreSQL's rule engine. They are incredibly powerful and flexible, allowing you to write complex SQL rules which fit your unique business needs.
+
+Get started with our [Row Level Security Guides](/docs/guides/auth/row-level-security).
\ No newline at end of file
diff --git a/web/docs/guides/auth/managing-user-data.mdx b/web/docs/guides/auth/managing-user-data.mdx
index bf55d3d18cf..ed1e169a1da 100644
--- a/web/docs/guides/auth/managing-user-data.mdx
+++ b/web/docs/guides/auth/managing-user-data.mdx
@@ -76,4 +76,35 @@ const { data: profile } = await supabase
If you need to fetch a full list of user profiles, we supply a `service_key` which you can use with your API and Client Libraries to bypass Row Level Security.
-Make sure you _NEVER_ expose this publicly. But it can be used on the server-side to fetch all of the profiles.
\ No newline at end of file
+Make sure you _NEVER_ expose this publicly. But it can be used on the server-side to fetch all of the profiles.
+
+
+## Advanced techniques
+
+### Using triggers
+
+If you want to add a row to your `public.users` table every time a user signs up, you can use triggers.
+If the trigger fails however, it could block the user sign ups - so make sure that the code is well-tested.
+
+For example:
+
+```sql
+-- inserts a row into public.users
+create function public.handle_new_user()
+returns trigger
+language plpgsql
+security definer
+search_path = public
+as $$
+begin
+ insert into public.users (id)
+ values (new.id);
+ return new;
+end;
+$$;
+
+-- trigger the function every time a user is created
+create trigger on_auth_user_created
+ after insert on auth.users
+ for each row execute procedure public.handle_new_user();
+```
\ No newline at end of file
diff --git a/web/docs/guides/auth/row-level-security.mdx b/web/docs/guides/auth/row-level-security.mdx
new file mode 100644
index 00000000000..12ec835ad4d
--- /dev/null
+++ b/web/docs/guides/auth/row-level-security.mdx
@@ -0,0 +1,313 @@
+---
+id: row-level-security
+title: Row Level Security
+description: Secure your data using Postgres Row Level Security.
+---
+
+When you need granular authorization rules, nothing beats PostgreSQL's [Row Level Security (RLS)](https://www.postgresql.org/docs/current/ddl-rowsecurity.html).
+
+[Policies](https://www.postgresql.org/docs/current/sql-createpolicy.html) are PostgreSQL's rule engine. They are incredibly powerful and flexible, allowing you to write complex SQL rules which fit your unique business needs.
+
+
+
+
+## Policies
+
+Policies are easy to understand once you get the hang of them. Each policy is attached to a table, and the policy is executed
+every time a table is accessed.
+You can just think of them as adding a `WHERE` clause to every query. For example a policy like this ...
+
+```sql
+create policy "Individuals can view their own todos."
+ on todos for select
+ using ( auth.uid() = user_id );
+```
+
+.. would translate to this whenever a user tries to select from the todos table:
+
+```sql
+select *
+from todos
+where auth.uid() = todos.user_id; -- Policy is implicitly added.
+```
+
+## Helper Functions
+
+Supabase provides you with a few easy functions that you can use with your policies.
+
+
+### `auth.uid()`
+
+Returns the ID of the user making the request.
+
+### `auth.role()`
+
+Returns the role of the user making the request. In most cases this is either `authenticated` or `anon`.
+
+### `auth.email()`
+
+Retuns the email of the user making the request.
+
+## Examples
+
+Here are some examples to show you the power of PostgreSQL's RLS.
+
+### Allow read access
+
+```sql
+-- 1. Create table
+create table profiles (
+ id uuid references auth.users,
+ avatar_url text
+);
+
+-- 2. Enable RLS
+alter table profiles
+ enable row level security;
+
+-- 3. Create Policy
+create policy "Public profiles are viewable by everyone."
+ on profiles for select using (
+ true
+ );
+```
+
+1. Creates a table called `profiles` in the public schema (default schema).
+2. Enables Row Level Security.
+3. Creates a policy which allows all `select` queries to run.
+
+### Restrict updates
+
+```sql
+-- 1. Create table
+create table profiles (
+ id uuid references auth.users,
+ avatar_url text
+);
+
+-- 2. Enable RLS
+alter table profiles
+ enable row level security;
+
+-- 3. Create Policy
+create policy "Users can update their own profiles."
+ on profiles for update using (
+ auth.uid() = id
+ );
+```
+
+1. Creates a table called `profiles` in the public schema (default schema).
+2. Enables RLS.
+3. Creates a policy which allows logged in users to update their own data.
+
+### Policies with joins
+
+Policies can even include table joins. This example shows how you can query "external" tables to build more advanced rules.
+
+```sql
+create table teams (
+ id serial primary key,
+ name text
+);
+
+-- 2. Create many to many join
+create table members (
+ team_id bigint references teams,
+ user_id uuid references auth.users
+);
+
+-- 3. Enable RLS
+alter table teams
+ enable row level security;
+
+-- 4. Create Policy
+create policy "Team members can update team details if they belong to the team."
+ on teams
+ for update using (
+ auth.uid() in (
+ select user_id from members
+ where team_id = id
+ )
+ );
+```
+
+### Policies with security definer functions
+
+Policies can also make use of `security definer functions`. This is useful in a many-to-many relationship where you want to restrict access to the linking table. Following the `teams` and `members` example from above, this example shows how you can use security definer function in combination with a policy to control access to the `members` table.
+
+```sql
+-- 1. Follow example for 'Policies with joins' above
+
+-- 2. Enable RLS
+alter table members
+ enable row level security
+
+-- 3. Create security definer function
+create or replace function get_teams_for_authenticated_user()
+returns setof bigint
+language sql
+security definer
+set search_path = public
+stable
+as $$
+ select team_id
+ from members
+ where user_id = auth.uid()
+$$;
+
+-- 4. Create Policy
+create policy "Team members can update team members if they belong to the team."
+ on members
+ for all using (
+ team_id in (
+ select get_teams_for_authenticated_user()
+ )
+ );
+
+```
+
+### Verifying email domains
+
+Postgres has a function `right(string, n)` that returns the rightmost n characters of a string.
+You could use this to match staff member's email domains.
+
+```sql
+-- 1. Create table
+create table leaderboard (
+ id uuid references auth.users,
+ high_score bigint
+);
+
+-- 2. Enable RLS
+alter table leaderboard
+ enable row level security;
+
+-- 3. Create Policy
+create policy "Only Blizzard staff can update leaderboard"
+ on leaderboard
+ for update using (
+ right(auth.email(), 13) = '@blizzard.com'
+ );
+```
+
+### Time to live for rows
+
+Policies can also be used to implement TTL or time to live feature that you see in Instagram stories or Snapchat.
+In the following example, rows of `stories` table are available only if they have been created within the last 24 hours.
+
+```sql
+-- 1. Create table
+create table if not exists stories (
+ id uuid not null primary key DEFAULT uuid_generate_v4(),
+ created_at timestamp with time zone default timezone('utc' :: text, now()) not null,
+ content text not null
+);
+
+-- 2. Enable RLS
+alter table stories
+ enable row level security;
+
+-- 3. Create Policy
+create policy "Stories are live for a day"
+ on stories
+ for select using (
+ created_at > (current_timestamp - interval '1 day')
+ );
+```
+
+### Advanced policies
+
+Use the full power of SQL to build extremely advanced rules.
+
+In this example, we will create a `posts` and `comments` tables and then create a policy that depends on another policy.
+(In this case, the comments policy depends on the posts policy.)
+
+```sql
+create table posts (
+ id serial primary key,
+ creator_id uuid not null references auth.users(id),
+ title text not null,
+ body text not null,
+ publish_date date not null default now(),
+ audience uuid[] null -- many to many table omitted for brevity
+);
+
+create table comments (
+ id serial primary key,
+ post_id int not null references posts(id) on delete cascade,
+ user_id uuid not null references auth.users(id),
+ body text not null,
+ comment_date date not null default now()
+);
+
+create policy "Creator can see their own posts"
+on posts
+for select
+using (
+ auth.uid() = posts.creator_id
+);
+
+create policy "Logged in users can see the posts if they belong to the post 'audience'."
+on posts
+for select
+using (
+ auth.uid() = any (posts.audience)
+);
+
+create policy "Users can see all comments for posts they have access to."
+on comments
+for select
+using (
+ exists (
+ select 1 from posts
+ where posts.id = comments.post_id
+ )
+);
+```
+
+
+## Tips
+
+### Disable realtime for private tables
+
+Our realtime server doesn't provide per-user security. Until we build a more robust auth system for WebSockets, you can disable realtime functionality for any private tables. To do this, you can manage the underlying Postgres replication publication:
+
+```sql
+/**
+ * REALTIME SUBSCRIPTIONS
+ * Only allow realtime listening on public tables.
+ */
+
+begin;
+ -- remove the realtime publication
+ drop publication if exists supabase_realtime;
+
+ -- re-create the publication but don't enable it for any tables
+ create publication supabase_realtime;
+commit;
+
+-- add a table to the publication
+alter publication supabase_realtime add table products;
+
+-- add other tables to the publication
+alter publication supabase_realtime add table posts;
+```
+
+We're in the process of building [enhanced realtime security](https://github.com/supabase/walrus).
+
+### You don't have to use policies
+
+You can also put your authorization rules in your middleware, similar to how you would create security rules with any other `backend <-> middleware <-> frontend` architecture.
+
+Policies are a tool. In the case of "serverless/Jamstack" setups, they are especially effective because you don't have to deploy any middleware at all.
+
+However, if you want to use another authorization method for your applications, that's also fine. Supabase is "just Postgres", so if your application
+works with Postgres, then it also works with Supabase.
+
+Tip: Make sure to enable RLS for all your tables, so that your tables are inaccessible. Then use the "Service" which we provide, which is designed to bypass RLS.
+
+
+### Never use a service key on the client
+
+Supabase provides special "Service" keys, which can be used to bypass all RLS.
+These should never be used in the browser or exposed to customers, but they are useful for administrative tasks.
diff --git a/web/sidebars.js b/web/sidebars.js
index 174de26686b..1676df931b6 100755
--- a/web/sidebars.js
+++ b/web/sidebars.js
@@ -136,10 +136,10 @@ module.exports = {
label: 'Auth',
collapsed: false,
items: [
- 'guides/auth/managing-user-data',
+ 'guides/auth/intro',
{
type: 'category',
- label: 'External Providers',
+ label: 'Authentication',
collapsed: true,
items: [
'guides/auth/auth-apple',
@@ -154,6 +154,12 @@ module.exports = {
'guides/auth/auth-twilio',
],
},
+ {
+ type: 'category',
+ label: 'Authorization',
+ collapsed: true,
+ items: ['guides/auth/row-level-security', 'guides/auth/managing-user-data'],
+ },
{
type: 'category',
label: 'Deep Dive',
diff --git a/web/src/css/custom.css b/web/src/css/custom.css
index 405599e4ef1..ac98141f03c 100755
--- a/web/src/css/custom.css
+++ b/web/src/css/custom.css
@@ -61,6 +61,8 @@
--custom-primary-light: #65d9a5;
--custom-primary-lighter: #9fe7c7;
--custom-primary-lightest: #c5f1dd;
+ --custom-primary-rgba: RGBA(36, 180, 126, 1);
+ --custom-primary-rgb: 36, 180, 126;
--custom-background-color: #1f1f1f;
--custom-background-color-highlight: #fff;
--custom-background-color-diff: #f5f6f7;
@@ -1297,3 +1299,35 @@ h4.method-list-item-label .method-list-item-validation {
overflow: hidden;
border: 2px solid var(--custom-border-color);
}
+
+.badge--official {
+ border-radius: 3px;
+ font-size: 0.6rem;
+ font-weight: 400;
+ text-transform: uppercase;
+ border-color: var(--custom-primary);
+ background-color: rgba(var(--custom-primary-rgb), 0.8);
+}
+.badge--unofficial {
+ border-radius: 3px;
+ font-size: 0.6rem;
+ font-weight: 400;
+ text-transform: uppercase;
+ color: var(--custom-content-color-lightest);
+ background: rgba(0, 0, 0, 0.1);
+ border-color: rgba(0, 0, 0, 0.05);
+}
+
+:root[data-theme='dark'] .badge--official {
+ background-color: rgba(var(--custom-primary-rgb), 0.5);
+}
+:root[data-theme='dark'] .badge--unofficial {
+ border-color: rgba(255, 255, 255, 0.1);
+ background: rgba(255, 255, 255, 0.05);
+}
+.code-block {
+ border-radius: 3px;
+ font-family: 'office code pro';
+ border: 1px solid var(--custom-border-color);
+ padding: 2px 6px;
+}
\ No newline at end of file
diff --git a/web/src/data/authProviders.js b/web/src/data/authProviders.js
new file mode 100644
index 00000000000..047b2744fe1
--- /dev/null
+++ b/web/src/data/authProviders.js
@@ -0,0 +1,130 @@
+const authProviders = [
+ // {
+ // name: 'Email',
+ // // logo: '/img/libraries/dart-icon.svg',
+ // href: '/docs/guides/auth/auth-apple',
+ // official: true,
+ // supporter: 'Supabase',
+ // platform: true,
+ // selfHosted: true,
+ // },
+ // {
+ // name: 'Magic Links',
+ // // logo: '/img/libraries/dart-icon.svg',
+ // href: '/docs/guides/auth/auth-apple',
+ // official: true,
+ // supporter: 'Supabase',
+ // platform: true,
+ // selfHosted: true,
+ // },
+ {
+ name: 'Apple',
+ // logo: '/img/libraries/dart-icon.svg',
+ href: '/docs/guides/auth/auth-apple',
+ official: true,
+ supporter: 'Supabase',
+ platform: true,
+ selfHosted: true,
+ },
+ {
+ name: 'Azure',
+ // logo: '/img/libraries/dart-icon.svg',
+ href: '/docs/guides/auth/auth-apple',
+ official: false,
+ supporter: 'TBD',
+ platform: false,
+ selfHosted: true,
+ },
+ {
+ name: 'Bitbucket',
+ // logo: '/img/libraries/dart-icon.svg',
+ href: '/docs/guides/auth/auth-bitbucket',
+ official: true,
+ supporter: 'Supabase',
+ platform: true,
+ selfHosted: true,
+ },
+ {
+ name: 'Discord',
+ // logo: '/img/libraries/dart-icon.svg',
+ href: '/docs/guides/auth/auth-discord',
+ official: true,
+ supporter: 'Supabase',
+ platform: true,
+ selfHosted: true,
+ },
+ {
+ name: 'Facebook',
+ // logo: '/img/libraries/dart-icon.svg',
+ href: '/docs/guides/auth/auth-facebook',
+ official: true,
+ supporter: 'Supabase',
+ platform: true,
+ selfHosted: true,
+ },
+ {
+ name: 'GitHub',
+ // logo: '/img/libraries/dart-icon.svg',
+ href: '/docs/guides/auth/auth-github',
+ official: true,
+ supporter: 'Supabase',
+ platform: true,
+ selfHosted: true,
+ },
+ {
+ name: 'GitLab',
+ // logo: '/img/libraries/dart-icon.svg',
+ href: '/docs/guides/auth/auth-gitlab',
+ official: true,
+ supporter: 'Supabase',
+ platform: true,
+ selfHosted: true,
+ },
+ {
+ name: 'Google',
+ // logo: '/img/libraries/dart-icon.svg',
+ href: '/docs/guides/auth/auth-google',
+ official: true,
+ supporter: 'Supabase',
+ platform: true,
+ selfHosted: true,
+ },
+ // {
+ // name: 'MessageBird',
+ // // logo: '/img/libraries/dart-icon.svg',
+ // href: '/docs/guides/auth/auth-twilio',
+ // official: false,
+ // supporter: 'Messagebird',
+ // platform: false,
+ // selfHosted: true,
+ // },
+ {
+ name: 'Twitter',
+ // logo: '/img/libraries/dart-icon.svg',
+ href: '/docs/guides/auth/auth-twitter',
+ official: true,
+ supporter: 'Supabase',
+ platform: true,
+ selfHosted: true,
+ },
+ {
+ name: 'Twitch',
+ // logo: '/img/libraries/dart-icon.svg',
+ href: '/docs/guides/auth/auth-twitch',
+ official: true,
+ supporter: 'Supabase',
+ platform: true,
+ selfHosted: true,
+ },
+ {
+ name: 'Twilio',
+ // logo: '/img/libraries/dart-icon.svg',
+ href: '/docs/guides/auth/auth-twilio',
+ official: true,
+ supporter: 'Supabase',
+ platform: true,
+ selfHosted: true,
+ },
+]
+
+export default authProviders
\ No newline at end of file