Supabase Authentication and create Stripe customer - Subscription with Supabase and Stripe Billing | Part 1

25 July 2022[updated]

5 min read

Web development

In this series, we are going to learn how to implement a subscription system with Stripe and Supabase. We will use Supabase Authentication, Supabase Database, and Stripe Billing.

This guide is not intended to be a complete walk-through of the code you need to write. It is instead an overview of the main steps and gotchas that I found in the process of learning how to set up the system. I will highlight the main API calls and give you access to external references and sources. It will be up to you to structure the system as you prefer and with any programming language of your choice.

Feel free to reach out if you need any clarification.


Create an account on Supabase and Stripe Billing

Visit the website of Supabase and Stripe and create an account for both.

Follow this video to sign up and create a new project on Supabase.

Click on Sign In to create a Supabase account

Click the Sign In button on the top-right corner to create an account. Then create an organization and a new project in Supabase.

Click on Sign In to create a Stripe account

Click on the Sign In button on the top-right corner.

Setup Supabase users table

We create a user table to store the minimum required information of each user. The user will have in id, an email, and a customer_id (from Stripe).

Supabase database table for the user

An example of user in Supabase.

The id is of type uuid and it is the primary key of the table, while the email and the customer_id are of type varchar.

-- Supabase postgresql database
CREATE TABLE public."user"
(
    id uuid NOT NULL DEFAULT uuid_generate_v4(),
    email character varying COLLATE pg_catalog."default" NOT NULL,
    customer_id character varying COLLATE pg_catalog."default",
    CONSTRAINT user_pkey PRIMARY KEY (id)
)

When we sign up the user using Supabase Authentication, a trigger will automatically create a new row in the user table with the id and email values. The trigger we use is the following:

create function public.handle_new_user()
returns trigger as $$
begin
  insert into public.user (id, email)
  values (new.id, new.email);
  return new;
end;
$$ language plpgsql security definer;

-- 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();

If the sign up is successful, we will have a new row in the user table with the id and email values. The customer_id field is still NULL since when did not yet register the customer on Stripe.

Signin up the user using Supabase is easy:

const { user, session, error } = await supabase.auth.signUp({
  email: 'example@email.com',
  password: 'example-password',
})

The signUp method will return the newly created row in the user table (with id and email).

Create Stripe customer for Stripe billing

Right after the sign up we need to register the user with the same email to Stripe.

We create an API endpoint in the backend of our application. The endpoint will accept a POST request with the user email in the body. We register a new stripe customer from the given email:

const { email } = req.body;
const customer = await stripe.customers.create({
  email, // <- User email from the request body
});
res.send(customer);

The previous call will return the new customer information. We are interested in the customer_id autogenerated by Stripe. The endpoint returns the newly created customer.

We need to update the user in our Supabase database by adding the customer_id from Stripe:

const response = await supabase
      .from('user')
      .update({
        customer_id: customerId, // <- Customer id from API endpoint
      })
      .match({
        id: supabaseId, // <- Uuid of the user from Supabase sign up
      });

If everything is successful, we now have completed the registration phase!

Sign in the user with Supabase Authentication

Signing in the user with Supabase is as easy as the sign up:

const { user, session, error } = await supabase.auth.signIn({
  email: 'example@email.com',
  password: 'example-password',
})

Supabase will manage the complete Authentication process for you. You do not need to store any other information or implement any other functionality. Check out the documentation from Supabase.

Recap

  1. Create an account on Supabase
  2. Create an account on Stripe
  3. Create a new user table in Supabase
  4. Create a trigger to insert new users in the user table on each signup
  5. Collect the user email and password and complete the sign up by calling supabase.auth.signUp
  6. Create an API endpoint to insert a new customer on Stripe after each sign up by calling stripe.customers.create
  7. Insert the customerId from Stripe in the customer_id field of the user table on Supabase
  8. Sign in the user by calling supabase.auth.signIn

In three easy steps, we completed the authentication phase. We now have a user registered both on Supabase and Stripe, with a shared customer_id field.

In the next part of the guide we are going to understand how product and pricing work in Stripe billing.