UNPKG

@guardian/pan-domain-node

Version:

NodeJs implementation of Guardian pan-domain auth verification

108 lines (107 loc) 4.55 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PanDomainAuthentication = exports.verifyUser = exports.createCookie = void 0; const cookie = __importStar(require("cookie")); const utils_1 = require("./utils"); const api_1 = require("./api"); const fetch_public_key_1 = require("./fetch-public-key"); function createCookie(user, privateKey) { let queryParams = []; queryParams.push("firstName=" + user.firstName); queryParams.push("lastName=" + user.lastName); queryParams.push("email=" + user.email); user.avatarUrl && queryParams.push("avatarUrl=" + user.avatarUrl); queryParams.push("system=" + user.authenticatingSystem); queryParams.push("authedIn=" + user.authenticatedIn.join(",")); queryParams.push("expires=" + user.expires.toString()); queryParams.push("multifactor=" + String(user.multifactor)); const combined = queryParams.join("&"); const queryParamsString = Buffer.from(combined).toString('base64'); const signature = utils_1.sign(combined, privateKey); return queryParamsString + "." + signature; } exports.createCookie = createCookie; function verifyUser(pandaCookie, publicKey, currentTime, validateUser) { if (!pandaCookie) { return { status: api_1.AuthenticationStatus.INVALID_COOKIE }; } const { data, signature } = utils_1.parseCookie(pandaCookie); if (!utils_1.verifySignature(data, signature, publicKey)) { return { status: api_1.AuthenticationStatus.INVALID_COOKIE }; } const currentTimestampInMilliseconds = currentTime.getTime(); try { const user = utils_1.parseUser(data); const isExpired = user.expires < currentTimestampInMilliseconds; if (isExpired) { return { status: api_1.AuthenticationStatus.EXPIRED, user }; } if (!validateUser(user)) { return { status: api_1.AuthenticationStatus.NOT_AUTHORISED, user }; } return { status: api_1.AuthenticationStatus.AUTHORISED, user }; } catch (error) { console.error(error); return { status: api_1.AuthenticationStatus.INVALID_COOKIE }; } } exports.verifyUser = verifyUser; class PanDomainAuthentication { constructor(cookieName, region, bucket, keyFile, validateUser) { this.keyCacheTime = 60 * 1000; // 1 minute this.cookieName = cookieName; this.region = region; this.bucket = bucket; this.keyFile = keyFile; this.validateUser = validateUser; this.publicKey = fetch_public_key_1.fetchPublicKey(region, bucket, keyFile); this.keyUpdateTimer = setInterval(() => this.getPublicKey(), this.keyCacheTime); } stop() { if (this.keyUpdateTimer) { clearInterval(this.keyUpdateTimer); this.keyUpdateTimer = undefined; } } getPublicKey() { return this.publicKey.then(({ key, lastUpdated }) => { const now = new Date(); const diff = now.getTime() - lastUpdated.getTime(); if (diff > this.keyCacheTime) { this.publicKey = fetch_public_key_1.fetchPublicKey(this.region, this.bucket, this.keyFile); return this.publicKey.then(({ key }) => key); } else { return key; } }); } verify(requestCookies) { return this.getPublicKey().then(publicKey => { const cookies = cookie.parse(requestCookies); const pandaCookie = cookies[this.cookieName]; return verifyUser(pandaCookie, publicKey, new Date(), this.validateUser); }); } } exports.PanDomainAuthentication = PanDomainAuthentication;