refactor: migrate authentication from Supabase to Better Auth and update Prisma schema models

This commit is contained in:
Jose Selesan
2026-04-16 20:05:08 -03:00
parent bd30b32b49
commit f158845279
28 changed files with 1275 additions and 608 deletions

View File

@@ -1,78 +1,27 @@
import { db } from '@/lib/prisma';
import { supabase } from '@/lib/supabase';
import type { AppEnv } from '@/types/hono';
import type { MiddlewareHandler } from 'hono';
import { createRemoteJWKSet, jwtVerify } from 'jose';
import { createMiddleware } from "hono/factory";
import { auth } from "@/lib/auth";
import type { Session, User } from "@/lib/auth";
const JWKS_CACHE_TTL_MS = 5 * 60 * 1000;
export type AuthEnv = {
Variables: {
user: User;
session: Session;
};
};
let jwks: ReturnType<typeof createRemoteJWKSet> | null = null;
let jwksCacheTime = 0;
async function getJWKS() {
const now = Date.now();
if (!jwks || now - jwksCacheTime > JWKS_CACHE_TTL_MS) {
const supabaseUrl = process.env.SUPABASE_URL ?? process.env.VITE_SUPABASE_URL;
if (!supabaseUrl) {
throw new Error('SUPABASE_URL not configured');
}
const jwksUrl = new URL('/auth/v1/.well-known/jwks.json', supabaseUrl).toString();
jwks = createRemoteJWKSet(new URL(jwksUrl));
jwksCacheTime = now;
}
return jwks;
}
function getBearerToken(value: string | undefined): string | null {
if (!value) return null;
const [scheme, token] = value.split(' ');
if (scheme?.toLowerCase() !== 'bearer' || !token) return null;
return token;
}
export const requireAuth: MiddlewareHandler<AppEnv> = async (c, next) => {
const token = getBearerToken(c.req.header('authorization'));
if (!token) {
return c.json({ message: 'Missing bearer token.' }, 403);
}
let supabaseUserId: string;
let email: string | undefined;
try {
const jwksSet = await getJWKS();
const { payload } = await jwtVerify(token, jwksSet, {
algorithms: ['ES256'],
});
supabaseUserId = payload.sub as string;
email = payload.email as string | undefined;
} catch {
const { data, error } = await supabase.auth.getUser(token);
if (error || !data.user) {
return c.json({ message: 'Invalid or expired token.' }, 403);
}
supabaseUserId = data.user.id;
email = data.user.email?.toLowerCase();
}
if (!email) {
return c.json({ message: 'Auth user does not contain email.' }, 403);
}
const appUser = await db.user.findUnique({
where: { supabaseUserId },
select: { id: true },
export const requireAuth = createMiddleware<AuthEnv>(async (c, next) => {
const session = await auth.api.getSession({
headers: c.req.raw.headers,
});
if (!appUser) {
return c.json({ message: 'User not provisioned in backend.' }, 403);
console.log(session)
if (!session) {
return c.json({ message: "Unauthorized" }, 401);
}
c.set('appUserId', appUser.id);
c.set("user", session.user);
c.set("session", session.session);
await next();
};
});