UNPKG

@guardian/pan-domain-node

Version:

NodeJs implementation of Guardian pan-domain auth verification

115 lines (114 loc) 7.1 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const api_1 = require("../src/api"); const panda_1 = require("../src/panda"); const fetch_public_key_1 = require("../src/fetch-public-key"); const fixtures_1 = require("./fixtures"); const utils_1 = require("../src/utils"); jest.mock('../src/fetch-public-key'); jest.useFakeTimers('modern'); describe('verifyUser', function () { test("return invalid cookie if missing", () => { expect(panda_1.verifyUser(undefined, "", new Date(0), api_1.guardianValidation).status).toBe(api_1.AuthenticationStatus.INVALID_COOKIE); }); test("return invalid cookie for a malformed signature", () => { const [data, signature] = fixtures_1.sampleCookie.split("."); const testCookie = data + ".1234"; expect(panda_1.verifyUser(testCookie, fixtures_1.publicKey, new Date(0), api_1.guardianValidation).status).toBe(api_1.AuthenticationStatus.INVALID_COOKIE); }); test("return expired", () => { const someTimeInTheFuture = new Date(5678); expect(someTimeInTheFuture.getTime()).toBe(5678); expect(panda_1.verifyUser(fixtures_1.sampleCookie, fixtures_1.publicKey, someTimeInTheFuture, api_1.guardianValidation).status).toBe(api_1.AuthenticationStatus.EXPIRED); }); test("return not authenticated if user fails validation function", () => { expect(panda_1.verifyUser(fixtures_1.sampleCookieWithoutMultifactor, fixtures_1.publicKey, new Date(0), api_1.guardianValidation).status).toBe(api_1.AuthenticationStatus.NOT_AUTHORISED); expect(panda_1.verifyUser(fixtures_1.sampleNonGuardianCookie, fixtures_1.publicKey, new Date(0), api_1.guardianValidation).status).toBe(api_1.AuthenticationStatus.NOT_AUTHORISED); }); test("return authenticated", () => { expect(panda_1.verifyUser(fixtures_1.sampleCookie, fixtures_1.publicKey, new Date(0), api_1.guardianValidation).status).toBe(api_1.AuthenticationStatus.AUTHORISED); }); }); describe('createCookie', function () { it('should return the same cookie based on the user details being provided', function () { const user = { firstName: "Test", lastName: "User", email: "test.user@guardian.co.uk", authenticatingSystem: "test", authenticatedIn: ["test"], expires: 1234, multifactor: true }; const cookie = panda_1.createCookie(user, fixtures_1.privateKey); expect(utils_1.decodeBase64(cookie)).toEqual(utils_1.decodeBase64(fixtures_1.sampleCookie)); expect(cookie).toEqual(fixtures_1.sampleCookie); }); }); describe('panda class', function () { beforeEach(() => { fetch_public_key_1.fetchPublicKey.mockResolvedValue({ key: 'PUBLIC KEY', lastUpdated: new Date() }); }); describe('stop', () => { it('stops auto refresh', () => { const panda = new panda_1.PanDomainAuthentication('cookiename', 'region', 'bucket', 'keyfile', (u) => true); expect(panda.keyUpdateTimer).not.toBeUndefined(); panda.stop(); expect(panda.keyUpdateTimer).toBeUndefined(); }); }); describe('getPublicKey', () => { it('getsPublicKey immediately when last fetch is within the cache time', () => __awaiter(this, void 0, void 0, function* () { const panda = new panda_1.PanDomainAuthentication('cookiename', 'region', 'bucket', 'keyfile', (u) => true); const fetchesBeforeGet = fetch_public_key_1.fetchPublicKey.mock.calls.length; yield expect(panda.getPublicKey()).resolves.toEqual('PUBLIC KEY'); const fetchesAfterGet = fetch_public_key_1.fetchPublicKey.mock.calls.length; expect(fetchesAfterGet).toEqual(fetchesBeforeGet); })); it('getsPublicKey after refetching when last fetch is outside the cache time', () => __awaiter(this, void 0, void 0, function* () { // cache time is 1 min const fiveMinsAgo = new Date(); fiveMinsAgo.setMinutes(fiveMinsAgo.getMinutes() - 5); fetch_public_key_1.fetchPublicKey.mockResolvedValue({ key: 'PUBLIC KEY', lastUpdated: fiveMinsAgo }); const panda = new panda_1.PanDomainAuthentication('cookiename', 'region', 'bucket', 'keyfile', (u) => true); const fetchesBefore = fetch_public_key_1.fetchPublicKey.mock.calls.length; yield expect(panda.getPublicKey()).resolves.toEqual('PUBLIC KEY'); fetch_public_key_1.fetchPublicKey.mockResolvedValue({ key: 'PUBLIC KEY 2', lastUpdated: fiveMinsAgo }); const fetchesAfter = fetch_public_key_1.fetchPublicKey.mock.calls.length; yield expect(panda.getPublicKey()).resolves.toEqual('PUBLIC KEY 2'); expect(fetchesAfter).toEqual(fetchesBefore + 1); })); }); describe('verify', () => { beforeEach(() => { fetch_public_key_1.fetchPublicKey.mockResolvedValue({ key: fixtures_1.publicKey, lastUpdated: new Date() }); }); it('should return authenticated if valid', () => __awaiter(this, void 0, void 0, function* () { jest.setSystemTime(100); const panda = new panda_1.PanDomainAuthentication('cookiename', 'region', 'bucket', 'keyfile', (u) => true); const { status } = yield panda.verify(`cookiename=${fixtures_1.sampleCookie}`); expect(status).toBe(api_1.AuthenticationStatus.AUTHORISED); })); it('should return expired if expired', () => __awaiter(this, void 0, void 0, function* () { jest.setSystemTime(10000); const panda = new panda_1.PanDomainAuthentication('cookiename', 'region', 'bucket', 'keyfile', (u) => true); const { status } = yield panda.verify(`cookiename=${fixtures_1.sampleCookie}`); expect(status).toBe(api_1.AuthenticationStatus.EXPIRED); })); it('should return not authenticated if validation fails', () => __awaiter(this, void 0, void 0, function* () { jest.setSystemTime(100); const panda = new panda_1.PanDomainAuthentication('cookiename', 'region', 'bucket', 'keyfile', api_1.guardianValidation); const { status } = yield panda.verify(`cookiename=${fixtures_1.sampleNonGuardianCookie}`); expect(status).toBe(api_1.AuthenticationStatus.NOT_AUTHORISED); })); }); });