nuxt-supabase-team-auth
Version:
Drop-in Nuxt 3 module for team-based authentication with Supabase
102 lines (101 loc) • 3.44 kB
JavaScript
import { defineEventHandler, readBody, createError, getCookie, deleteCookie, getHeader } from "h3";
import { jwtVerify } from "jose";
import { createSessionFromMagicLink } from "../utils/magicLinkSession.js";
import { serverSupabaseServiceRole } from "#supabase/server";
const createServiceRoleClient = serverSupabaseServiceRole;
export default defineEventHandler(async (event) => {
try {
const authHeader = getHeader(event, "authorization");
if (!authHeader) {
throw createError({
statusCode: 401,
message: "Missing authorization header"
});
}
const token = authHeader.replace("Bearer ", "");
if (!token) {
throw createError({
statusCode: 401,
message: "Invalid authorization header format"
});
}
const adminClient = createServiceRoleClient(event);
const { data: { user }, error: userError } = await adminClient.auth.getUser(token);
if (userError || !user) {
throw createError({
statusCode: 401,
message: "Invalid or expired token"
});
}
const { sessionId } = await readBody(event);
if (!sessionId) {
throw createError({
statusCode: 400,
message: "Session ID is required"
});
}
const { data: sessionData, error: sessionError } = await adminClient.from("impersonation_sessions").select("*").eq("id", sessionId).eq("target_user_id", user.id).is("ended_at", null).single();
if (sessionError || !sessionData) {
throw createError({
statusCode: 404,
message: "Active impersonation session not found"
});
}
const impersonationCookie = getCookie(event, "admin-impersonation");
if (!impersonationCookie) {
throw createError({
statusCode: 400,
message: "Admin impersonation cookie not found"
});
}
const jwtSecret = process.env.SUPABASE_JWT_SECRET;
if (!jwtSecret) {
throw createError({
statusCode: 500,
message: "SUPABASE_JWT_SECRET environment variable is required for impersonation functionality"
});
}
let adminEmail;
try {
const { payload } = await jwtVerify(impersonationCookie, new TextEncoder().encode(jwtSecret));
adminEmail = payload.admin_email;
if (!adminEmail) {
throw new Error("Admin email not found in JWT");
}
} catch (error) {
console.error("Failed to verify impersonation JWT:", error);
throw createError({
statusCode: 400,
message: "Invalid impersonation session token"
});
}
const { error: updateError } = await adminClient.from("impersonation_sessions").update({
ended_at: (/* @__PURE__ */ new Date()).toISOString()
}).eq("id", sessionId);
if (updateError) {
console.error("Failed to update impersonation session:", updateError);
}
deleteCookie(event, "admin-impersonation", {
path: "/"
});
const { session: adminSession } = await createSessionFromMagicLink(
adminClient,
adminEmail
);
return {
success: true,
message: "Impersonation ended successfully",
session: adminSession
};
} catch (error) {
console.error("Stop impersonation error:", error);
const errorObj = error;
if (errorObj.statusCode) {
throw error;
}
throw createError({
statusCode: 500,
message: errorObj.message || "Failed to stop impersonation"
});
}
});