A secure tool designed for server-side user session management in applications using Supabase.
The default Supabase auth client lacks optimal compatibility with server components, leading to potential security risks and performance issues.
Using Supabase's auth.getUser()
method in server components triggers a unique backend request each time, potentially resulting in a large number of database queries. This can significantly slow down your system. Below is a screenshot from a Supabase dashboard showing the frequency of queries for a single user with minimal server components:
The typical approach of using getUser
once in middleware and then relying on getSession
is problematic. The getUser
method validates a JWT based solely on its format and expiry, not its authenticity, accepting any correctly formatted JWT as valid.
supabase-safesession
utilizes jsonwebtoken
to securely verify sessions without unnecessary database queries, focusing primarily on user ID to manage user-related data efficiently. It also handles expired tokens, leveraging Supabase to refresh tokens and update cookies accordingly.
- Retrieve your JWT secret from the Supabase project settings (API tab) and add it to your
.env
file.
- Install the package:
npm i supabase-safesession
- Create a Supabase server client and initialize
AuthManager
:
import { createServerClient, type CookieOptions } from "@supabase/ssr";
import { cookies } from "next/headers";
import { AuthManager } from "supabase-safesession";
export function createSupabaseServerClient() {
const cookieStore = cookies();
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return cookieStore.get(name)?.value;
},
set(name: string, value: string, options: CookieOptions) {
try {
cookieStore.set({ name, value, ...options });
} catch (error) {
console.error("Error setting cookie in server component:", error);
}
},
remove(name: string, options: CookieOptions) {
try {
cookieStore.delete({ name, ...options });
} catch (error) {
console.error("Error removing cookie in server component:", error);
}
},
},
}
);
}
// Export the initialized Supabase client and AuthManager
export const supabaseServerClient = () => createSupabaseServerClient();
export const supabaseServerAuth = () =>
new AuthManager(supabaseServerClient(), process.env.SUPABASE_JWT_SECRET!);
- use
AuthManager
inside your server components:
const autoRefreshToken = true;
export default async function ExampleComponent() {
// autoRefreshToken is optional with a default value of false
const {
data: session,
status,
error,
} = await supabaseServerAuth.getSafeSession(autoRefreshToken);
// Implement component logic using the session data
return <div>User session status: {status}</div>;
}