auth-backend: make key duration configurable
This commit is contained in:
@@ -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<DatabaseKeyStore> {
|
||||
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) {
|
||||
|
||||
@@ -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<JSONWebKey>;
|
||||
|
||||
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',
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user