Banning users with Supabase

HiramHiram
2 min read

For one of my side projects I came to the scenario in which I would like to have a way of prevent access to users who has demonstrated malicious activity or simply deny access 🙉

Ban users (easy way)

You can ban users directly from the Supabase authentication dashboard. Go to the user selection, choose the user, click on "ban user," and set a future date for how long the ban will last.

Ban users (funny way)

We are devs and we like to struggle to death until it got solved to be creative right?

Let’s say you are automating processes and the user got enough strikes to be banned but not deleted. For this case you would like to programmatically ban the user. Supabase service role allows to admin user for this and more cases, let’s focus on the banning process.

export function supabaseServiceClient(): SupabaseClient {
  return createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL || "",
    process.env.NEXT_PUBLIC_SUPABASE_SERVICE_KEY || "",
  );
}
export const TEN_YEARS_IN_HOURS = 87600;
const supabase = supabaseServiceClient();
const { error } = await supabase.auth.admin.updateUserById("user_id", {
    ban_duration: banned ? `${TEN_YEARS_IN_HOURS}h` : "none",
});

The previous code will set a timestamp with the current date + specific amount of hours (87600h = 10y). According to docs you can only pass none property which will unban users or amount + unit where valid units are: "ns", "us" (or "µs"), "ms", "s", "m", "h" (if you know why someone would use nano or micro seconds please let me know 🤔). Hence the reason I had to convert hours to years.

With this in place you can ban users, but what about kicking out already signed in users? At least with Next.js you can leverage this task to the middleware file.

export async function middleware(request: NextRequest) {
  const requestHeaders = new Headers(request.headers);

  const supabase = createClient();
  const {
    data: { user },
  } = await supabase.auth.getUser();

  //@ts-ignore
  if (user?.banned_until) {
    await supabase.auth.signOut();
    const redirectUrl = request.nextUrl.clone();
    redirectUrl.pathname = "/";
    return NextResponse.redirect(redirectUrl);
  }

  return NextResponse.next({
    request: {
      headers: requestHeaders,
    },
  });
}

The previous code retrieves user information and checks the banned_until property to block access for banned users. This might not be the perfect approach, but it gives you an idea of how to manage user access.

This is it, fellows. Feel free to make a comment, and let's keep having fun! 😵‍💫

0
Subscribe to my newsletter

Read articles from Hiram directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Hiram
Hiram

senior software engineer | cloud engineer