import { db } from "@/lib/db"; import { refresh_tokens, users } from "@/lib/schema"; import { eq } from "drizzle-orm"; import { NextResponse } from "next/server"; import * as jwt from "jsonwebtoken"; const JWT_RT_SECRET = process.env.JWT_RT_SECRET as string; const JWT_AT_SECRET = process.env.JWT_AT_SECRET as string; export async function POST(req: Request) { const body = await req.json(); const { refresh_token } = body; if (!refresh_token) { return NextResponse.json({ error: "Refresh token is required" }, { status: 400 }); } let decoded; try { decoded = jwt.verify(refresh_token, JWT_RT_SECRET) as jwt.JwtPayload; } catch { return NextResponse.json({ error: "Invalid Refresh Token" }, { status: 403 }); } const currentToken = await db.query.refresh_tokens.findFirst({ where: eq(refresh_tokens.refresh_token, refresh_token), }); if (!currentToken || currentToken.revoked) { return NextResponse.json({ error: "Refresh token is invalid or revoked" }, { status: 403 }); } const user = await db.query.users.findFirst({ where: eq(users.username, decoded.username) }); if (!user) { return NextResponse.json({ error: "User not found" }, { status: 404 }); } // Generate a new access token const access_token = jwt.sign( { username: user.username, title: user.title, perm: user.permission }, JWT_AT_SECRET, { expiresIn: '1h' } ); // Optional: Rotate the refresh token (invalidate old and issue a new one) const new_refresh_token = jwt.sign( { username: user.username }, JWT_RT_SECRET, { expiresIn: '7d' } ); // Optionally update or remove the old token in the database await db.update(refresh_tokens) .set({ revoked: true }) .where(eq(refresh_tokens.refresh_token, refresh_token)); await db.insert(refresh_tokens).values({ username: user.username, refresh_token: new_refresh_token, issued_at: new Date(), expires_at: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) }); return NextResponse.json({ access_token, refresh_token: new_refresh_token }, { status: 200 }); }