diff --git a/lib/Authenticator.ts b/lib/Authenticator.ts deleted file mode 100644 index e69de29..0000000 diff --git a/lib/Gateway.ts b/lib/Gateway.ts index 4caaee6..5f8e222 100644 --- a/lib/Gateway.ts +++ b/lib/Gateway.ts @@ -7,27 +7,31 @@ interface GatewayOptions { } class GatewayClass { - private options: GatewayOptions; + private _options: GatewayOptions; public constructor (options: GatewayOptions) { - this.options = options; + this._options = options; } private redirect (res): void { res.statusCode = 302; - res.setHeader ('Location', this.options.redirect_url); + res.setHeader ('Location', this._options.redirect_url); res.end (); } - private async authenticate (req): Promise { + private async authenticate (req: Request): Promise { + await Promise.resolve (req.body); return false; } - public async process_request (req: Request, res: Response, next: AnyFunc): Promise { + public async process_request ( + req: Request, + res: Response, + next: AnyFunc + ): Promise { if (await this.authenticate (req)) - next (); - else - this.redirect (res); + return next (); + return this.redirect (res); } } diff --git a/lib/KeyStore.ts b/lib/KeyStore.ts new file mode 100644 index 0000000..882c010 --- /dev/null +++ b/lib/KeyStore.ts @@ -0,0 +1,26 @@ +import { create_salt } from '@sapphirecode/crypto-helper'; + +class KeyStore { + private _keys: Record = {}; + + public get_key (iat: number, valid_for = 0): string { + const key = Math.floor (iat / 60) + .toFixed (0); + + if (typeof this._keys[key] === 'string') + return this._keys[key]; + + if (valid_for !== 0) { + this._keys[key] = create_salt (); + setTimeout (() => { + delete this._keys[key]; + }, (valid_for + 5) * 1000); + return this._keys[key]; + } + + throw new Error ('key could not be found'); + } +} + +const ks: KeyStore = (new KeyStore); +export default ks; diff --git a/package.json b/package.json index 29ca5e5..b65bd3c 100644 --- a/package.json +++ b/package.json @@ -34,5 +34,8 @@ "authentication", "express", "middleware" - ] + ], + "dependencies": { + "@sapphirecode/crypto-helper": "^1.1.62" + } } diff --git a/test/.eslintrc.js b/test/.eslintrc.js new file mode 100644 index 0000000..94184dc --- /dev/null +++ b/test/.eslintrc.js @@ -0,0 +1,22 @@ +/* + * Copyright (C) Sapphirecode - All Rights Reserved + * This file is part of Auth-Server-Helper which is released under MIT. + * See file 'LICENSE' for full license details. + * Created by Timo Hocker , December 2020 + */ + +/* eslint-disable */ + +module.exports = { + env: { + commonjs: true, + es6: true, + node: true + }, + extends: [ '@sapphirecode/eslint-config-ts' ], + globals: { + Atomics: 'readonly', + SharedArrayBuffer: 'readonly' + }, + parserOptions: { ecmaVersion: 2018 } +}; diff --git a/test/spec/KeyStore.ts b/test/spec/KeyStore.ts new file mode 100644 index 0000000..96c3ec0 --- /dev/null +++ b/test/spec/KeyStore.ts @@ -0,0 +1,86 @@ +import ks from '../../lib/KeyStore'; + +/* eslint-disable-next-line max-lines-per-function */ +describe ('key store', () => { + beforeAll (() => { + jasmine.clock () + .install (); + const base_date = (new Date); + base_date.setSeconds (2); + jasmine.clock () + .mockDate (base_date); + }); + + const keys: {key:string, iat:number}[] = []; + + it ('should generate a new key', () => { + const iat = (new Date) + .getTime () / 1000; + const duration = 600; + const key = ks.get_key (iat, duration); + expect (typeof key) + .toEqual ('string'); + expect (key.length) + .toEqual (64); + keys.push ({ iat, key }); + }); + + it ('should return the generated key', () => { + const key = ks.get_key (keys[0].iat); + expect (key) + .toEqual (keys[0].key); + }); + + it ('should return the same key on a different time', () => { + const key = ks.get_key (keys[0].iat + 30); + expect (key) + .toEqual (keys[0].key); + }); + + it ('should generate a new key after 60 seconds', () => { + jasmine.clock () + .tick (60000); + const iat = (new Date) + .getTime () / 1000; + const duration = 600; + const key = ks.get_key (iat, duration); + expect (typeof key) + .toEqual ('string'); + expect (key.length) + .toEqual (64); + expect (key).not.toEqual (keys[0].key); + keys.push ({ iat, key }); + }); + + it ('should return both keys', () => { + const key = ks.get_key (keys[0].iat); + expect (key) + .toEqual (keys[0].key); + const k2 = ks.get_key (keys[1].iat); + expect (k2) + .toEqual (keys[1].key); + }); + + it ('should throw on non existing key', () => { + expect (() => ks.get_key (keys[1].iat + 60)) + .toThrowError ('key could not be found'); + }); + + it ('should delete a key after it expires', () => { + jasmine.clock () + .tick (600000); + expect (() => ks.get_key (keys[0].iat)) + .toThrowError ('key could not be found'); + }); + + it ('should still retrieve the second key', () => { + const key = ks.get_key (keys[1].iat); + expect (key) + .toEqual (keys[1].key); + }); + + afterAll (() => { + jasmine.clock () + .uninstall (); + }); +}); diff --git a/yarn.lock b/yarn.lock index fab66f9..0bdb4e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -245,6 +245,18 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" +"@sapphirecode/crypto-helper@^1.1.62": + version "1.1.62" + resolved "https://registry.yarnpkg.com/@sapphirecode/crypto-helper/-/crypto-helper-1.1.62.tgz#e5d610a3596166d47d1a509ae9a949c740994d92" + integrity sha512-J5Tk5/WYu9SaXeNI9hqkWz9X8NeH9zDTMDYddF3y/QofKpNW33AI30aVmLmEWbMvi8sHfQw5GidGAdRApciXYg== + dependencies: + "@sapphirecode/encoding-helper" "^1.0.38" + +"@sapphirecode/encoding-helper@^1.0.38": + version "1.0.51" + resolved "https://registry.yarnpkg.com/@sapphirecode/encoding-helper/-/encoding-helper-1.0.51.tgz#1d07793c995d12459ce2518bd3e6663ca4b11f69" + integrity sha512-aYaGbmaI33yGxfF1MP4nQmwREoSwN9EM0u1G6y0UuuryaObd3HzZIWE2N7hhVoHRLWUsUwneRGVhQGaLTwyd3A== + "@sapphirecode/eslint-config-es6@^1.1.1": version "1.2.2" resolved "https://registry.yarnpkg.com/@sapphirecode/eslint-config-es6/-/eslint-config-es6-1.2.2.tgz#0fff415a04ee305f7ae91898c01673b58bf86f83"