You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

39 lines
1.2 KiB

const crypto = require('crypto')
const { env } = require('../config/env')
function sign(value) {
return crypto
.createHmac('sha256', env.auth.sessionSecret)
.update(value)
.digest('base64url')
}
function createSessionToken(accountId) {
const issuedAt = Math.floor(Date.now() / 1000)
const payload = Buffer.from(JSON.stringify({
sub: accountId,
iat: issuedAt,
exp: issuedAt + Math.max(1, Number(env.auth.sessionTtlHours || 168)) * 60 * 60,
})).toString('base64url')
return `${payload}.${sign(payload)}`
}
function verifySessionToken(token) {
const [payload, signature, extra] = String(token || '').trim().split('.')
if (!payload || !signature || extra) return null
const expected = sign(payload)
const actualBuffer = Buffer.from(signature)
const expectedBuffer = Buffer.from(expected)
if (actualBuffer.length !== expectedBuffer.length || !crypto.timingSafeEqual(actualBuffer, expectedBuffer)) return null
try {
const data = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8'))
if (!data.sub || !data.exp || Number(data.exp) <= Math.floor(Date.now() / 1000)) return null
return data
} catch (error) {
return null
}
}
module.exports = { createSessionToken, verifySessionToken }