authkit-js
Version:
Express auth toolkit (JWT, Sessions with Redis, Google/GitHub OAuth) in JavaScript
56 lines (50 loc) • 2.16 kB
JavaScript
const { cookieOptions, makeId } = require('../utils/cookies');
class SessionStrategy {
constructor(cfg) {
if (!cfg || !cfg.store) throw new Error('SessionStrategy: store required');
this.store = cfg.store;
this.opts = cfg.opts || {};
this.cookieCfg = Object.assign({ names: { session: 'sid', csrf: '_csrf' }, sameSite: 'lax' }, cfg.cookie || {});
this.serialize = cfg.serializeUser || (async (u) => u);
this.deserialize = cfg.deserializeUser || (async (data) => data);
}
async login(res, user) {
const sid = makeId(24);
const data = await this.serialize(user);
const ttl = this.opts.ttlSec != null ? this.opts.ttlSec : 24 * 60 * 60;
await this.store.set(sid, data, ttl);
const c = cookieOptions(this.cookieCfg);
const names = this.cookieCfg.names;
res.cookie(names.session, sid, { ...c, maxAge: ttl * 1000 });
const csrf = makeId(16);
res.cookie(names.csrf, csrf, { ...c, httpOnly: false, maxAge: ttl * 1000 });
return { sessionId: sid, csrf };
}
async authenticate(req) {
const names = this.cookieCfg.names;
const sid = req.cookies && req.cookies[names.session];
if (!sid) return null;
const data = await this.store.get(sid);
if (!data) return null;
const user = await this.deserialize(data);
if (!user) return null;
return { user, sessionId: sid };
}
async assertCsrf(req) {
const names = this.cookieCfg.names;
const sid = req.cookies && req.cookies[names.session];
const cookieCsrf = req.cookies && req.cookies[names.csrf];
const headerCsrf = req.headers && (req.headers['x-csrf-token'] || req.headers['X-CSRF-Token']);
if (!sid || !cookieCsrf || !headerCsrf || cookieCsrf !== headerCsrf) {
const err = new Error('CSRF validation failed'); err.status = 400; throw err;
}
}
async logout(req, res) {
const names = this.cookieCfg.names;
const sid = req.cookies && req.cookies[names.session];
if (sid) await this.store.del(sid);
res.clearCookie(names.session);
res.clearCookie(names.csrf);
}
}
module.exports = { SessionStrategy };