Created
February 22, 2024 11:55
-
-
Save daaru00/faef5b3b243a470c2eab15a4e3deff9d to your computer and use it in GitHub Desktop.
Session management using encrypted server-only cookie
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import crypto from 'crypto' | |
const COOKIE_NAME = 'session' | |
const COOKIE_GET_HEADER = 'Cookie' | |
const COOKIE_SET_HEADER = 'Set-Cookie' | |
const ENCRYPTION_ALGORITHM = 'aes-256-cbc' | |
/** | |
* Decode session from cookie header | |
* | |
* @param {object} headers | |
* @param {string} key | |
* @returns {object|null} session | |
*/ | |
export function decodeSession(headers = {}, key) { | |
const cookieHeader = headers[COOKIE_GET_HEADER] || headers[COOKIE_GET_HEADER.toLowerCase()] | |
if (!cookieHeader) { | |
return null | |
} | |
const cookies = cookieHeader.split(';').map(v => v.trim()).reduce((acc, cookie) => { | |
const [key, value] = cookie.split('=') | |
acc[key] = value | |
return acc | |
}, {}) | |
if (!cookies[COOKIE_NAME]) { | |
return null | |
} | |
const value = decodeURIComponent(cookies[COOKIE_NAME]) | |
const [iv, data] = value.split(':').map(value => Buffer.from(value, 'hex')) | |
let decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key), iv) | |
let decrypted = decipher.update(data) | |
decrypted = Buffer.concat([decrypted, decipher.final()]) | |
return JSON.parse(decrypted.toString()) | |
} | |
/** | |
* Encode session into cookie header | |
* | |
* @param {object} data | |
* @param {string} key | |
* @returns {object} headers | |
*/ | |
export function encodeSession(data = {}, key) { | |
const iv = crypto.randomBytes(16) | |
const cipher = crypto.createCipheriv(ENCRYPTION_ALGORITHM, Buffer.from(key), iv) | |
let encrypted = cipher.update(JSON.stringify(data)) | |
encrypted = Buffer.concat([encrypted, cipher.final()]) | |
const value = iv.toString('hex') + ':' + encrypted.toString('hex') | |
return { | |
[COOKIE_SET_HEADER]: `${COOKIE_NAME}=${encodeURIComponent(value)}; Secure; HttpOnly` | |
} | |
} | |
/** | |
* Clean session | |
* | |
* @returns {object} headers | |
*/ | |
export function cleanSession() { | |
return { | |
[COOKIE_SET_HEADER]: `${COOKIE_NAME}=none; Max-Age=1` | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment