ghostguild-org/server/utils/auth.js

73 lines
1.6 KiB
JavaScript

import jwt from 'jsonwebtoken'
import Member from '../models/member.js'
import { connectDB } from './mongoose.js'
/**
* Verify JWT from cookie and return the decoded member.
* Throws 401 if token is missing or invalid.
*/
export async function requireAuth(event) {
await connectDB()
const token = getCookie(event, 'auth-token')
if (!token) {
throw createError({
statusCode: 401,
statusMessage: 'Authentication required'
})
}
let decoded
try {
decoded = jwt.verify(token, useRuntimeConfig().jwtSecret)
} catch (err) {
throw createError({
statusCode: 401,
statusMessage: 'Invalid or expired token'
})
}
const member = await Member.findById(decoded.memberId)
if (!member) {
throw createError({
statusCode: 401,
statusMessage: 'Member not found'
})
}
if (member.status === 'suspended' || member.status === 'cancelled') {
throw createError({
statusCode: 403,
statusMessage: 'Account is ' + member.status
})
}
// Verify session has not been revoked (tokenVersion incremented on logout)
if (decoded.tv !== member.tokenVersion) {
throw createError({
statusCode: 401,
statusMessage: 'Session has been revoked'
})
}
return member
}
/**
* Verify JWT and require admin role.
* Throws 401 if not authenticated, 403 if not admin.
*/
export async function requireAdmin(event) {
const member = await requireAuth(event)
if (member.role !== 'admin') {
throw createError({
statusCode: 403,
statusMessage: 'Admin access required'
})
}
return member
}