Random UI

use-supabase-auth

Elegant utility function for Supabase authentication

Why is it useful?

Usually, to get the user status with Supabase in NextJs server-side, we should do something like this:

const cookie = cookies();
const supabase = createClient(cookie);

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

if (!user) {
    // User does not exist
}

// Do stuff with user, but you may need some type safe conversion to get specific data here

With this utility instead, we're centralizing the declaration and the logic. Moreover, type safety is enforced to improve your code readability and maintainability.

Installation

Install the following dependencies:

npm install @supabase/supabase-js @supabase/ssr
pnpm add @supabase/supabase-js @supabase/ssr
yarn add @supabase/supabase-js @supabase/ssr
bun add @supabase/supabase-js @supabase/ssr

This guide assumes you have already configured Supabase in your project. If not, you can follow the official Supabase guide for NextJs.

useSupabaseAuth.ts
import { createClient } from "@/lib/supabase/server";
import { SupabaseClient } from "@supabase/supabase-js";
import { cookies } from "next/headers";

// Replace with your own type if you need extra attributes
export type ProfileModel = {
  id: string;
  fullName: string;
  email: string;
  avatar: string;
};

export type UseAuthProps =
| {
    isLoggedIn: true;
    user: ProfileModel;
    supabase: SupabaseClient;
    }
| {
    isLoggedIn: false;
    user: null;
    supabase: SupabaseClient;
    };

/**
* Utility hook to check current Supabase user
*
* It works **only Server Side**
* @returns {UseAuthProps} Auth object {@link UseAuthProps}
*/
export const useAuth = async (): Promise<UseAuthProps> => {
    const cookie = cookies();
    const supabase = createClient(cookie);

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

    if (user) {
        const userModel: ProfileModel = {
        id: user.id,
        fullName: user.user_metadata?.name ?? user.user_metadata?.user_name,
        email: user.email || "",
        avatar: user.user_metadata.avatar_url || "",
        };

        return { isLoggedIn: true, user: userModel, supabase };
    } else {
        return { isLoggedIn: false, user: null, supabase };
    }
};
useSupabaseAuth.ts
import { createClient, SupabaseClient } from '@supabase/supabase-js'
import supabase from '@/lib/supabase'

// Replace with your own type if you need extra attributes
export type ProfileModel = {
  id: string;
  fullName: string;
  email: string;
  avatar: string;
};

export type UseAuthProps =
| {
    isLoggedIn: true;
    user: ProfileModel;
    supabase: SupabaseClient;
    }
| {
    isLoggedIn: false;
    user: null;
    supabase: SupabaseClient;
    };

/**
* Utility hook to check current Supabase user
*
* It works **only Server Side**
* @returns {UseAuthProps} Auth object {@link UseAuthProps}
*/
export const useAuth = async (): Promise<UseAuthProps> => {

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

    if (user) {
        const userModel: ProfileModel = {
        id: user.id,
        fullName: user.user_metadata?.name ?? user.user_metadata?.user_name,
        email: user.email || "",
        avatar: user.user_metadata.avatar_url || "",
        };

        return { isLoggedIn: true, user: userModel, supabase };
    } else {
        return { isLoggedIn: false, user: null, supabase };
    }
};

Usage

async function myServerFunction(){

    const { isLoggedIn, user } = await useAuth();

    if (!isLoggedIn) {
        const isRandomUser = user.fullName === "Random UI" //TS ERROR: since "isLoggedIn" is false, user is undefined
    }  

    const isRandomUser = user.fullName === "Random UI" //OK: since "isLoggedIn" is true, user is defined and we can access its properties
    
}