From 8ff4fe598c1abf2654b08f3b780ea3a6b6b194bb Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 4 Feb 2021 11:35:21 +0100 Subject: [PATCH 01/15] Add luxon and remove moment --- plugins/auth-backend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 27cb725faa..439b60e3ce 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -47,7 +47,7 @@ "jose": "^1.27.1", "jwt-decode": "^3.1.0", "knex": "^0.21.6", - "moment": "^2.26.0", + "luxon": "^1.25.0", "morgan": "^1.10.0", "node-cache": "^5.1.2", "openid-client": "^4.2.1", From 306dc12f3a11e99383d294b0fb905359e9c3821f Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 4 Feb 2021 11:36:40 +0100 Subject: [PATCH 02/15] Port moment to luxon --- .../src/identity/DatabaseKeyStore.test.ts | 3 +-- .../auth-backend/src/identity/DatabaseKeyStore.ts | 9 ++++----- .../auth-backend/src/identity/MemoryKeyStore.ts | 6 +++--- plugins/auth-backend/src/identity/TokenFactory.ts | 14 +++++++------- plugins/auth-backend/src/identity/types.ts | 2 +- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts index b22ab0ecda..94dd442b44 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts @@ -15,7 +15,6 @@ */ import Knex from 'knex'; -import moment from 'moment'; import { DatabaseKeyStore } from './DatabaseKeyStore'; function createDB() { @@ -51,7 +50,7 @@ describe('DatabaseKeyStore', () => { const { items } = await store.listKeys(); expect(items).toEqual([{ createdAt: expect.anything(), key }]); - expect(Math.abs(items[0].createdAt.diff(moment(), 's'))).toBeLessThan(10); + expect(Math.abs(items[0].createdAt.diffNow('seconds').seconds)).toBeLessThan(10); }); it('should remove stored keys', async () => { diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts index c24cac55be..cc4838cf9b 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts @@ -15,9 +15,9 @@ */ import Knex from 'knex'; -import { utc } from 'moment'; import { resolvePackagePath } from '@backstage/backend-common'; import { AnyJWK, KeyStore, StoredKey } from './types'; +import { DateTime } from 'luxon'; const migrationsDir = resolvePackagePath( '@backstage/plugin-auth-backend', @@ -62,12 +62,11 @@ export class DatabaseKeyStore implements KeyStore { async listKeys(): Promise<{ items: StoredKey[] }> { const rows = await this.database(TABLE).select(); - return { items: rows.map(row => ({ - key: JSON.parse(row.key), - createdAt: utc(row.created_at), - })), + key: JSON.parse(row.key), + createdAt: DateTime.fromFormat(row.created_at, 'yyyy-MM-dd HH:mm:ss', {zone: 'UTC'}), + })), }; } diff --git a/plugins/auth-backend/src/identity/MemoryKeyStore.ts b/plugins/auth-backend/src/identity/MemoryKeyStore.ts index b35002b146..0903f6987d 100644 --- a/plugins/auth-backend/src/identity/MemoryKeyStore.ts +++ b/plugins/auth-backend/src/identity/MemoryKeyStore.ts @@ -14,18 +14,18 @@ * limitations under the License. */ -import { utc } from 'moment'; import { KeyStore, AnyJWK, StoredKey } from './types'; +import { DateTime } from 'luxon'; export class MemoryKeyStore implements KeyStore { private readonly keys = new Map< string, - { createdAt: moment.Moment; key: string } + { createdAt: DateTime; key: string } >(); async addKey(key: AnyJWK): Promise { this.keys.set(key.kid, { - createdAt: utc(), + createdAt: DateTime.local().toUTC(), key: JSON.stringify(key), }); } diff --git a/plugins/auth-backend/src/identity/TokenFactory.ts b/plugins/auth-backend/src/identity/TokenFactory.ts index 36622332e0..6874b08789 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -import moment from 'moment'; import { TokenIssuer, TokenParams, KeyStore, AnyJWK } from './types'; import { JSONWebKey, JWK, JWS } from 'jose'; import { Logger } from 'winston'; import { v4 as uuid } from 'uuid'; +import { DateTime } from 'luxon'; const MS_IN_S = 1000; @@ -52,7 +52,7 @@ export class TokenFactory implements TokenIssuer { private readonly keyStore: KeyStore; private readonly keyDurationSeconds: number; - private keyExpiry?: moment.Moment; + private keyExpiry?: DateTime; private privateKeyPromise?: Promise; constructor(options: Options) { @@ -90,8 +90,8 @@ export class TokenFactory implements TokenIssuer { for (const key of keys) { // Allow for a grace period of another full key duration before we remove the keys from the database - const expireAt = key.createdAt.add(3 * this.keyDurationSeconds, 's'); - if (expireAt.isBefore()) { + const expireAt = key.createdAt.plus({ seconds: 3 * this.keyDurationSeconds }); + if (expireAt < DateTime.local()) { expiredKeys.push(key); } else { validKeys.push(key); @@ -115,16 +115,16 @@ export class TokenFactory implements TokenIssuer { } private async getKey(): Promise { - // Make sure that we only generate one key at a time + // Make sure that we only generate one key at a time¨ if (this.privateKeyPromise) { - if (this.keyExpiry?.isAfter()) { + if (this.keyExpiry > DateTime.local()) { return this.privateKeyPromise; } this.logger.info(`Signing key has expired, generating new key`); delete this.privateKeyPromise; } - this.keyExpiry = moment().add(this.keyDurationSeconds, 'seconds'); + this.keyExpiry = DateTime.local().plus({ seconds: this.keyDurationSeconds }); const promise = (async () => { // This generates a new signing key to be used to sign tokens until the next key rotation const key = await JWK.generate('EC', 'P-256', { diff --git a/plugins/auth-backend/src/identity/types.ts b/plugins/auth-backend/src/identity/types.ts index 827aba51ab..ac2e662214 100644 --- a/plugins/auth-backend/src/identity/types.ts +++ b/plugins/auth-backend/src/identity/types.ts @@ -52,7 +52,7 @@ export type TokenIssuer = { */ export type StoredKey = { key: AnyJWK; - createdAt: moment.Moment; + createdAt: luxon.DateTime; }; /** From 3600ac3b05a6580b3f539387e467a8c9714443fc Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 4 Feb 2021 11:52:01 +0100 Subject: [PATCH 03/15] Add change set --- .changeset/strange-olives-unite.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/strange-olives-unite.md diff --git a/.changeset/strange-olives-unite.md b/.changeset/strange-olives-unite.md new file mode 100644 index 0000000000..5fba505e46 --- /dev/null +++ b/.changeset/strange-olives-unite.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': minor +--- + +Migrated the package from using moment to luxon. #4278 From bd29ebb6059ec3326d4a948fd01369c7e1bd517c Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 4 Feb 2021 15:02:37 +0100 Subject: [PATCH 04/15] Fix tsc, prettier and import issues --- .../src/identity/DatabaseKeyStore.test.ts | 4 +++- .../auth-backend/src/identity/DatabaseKeyStore.ts | 15 +++++++++++---- plugins/auth-backend/src/identity/TokenFactory.ts | 10 +++++++--- plugins/auth-backend/src/identity/types.ts | 3 ++- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts index 94dd442b44..ec886856fe 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts @@ -50,7 +50,9 @@ describe('DatabaseKeyStore', () => { const { items } = await store.listKeys(); expect(items).toEqual([{ createdAt: expect.anything(), key }]); - expect(Math.abs(items[0].createdAt.diffNow('seconds').seconds)).toBeLessThan(10); + expect( + Math.abs(items[0].createdAt.diffNow('seconds').seconds), + ).toBeLessThan(10); }); it('should remove stored keys', async () => { diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts index cc4838cf9b..a41abffc7b 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts @@ -27,7 +27,7 @@ const migrationsDir = resolvePackagePath( const TABLE = 'signing_keys'; type Row = { - created_at: Date; + created_at: Date; //row.created_at is a string after being returned from the database kid: string; key: string; }; @@ -62,11 +62,18 @@ export class DatabaseKeyStore implements KeyStore { async listKeys(): Promise<{ items: StoredKey[] }> { const rows = await this.database(TABLE).select(); + return { items: rows.map(row => ({ - key: JSON.parse(row.key), - createdAt: DateTime.fromFormat(row.created_at, 'yyyy-MM-dd HH:mm:ss', {zone: 'UTC'}), - })), + key: JSON.parse(row.key), + createdAt: DateTime.fromFormat( + (row.created_at as unknown) as string, + 'yyyy-MM-dd HH:mm:ss', + { + zone: 'UTC', + }, + ), + })), }; } diff --git a/plugins/auth-backend/src/identity/TokenFactory.ts b/plugins/auth-backend/src/identity/TokenFactory.ts index 6874b08789..963251f42b 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.ts @@ -90,7 +90,9 @@ export class TokenFactory implements TokenIssuer { for (const key of keys) { // Allow for a grace period of another full key duration before we remove the keys from the database - const expireAt = key.createdAt.plus({ seconds: 3 * this.keyDurationSeconds }); + const expireAt = key.createdAt.plus({ + seconds: 3 * this.keyDurationSeconds, + }); if (expireAt < DateTime.local()) { expiredKeys.push(key); } else { @@ -117,14 +119,16 @@ export class TokenFactory implements TokenIssuer { private async getKey(): Promise { // Make sure that we only generate one key at a time¨ if (this.privateKeyPromise) { - if (this.keyExpiry > DateTime.local()) { + if (this.keyExpiry && this.keyExpiry > DateTime.local()) { return this.privateKeyPromise; } this.logger.info(`Signing key has expired, generating new key`); delete this.privateKeyPromise; } - this.keyExpiry = DateTime.local().plus({ seconds: this.keyDurationSeconds }); + this.keyExpiry = DateTime.local().plus({ + seconds: this.keyDurationSeconds, + }); const promise = (async () => { // This generates a new signing key to be used to sign tokens until the next key rotation const key = await JWK.generate('EC', 'P-256', { diff --git a/plugins/auth-backend/src/identity/types.ts b/plugins/auth-backend/src/identity/types.ts index ac2e662214..4e3eeb872e 100644 --- a/plugins/auth-backend/src/identity/types.ts +++ b/plugins/auth-backend/src/identity/types.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { DateTime } from 'luxon'; /** Represents any form of serializable JWK */ export interface AnyJWK extends Record { @@ -52,7 +53,7 @@ export type TokenIssuer = { */ export type StoredKey = { key: AnyJWK; - createdAt: luxon.DateTime; + createdAt: DateTime; }; /** From fc2371edeb88fd8d64d070e3bf1a2791bb71c374 Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 4 Feb 2021 15:03:32 +0100 Subject: [PATCH 05/15] Update .changeset/strange-olives-unite.md Co-authored-by: Himanshu Mishra --- .changeset/strange-olives-unite.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/strange-olives-unite.md b/.changeset/strange-olives-unite.md index 5fba505e46..a6b89f3bc4 100644 --- a/.changeset/strange-olives-unite.md +++ b/.changeset/strange-olives-unite.md @@ -2,4 +2,4 @@ '@backstage/plugin-auth-backend': minor --- -Migrated the package from using moment to luxon. #4278 +Migrated the package from using moment to Luxon. #4278 From 190f2358fd2fb3c4f0d8e1f184ac74ca493d8042 Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 4 Feb 2021 15:05:34 +0100 Subject: [PATCH 06/15] Update plugins/auth-backend/src/identity/TokenFactory.ts Co-authored-by: Himanshu Mishra --- plugins/auth-backend/src/identity/TokenFactory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/auth-backend/src/identity/TokenFactory.ts b/plugins/auth-backend/src/identity/TokenFactory.ts index 963251f42b..99ea26a7fb 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.ts @@ -117,7 +117,7 @@ export class TokenFactory implements TokenIssuer { } private async getKey(): Promise { - // Make sure that we only generate one key at a time¨ + // Make sure that we only generate one key at a time if (this.privateKeyPromise) { if (this.keyExpiry && this.keyExpiry > DateTime.local()) { return this.privateKeyPromise; From 2a49b2cc5fa9ebbcd21312230373cc3fc4cd5c1c Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 4 Feb 2021 15:07:48 +0100 Subject: [PATCH 07/15] Change from minor to patch --- .changeset/strange-olives-unite.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/strange-olives-unite.md b/.changeset/strange-olives-unite.md index a6b89f3bc4..7490f6096a 100644 --- a/.changeset/strange-olives-unite.md +++ b/.changeset/strange-olives-unite.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-auth-backend': minor +'@backstage/plugin-auth-backend': patch --- Migrated the package from using moment to Luxon. #4278 From a816fd2f33c524345154edb7f2acc521a363f3b1 Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 4 Feb 2021 15:14:18 +0100 Subject: [PATCH 08/15] Update DatabaseKeyStore.ts --- plugins/auth-backend/src/identity/DatabaseKeyStore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts index a41abffc7b..b789522122 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts @@ -27,7 +27,7 @@ const migrationsDir = resolvePackagePath( const TABLE = 'signing_keys'; type Row = { - created_at: Date; //row.created_at is a string after being returned from the database + created_at: Date; // row.created_at is a string after being returned from the database kid: string; key: string; }; From b3b90acee7a4bf6df07a6880b6a89edb856fa631 Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 4 Feb 2021 16:49:06 +0100 Subject: [PATCH 09/15] Changed to fromSQL --- plugins/auth-backend/src/identity/DatabaseKeyStore.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts index b789522122..53c8bde307 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts @@ -66,9 +66,8 @@ export class DatabaseKeyStore implements KeyStore { return { items: rows.map(row => ({ key: JSON.parse(row.key), - createdAt: DateTime.fromFormat( + createdAt: DateTime.fromSQL( (row.created_at as unknown) as string, - 'yyyy-MM-dd HH:mm:ss', { zone: 'UTC', }, From f6e56e6cfb09c08f2bccf1765d33f2afa1f74a73 Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 4 Feb 2021 17:55:00 +0100 Subject: [PATCH 10/15] Fix prettier formatting --- plugins/auth-backend/src/identity/DatabaseKeyStore.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts index 53c8bde307..6aad9af30f 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts @@ -66,12 +66,9 @@ export class DatabaseKeyStore implements KeyStore { return { items: rows.map(row => ({ key: JSON.parse(row.key), - createdAt: DateTime.fromSQL( - (row.created_at as unknown) as string, - { - zone: 'UTC', - }, - ), + createdAt: DateTime.fromSQL((row.created_at as unknown) as string, { + zone: 'UTC', + }), })), }; } From 529c8501b822aa14ddef4d44a75cf3f2f75f900d Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Mon, 8 Feb 2021 09:51:57 +0100 Subject: [PATCH 11/15] Create utc DateTime object directly --- plugins/auth-backend/src/identity/MemoryKeyStore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/auth-backend/src/identity/MemoryKeyStore.ts b/plugins/auth-backend/src/identity/MemoryKeyStore.ts index 0903f6987d..ecb31d9998 100644 --- a/plugins/auth-backend/src/identity/MemoryKeyStore.ts +++ b/plugins/auth-backend/src/identity/MemoryKeyStore.ts @@ -25,7 +25,7 @@ export class MemoryKeyStore implements KeyStore { async addKey(key: AnyJWK): Promise { this.keys.set(key.kid, { - createdAt: DateTime.local().toUTC(), + createdAt: DateTime.utc(), key: JSON.stringify(key), }); } From 636c70ac9199cedbc75801f2270b7a96950423b9 Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 11 Feb 2021 10:16:34 +0100 Subject: [PATCH 12/15] Use JS Date instead of Datetime --- .../src/identity/DatabaseKeyStore.test.ts | 3 ++- .../src/identity/DatabaseKeyStore.ts | 16 +++++++++++++--- .../auth-backend/src/identity/MemoryKeyStore.ts | 4 ++-- .../auth-backend/src/identity/TokenFactory.ts | 10 +++++----- plugins/auth-backend/src/identity/types.ts | 3 +-- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts index ec886856fe..3c61e20c1c 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts @@ -16,6 +16,7 @@ import Knex from 'knex'; import { DatabaseKeyStore } from './DatabaseKeyStore'; +import { DateTime } from 'luxon' function createDB() { const knex = Knex({ @@ -51,7 +52,7 @@ describe('DatabaseKeyStore', () => { const { items } = await store.listKeys(); expect(items).toEqual([{ createdAt: expect.anything(), key }]); expect( - Math.abs(items[0].createdAt.diffNow('seconds').seconds), + Math.abs(DateTime.fromJSDate(items[0].createdAt).diffNow('seconds').seconds), ).toBeLessThan(10); }); diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts index 6aad9af30f..6ffb840e6d 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts @@ -66,9 +66,7 @@ export class DatabaseKeyStore implements KeyStore { return { items: rows.map(row => ({ key: JSON.parse(row.key), - createdAt: DateTime.fromSQL((row.created_at as unknown) as string, { - zone: 'UTC', - }), + createdAt: parseDate(row.created_at), })), }; } @@ -77,3 +75,15 @@ export class DatabaseKeyStore implements KeyStore { await this.database(TABLE).delete().whereIn('kid', kids); } } + +const parseDate = (date: string | Date) => { + const parsedDate = typeof date === 'string' ? DateTime.fromSQL(date, {locale: 'UTC'}) : DateTime.fromJSDate(date) + + if (!parsedDate.isValid) { + throw new Error( + `Failed to parse date, reason: ${parsedDate.invalidReason}, explanation: ${parsedDate.invalidExplanation}`, + ); + } + + return parsedDate.toJSDate() +} \ No newline at end of file diff --git a/plugins/auth-backend/src/identity/MemoryKeyStore.ts b/plugins/auth-backend/src/identity/MemoryKeyStore.ts index ecb31d9998..efb81cd264 100644 --- a/plugins/auth-backend/src/identity/MemoryKeyStore.ts +++ b/plugins/auth-backend/src/identity/MemoryKeyStore.ts @@ -20,12 +20,12 @@ import { DateTime } from 'luxon'; export class MemoryKeyStore implements KeyStore { private readonly keys = new Map< string, - { createdAt: DateTime; key: string } + { createdAt: Date; key: string } >(); async addKey(key: AnyJWK): Promise { this.keys.set(key.kid, { - createdAt: DateTime.utc(), + createdAt: DateTime.utc().toJSDate(), key: JSON.stringify(key), }); } diff --git a/plugins/auth-backend/src/identity/TokenFactory.ts b/plugins/auth-backend/src/identity/TokenFactory.ts index 99ea26a7fb..4169484191 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.ts @@ -52,7 +52,7 @@ export class TokenFactory implements TokenIssuer { private readonly keyStore: KeyStore; private readonly keyDurationSeconds: number; - private keyExpiry?: DateTime; + private keyExpiry?: Date; private privateKeyPromise?: Promise; constructor(options: Options) { @@ -90,7 +90,7 @@ export class TokenFactory implements TokenIssuer { for (const key of keys) { // Allow for a grace period of another full key duration before we remove the keys from the database - const expireAt = key.createdAt.plus({ + const expireAt = DateTime.fromJSDate(key.createdAt).plus({ seconds: 3 * this.keyDurationSeconds, }); if (expireAt < DateTime.local()) { @@ -119,16 +119,16 @@ export class TokenFactory implements TokenIssuer { private async getKey(): Promise { // Make sure that we only generate one key at a time if (this.privateKeyPromise) { - if (this.keyExpiry && this.keyExpiry > DateTime.local()) { + if (this.keyExpiry && DateTime.fromJSDate(this.keyExpiry) > DateTime.local()) { return this.privateKeyPromise; } this.logger.info(`Signing key has expired, generating new key`); delete this.privateKeyPromise; } - this.keyExpiry = DateTime.local().plus({ + this.keyExpiry = DateTime.utc().plus({ seconds: this.keyDurationSeconds, - }); + }).toJSDate(); const promise = (async () => { // This generates a new signing key to be used to sign tokens until the next key rotation const key = await JWK.generate('EC', 'P-256', { diff --git a/plugins/auth-backend/src/identity/types.ts b/plugins/auth-backend/src/identity/types.ts index 4e3eeb872e..6e984d41cc 100644 --- a/plugins/auth-backend/src/identity/types.ts +++ b/plugins/auth-backend/src/identity/types.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { DateTime } from 'luxon'; /** Represents any form of serializable JWK */ export interface AnyJWK extends Record { @@ -53,7 +52,7 @@ export type TokenIssuer = { */ export type StoredKey = { key: AnyJWK; - createdAt: DateTime; + createdAt: Date; }; /** From a107018191ceb057fb3080a52db6ea5bcbac7939 Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 11 Feb 2021 10:22:34 +0100 Subject: [PATCH 13/15] Add line --- plugins/auth-backend/src/identity/DatabaseKeyStore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts index 6ffb840e6d..2c3cf41259 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts @@ -86,4 +86,4 @@ const parseDate = (date: string | Date) => { } return parsedDate.toJSDate() -} \ No newline at end of file +} From 01700ceccd495ea3becbe3595eece6398af204c0 Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 11 Feb 2021 10:30:48 +0100 Subject: [PATCH 14/15] Prettier fix --- .../src/identity/DatabaseKeyStore.test.ts | 6 ++++-- .../auth-backend/src/identity/DatabaseKeyStore.ts | 9 ++++++--- plugins/auth-backend/src/identity/MemoryKeyStore.ts | 5 +---- plugins/auth-backend/src/identity/TokenFactory.ts | 13 +++++++++---- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts index 3c61e20c1c..8896a0d158 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.test.ts @@ -16,7 +16,7 @@ import Knex from 'knex'; import { DatabaseKeyStore } from './DatabaseKeyStore'; -import { DateTime } from 'luxon' +import { DateTime } from 'luxon'; function createDB() { const knex = Knex({ @@ -52,7 +52,9 @@ describe('DatabaseKeyStore', () => { const { items } = await store.listKeys(); expect(items).toEqual([{ createdAt: expect.anything(), key }]); expect( - Math.abs(DateTime.fromJSDate(items[0].createdAt).diffNow('seconds').seconds), + Math.abs( + DateTime.fromJSDate(items[0].createdAt).diffNow('seconds').seconds, + ), ).toBeLessThan(10); }); diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts index 2c3cf41259..6183c2ed66 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts @@ -77,7 +77,10 @@ export class DatabaseKeyStore implements KeyStore { } const parseDate = (date: string | Date) => { - const parsedDate = typeof date === 'string' ? DateTime.fromSQL(date, {locale: 'UTC'}) : DateTime.fromJSDate(date) + const parsedDate = + typeof date === 'string' + ? DateTime.fromSQL(date, { locale: 'UTC' }) + : DateTime.fromJSDate(date); if (!parsedDate.isValid) { throw new Error( @@ -85,5 +88,5 @@ const parseDate = (date: string | Date) => { ); } - return parsedDate.toJSDate() -} + return parsedDate.toJSDate(); +}; diff --git a/plugins/auth-backend/src/identity/MemoryKeyStore.ts b/plugins/auth-backend/src/identity/MemoryKeyStore.ts index efb81cd264..3dc1d777c9 100644 --- a/plugins/auth-backend/src/identity/MemoryKeyStore.ts +++ b/plugins/auth-backend/src/identity/MemoryKeyStore.ts @@ -18,10 +18,7 @@ import { KeyStore, AnyJWK, StoredKey } from './types'; import { DateTime } from 'luxon'; export class MemoryKeyStore implements KeyStore { - private readonly keys = new Map< - string, - { createdAt: Date; key: string } - >(); + private readonly keys = new Map(); async addKey(key: AnyJWK): Promise { this.keys.set(key.kid, { diff --git a/plugins/auth-backend/src/identity/TokenFactory.ts b/plugins/auth-backend/src/identity/TokenFactory.ts index 4169484191..1c6192d5c5 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.ts @@ -119,16 +119,21 @@ export class TokenFactory implements TokenIssuer { private async getKey(): Promise { // Make sure that we only generate one key at a time if (this.privateKeyPromise) { - if (this.keyExpiry && DateTime.fromJSDate(this.keyExpiry) > DateTime.local()) { + if ( + this.keyExpiry && + DateTime.fromJSDate(this.keyExpiry) > DateTime.local() + ) { return this.privateKeyPromise; } this.logger.info(`Signing key has expired, generating new key`); delete this.privateKeyPromise; } - this.keyExpiry = DateTime.utc().plus({ - seconds: this.keyDurationSeconds, - }).toJSDate(); + this.keyExpiry = DateTime.utc() + .plus({ + seconds: this.keyDurationSeconds, + }) + .toJSDate(); const promise = (async () => { // This generates a new signing key to be used to sign tokens until the next key rotation const key = await JWK.generate('EC', 'P-256', { From 072a96051877542391f27f940e3b70a90cdd9cdf Mon Sep 17 00:00:00 2001 From: Nils Streijffert Date: Thu, 11 Feb 2021 10:37:58 +0100 Subject: [PATCH 15/15] Move parseDate function --- .../src/identity/DatabaseKeyStore.ts | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts index 6183c2ed66..e53102e333 100644 --- a/plugins/auth-backend/src/identity/DatabaseKeyStore.ts +++ b/plugins/auth-backend/src/identity/DatabaseKeyStore.ts @@ -36,6 +36,21 @@ type Options = { database: Knex; }; +const parseDate = (date: string | Date) => { + const parsedDate = + typeof date === 'string' + ? DateTime.fromSQL(date, { locale: 'UTC' }) + : DateTime.fromJSDate(date); + + if (!parsedDate.isValid) { + throw new Error( + `Failed to parse date, reason: ${parsedDate.invalidReason}, explanation: ${parsedDate.invalidExplanation}`, + ); + } + + return parsedDate.toJSDate(); +}; + export class DatabaseKeyStore implements KeyStore { static async create(options: Options): Promise { const { database } = options; @@ -75,18 +90,3 @@ export class DatabaseKeyStore implements KeyStore { await this.database(TABLE).delete().whereIn('kid', kids); } } - -const parseDate = (date: string | Date) => { - const parsedDate = - typeof date === 'string' - ? DateTime.fromSQL(date, { locale: 'UTC' }) - : DateTime.fromJSDate(date); - - if (!parsedDate.isValid) { - throw new Error( - `Failed to parse date, reason: ${parsedDate.invalidReason}, explanation: ${parsedDate.invalidExplanation}`, - ); - } - - return parsedDate.toJSDate(); -};