67 lines
1.7 KiB
TypeScript
67 lines
1.7 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { prisma } from '@/lib/prisma'
|
|
import { generateToken, validateRefreshToken, createRefreshToken } from '@/lib/auth'
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const body = await request.json()
|
|
const { refreshToken } = body
|
|
|
|
if (!refreshToken) {
|
|
return NextResponse.json(
|
|
{ error: 'Refresh token is required' },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
// Validate the refresh token
|
|
const user = await validateRefreshToken(refreshToken)
|
|
if (!user) {
|
|
return NextResponse.json(
|
|
{ error: 'Invalid or expired refresh token' },
|
|
{ status: 401 }
|
|
)
|
|
}
|
|
|
|
// Generate new access token
|
|
const accessToken = generateToken({
|
|
userId: user.id,
|
|
email: user.email,
|
|
role: user.role,
|
|
})
|
|
|
|
// Generate new refresh token (token rotation)
|
|
const newRefreshToken = await createRefreshToken(user.id)
|
|
|
|
// Set the new access token in cookie
|
|
const response = NextResponse.json(
|
|
{
|
|
accessToken,
|
|
refreshToken: newRefreshToken,
|
|
user: {
|
|
id: user.id,
|
|
email: user.email,
|
|
username: user.username,
|
|
role: user.role,
|
|
},
|
|
},
|
|
{ status: 200 }
|
|
)
|
|
|
|
response.cookies.set('auth-token', accessToken, {
|
|
httpOnly: true,
|
|
secure: process.env.NODE_ENV === 'production',
|
|
sameSite: 'lax',
|
|
maxAge: 60 * 15, // 15 minutes
|
|
path: '/',
|
|
})
|
|
|
|
return response
|
|
} catch (error) {
|
|
console.error('Token refresh error:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Failed to refresh token' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
} |