refactor: migrate authentication from Supabase to Better Auth and update Prisma schema models
This commit is contained in:
@@ -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();
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user