diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts index 016761fe99..b8247f066f 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts @@ -25,8 +25,6 @@ const migrationsDir = path.resolve( '../migrations', ); -const KEY_DURATION_MS = 3600 * 1000; - const TABLE = 'signing_keys'; type Row = { @@ -38,28 +36,32 @@ type Row = { type Options = { logger: Logger; database: Knex; + /** Expiration time of signing keys in seconds */ + keyDuration: number; }; export class DatabaseKeyStore { static async create(options: Options): Promise { - const { logger, database } = options; + const { database } = options; await database.migrate.latest({ directory: migrationsDir, }); - return new DatabaseKeyStore({ logger, database }); + return new DatabaseKeyStore(options); } private readonly logger: Logger; private readonly database: Knex; + private readonly keyDuration: number; private removingExpiredRows: boolean = false; private constructor(options: Options) { - const { logger, database } = options; + const { logger, database, keyDuration } = options; this.database = database; + this.keyDuration = keyDuration; this.logger = logger.child({ service: 'key-store' }); } @@ -90,7 +92,7 @@ export class DatabaseKeyStore { for (const row of rows) { const createdAt = utc(row.created_at); - const expireAt = createdAt.add(3 * KEY_DURATION_MS, 'ms'); + const expireAt = createdAt.add(3 * this.keyDuration, 'seconds'); const isExpired = expireAt.isBefore(); if (isExpired) { diff --git a/plugins/auth-backend/src/identity/TokenFactory.ts b/plugins/auth-backend/src/identity/TokenFactory.ts index 3899e2e608..60f827b51f 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.ts @@ -19,26 +19,30 @@ import { JSONWebKey, JWK, JWS } from 'jose'; import { Logger } from 'winston'; import { v4 as uuid } from 'uuid'; -const KEY_DURATION_MS = 3600 * 1000; - type Options = { - issuer: string; logger: Logger; + /** Value of the issuer claim in issued tokens */ + issuer: string; + /** Key store used for storing signing keys */ keyStore: KeyStore; + /** Expiration time of signing keys in seconds */ + keyDuration: number; }; export class TokenFactory implements TokenIssuer { private readonly issuer: string; private readonly logger: Logger; private readonly keyStore: KeyStore; + private readonly keyDuration: number; private keyExpiry?: number; private privateKeyPromise?: Promise; constructor(options: Options) { - const { issuer, logger, keyStore } = options; + const { issuer, logger, keyStore, keyDuration } = options; this.issuer = issuer; this.keyStore = keyStore; + this.keyDuration = keyDuration; this.logger = logger.child({ service: 'issuer' }); } @@ -68,7 +72,7 @@ export class TokenFactory implements TokenIssuer { delete this.privateKeyPromise; } - this.keyExpiry = Date.now() + KEY_DURATION_MS; + this.keyExpiry = Date.now() + this.keyDuration * 1000; const promise = (async () => { const key = await JWK.generate('EC', 'P-256', { use: 'sig', diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index 12ddbf8504..d57225daf6 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -37,15 +37,18 @@ export async function createRouter( const logger = options.logger.child({ plugin: 'auth' }); const baseUrl = `${options.config.getString('backend.baseUrl')}/auth`; + const keyDuration = 3600; const keyStore = await DatabaseKeyStore.create({ database: options.database, logger, + keyDuration, }); const issuer = new TokenFactory({ issuer: baseUrl, keyStore, logger, + keyDuration, }); router.use(cookieParser());