Creating a Waitlist with Firebase Auth

Implement a waitlist sign-up with Firebase Auth and allow sign-ins in batches to your SaaS

3 min read
Cover Image for Creating a Waitlist with Firebase Auth

If you are building a new SaaS and only want to make your service available to small batches of users, you may wish to allow signups but restrict users who can sign into your application.

Thanks to Firebase Auth Blocking Functions, this has become a much easier task than in the past. In this article, we want to show you how to create a waitlist that allows users to sign up but restricts those who can sign in in batches of users.

This post assumes you have a working authentication implementation with Firebase and Next.js.

This is the (straightforward) strategy we will use:

  1. We define a beforeCreate function: on sign-up, we add users to a collection waitlist: we will store the user ID and the timestamp when they signed up
  2. We define a max timestamp where users that signed in before the timestamp will be allowed to sign in
  3. We define a beforeSignIn function: on sign-in, we verify that the user signed up before the timestamp constant we defined

Adding users to a Waitlist Collection

When users sign-up, we add them to a collection we name waitlist: in this collection's documents, we will store the user's ID and the timestamp when they signed up.

The logic is the following:

  • allow users that signed up before timestamp to sign in and use the application. timestamp is defined as a hard-coded timestamp, but of course, you can apply logic as complex as you feel like.
src/functions/index.ts
import { auth } from 'firebase-functions'; import { getFirestore } from 'firebase-admin/firestore'; export const onSignUp = auth.user().beforeCreate(async (user) => { const collection = await getWaitlistCollection(); await collection.add({ userId: user.uid, timestamp: new Date().getTime(), }); }); async function getWaitlistCollection() { await initializeFirebaseAdminApp(); const firestore = getFirestore(); return firestore.collection(`waitlist`); }

Initially, we may want to fully disable sign-ins:

export const onSignIn = auth.user().beforeSignIn( ({ uid }) => { throw new auth.HttpsError('invalid-argument', `Unauthorized user`); });

Verifying Users signed in before timestamp cutoff

When it's time to allow users to sign in, we can implement the following logic:

  1. Retrieve the user record in the waitlist
  2. Compare the max timestamp cutoff with the record's timestamp property
  3. Reject sign-in if the record's timestamp property is greater than the cutoff time
// Thu Oct 06 2022 19:51:58 GMT+0200 (Central European Summer Time) const ALLOWED_MAX_TIMESTAMP = 1665078710248; export const onSignIn = auth.user().beforeSignIn(async ({ uid }) => { const collection = await getWaitlistCollection(); const docRef = await collection.where('userId', '==', uid).get(); const doc = docRef.docs[0]?.data(); if (!doc) { throw new auth.HttpsError('invalid-argument', `Unauthorized user`); } if (doc.timestamp > ALLOWED_MAX_TIMESTAMP) { throw new auth.HttpsError('invalid-argument', `Unauthorized user`); } });

Of course, remember to handle the errors on your client-side components.

And that's it! If you need help with the above, feel free to reach out or join our Discord Community!.



Read more about Tutorials

Cover Image for Building an AI-powered Blog with Next.js and WordPress

Building an AI-powered Blog with Next.js and WordPress

17 min read
Learn how to build a blog with Next.js 13 and WordPress and how to leverage AI to generate content.
Cover Image for Using Supabase Vault to store secrets

Using Supabase Vault to store secrets

6 min read
Supabase Vault is a Postgres extension that allows you to store secrets in your database. This is a great way to store API keys, tokens, and other sensitive information. In this tutorial, we'll use Supabase Vault to store our API keys
Cover Image for Introduction to Next.js Server Actions

Introduction to Next.js Server Actions

9 min read
Next.js Server Actions are a new feature introduced in Next.js 13 that allows you to run server code without having to create an API endpoint. In this article, we'll learn how to use them.
Cover Image for Next.js 13: complete guide to Server Components and the App Directory

Next.js 13: complete guide to Server Components and the App Directory

17 min read
Unlock the full potential of Next.js 13 with our most complete and definitive tutorial on using server components and the app directory.
Cover Image for Pagination with React.js and Supabase

Pagination with React.js and Supabase

6 min read
Discover the best practices for paginating data using Supabase and React.js using the Supabase Postgres client
Cover Image for How to sell code with Lemon Squeezy and Github

How to sell code with Lemon Squeezy and Github

7 min read
Sell and monetize your code by giving private access to your Github repositories using Lemon Squeezy