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.
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!.


Stay informed with our latest resources for building a SaaS

Subscribe to our newsletter to receive updatesor

Read more about

Cover Image for Authenticating users with Remix and Supabase

Authenticating users with Remix and Supabase

·16 min read
Learn how to use Remix and Supabase to authenticate users in your application.
Cover Image for How Makerkit helps boost your SaaS SEO

How Makerkit helps boost your SaaS SEO

·4 min read
Learn how Makerkit can help boost your SaaS SEO thanks to its optimized codebase and SEO-friendly features.
Cover Image for How to sell code with Gumroad and Github

How to sell code with Gumroad and Github

·7 min read
Sell and monetize your code by giving private access to your Github repositories using Gumroad
Cover Image for Migrating to Next.js Server Components Layouts

Migrating to Next.js Server Components Layouts

·6 min read
A simple guide to migrating your _app.tsx component to the new Server Components released with Next.js 13
Cover Image for Getting Started with Next.js Server Components

Getting Started with Next.js Server Components

·8 min read
A simple introduction to using Server Components and the new Layouts Folder Structure with Next.js 13
Cover Image for Counting a collection's documents with Firebase Firestore

Counting a collection's documents with Firebase Firestore

·2 min read
In this article, we learn how to count the number of documents in a Firestore collection using a custom React.js hook.