stacker.news/pages/api/signout.js

64 lines
2.3 KiB
JavaScript

import * as cookie from 'cookie'
import { datePivot } from '../../lib/time'
/**
* @param {NextApiRequest} req
* @param {NextApiResponse} res
* @return {void}
*/
export default (req, res) => {
// is there a cookie pointer?
const cookiePointerName = 'multi_auth.user-id'
const userId = req.cookies[cookiePointerName]
const secure = process.env.NODE_ENV === 'production'
// is there a session?
const sessionCookieName = secure ? '__Secure-next-auth.session-token' : 'next-auth.session-token'
const sessionJWT = req.cookies[sessionCookieName]
if (!userId && !sessionJWT) {
// no cookie pointer and no session cookie present. nothing to do.
res.status(404).end()
return
}
const cookies = []
const cookieOptions = {
path: '/',
secure,
httpOnly: true,
sameSite: 'lax',
expires: datePivot(new Date(), { months: 1 })
}
// remove JWT pointed to by cookie pointer
cookies.push(cookie.serialize(`multi_auth.${userId}`, '', { ...cookieOptions, expires: 0, maxAge: 0 }))
// update multi_auth cookie and check if there are more accounts available
const oldMultiAuth = req.cookies.multi_auth ? b64Decode(req.cookies.multi_auth) : undefined
const newMultiAuth = oldMultiAuth?.filter(({ id }) => id !== Number(userId))
if (!oldMultiAuth || newMultiAuth?.length === 0) {
// no next account available. cleanup: remove multi_auth + pointer cookie
cookies.push(cookie.serialize('multi_auth', '', { ...cookieOptions, httpOnly: false, expires: 0, maxAge: 0 }))
cookies.push(cookie.serialize('multi_auth.user-id', '', { ...cookieOptions, httpOnly: false, expires: 0, maxAge: 0 }))
res.setHeader('Set-Cookie', cookies)
res.status(204).end()
return
}
cookies.push(cookie.serialize('multi_auth', b64Encode(newMultiAuth), { ...cookieOptions, httpOnly: false }))
const newUserId = newMultiAuth[0].id
const newUserJWT = req.cookies[`multi_auth.${newUserId}`]
res.setHeader('Set-Cookie', [
...cookies,
cookie.serialize(cookiePointerName, newUserId, { ...cookieOptions, httpOnly: false }),
cookie.serialize(sessionCookieName, newUserJWT, cookieOptions)
])
res.status(302).end()
}
const b64Encode = obj => Buffer.from(JSON.stringify(obj)).toString('base64')
const b64Decode = s => JSON.parse(Buffer.from(s, 'base64'))