Merge pull request #3134 from supabase/docs/plugins

Docs: improve the auth section
This commit is contained in:
Copple authored and GitHub committed 2021-09-24 08:57:57 +08:00
commit f27ff7dc8d
17 files changed
+603 -333

No files matched your search

+4 -320
View File
@@ -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)
+1 -1
View File
@@ -1,6 +1,6 @@
---
id: auth-apple
title: "OAuth with Apple"
title: "Login with Apple"
description: Add Apple OAuth to your Supabase project
---
+1 -1
View File
@@ -1,6 +1,6 @@
---
id: auth-bitbucket
title: "OAuth with Bitbucket"
title: "Login with Bitbucket"
description: Add Bitbucket OAuth to your Supabase project
---
+1 -1
View File
@@ -1,6 +1,6 @@
---
id: auth-discord
title: "OAuth with Discord"
title: "Login with Discord"
description: Add Discord OAuth to your Supabase project
---
+1 -1
View File
@@ -1,6 +1,6 @@
---
id: auth-facebook
title: "OAuth with Facebook"
title: "Login with Facebook"
description: Add Facebook OAuth to your Supabase project
---
+1 -1
View File
@@ -1,6 +1,6 @@
---
id: auth-github
title: "OAuth with GitHub"
title: "Login with GitHub"
description: Add GitHub OAuth to your Supabase project
---
+1 -1
View File
@@ -1,6 +1,6 @@
---
id: auth-gitlab
title: "OAuth with GitLab"
title: "Login with GitLab"
description: Add GitLab OAuth to your Supabase project
---
+1 -1
View File
@@ -1,6 +1,6 @@
---
id: auth-google
title: "OAuth with Google"
title: "Login with Google"
description: Add Google OAuth to your Supabase project
---
+1 -1
View File
@@ -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.
---
+1 -1
View File
@@ -1,6 +1,6 @@
---
id: auth-twitch
title: 'OAuth with Twitch'
title: 'Login with Twitch'
description: Add Twitch OAuth to your Supabase project
---
+1 -1
View File
@@ -1,6 +1,6 @@
---
id: auth-twitter
title: "OAuth with Twitter"
title: "Login with Twitter"
description: Add Twitter OAuth to your Supabase project
---
+72
View File
@@ -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.
<div class="container" style={{ padding: 0 }}>
<div class="row is-multiline">
{providers.map((x) => (
<div key={x.name} class="col col--4">
<Link class="card" to={x.href}>
<div class="card__body">
<div class="" style={{ display: 'flex', justifyContent: 'space-between', gap: 10 }}>
{x.logo && <img src={x.logo} alt={x.name} width="20" />}
<p>{x.name}</p>
<p>
{x.official ? <span class={`badge badge--official`}>
Official
</span>:
<span class={`badge badge--unofficial`}>
Unofficial
</span>
}
</p>
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
<div class="code-block" style={{ width: '100%', display: 'flex', justifyContent: 'space-between', fontSize: '0.7rem' }}>
<span>Platform:</span>
<span>{x.platform.toString()}</span>
</div>
<div class="code-block" style={{ width: '100%', display: 'flex', justifyContent: 'space-between', fontSize: '0.7rem' }}>
<span>Hosted:</span>
<span>{x.selfHosted.toString()}</span>
</div>
</div>
</div>
</Link>
</div>
))}
</div>
</div>
## 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).
+32 -1
View File
@@ -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.
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();
```
+313
View File
@@ -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.
<iframe className="w-full video-with-border" width="640" height="385" src="https://www.youtube-nocookie.com/embed/Ow_Uzedfohk" frameBorder="1" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen></iframe>
## 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.
+8 -2
View File
@@ -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',
+34
View File
@@ -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;
}
+130
View File
@@ -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