diff --git a/packages/shared/src/__tests__/api.test.ts b/packages/shared/src/__tests__/api.test.ts index b58490aad..004aaf4c7 100644 --- a/packages/shared/src/__tests__/api.test.ts +++ b/packages/shared/src/__tests__/api.test.ts @@ -3,7 +3,7 @@ import { afterEach, beforeEach, describe, it } from 'node:test'; import { decodeTime, encodeTime, ulid } from 'ulid'; -import { getApiKey, OneDayMs, truncateApiKey } from '../api.js'; +import { getApiKey, isValidApiKey, OneDayMs, truncateApiKey } from '../api.js'; declare const global: { localStorage?: { getItem: (a: string) => string | null; setItem: (k: string, v: string) => void }; @@ -38,6 +38,11 @@ describe('ApiKey', () => { assert.equal(getApiKey(), newKey); }); + it('should allow api keys that are very old', () => { + const fakeUlid = 'c' + encodeTime(new Date('2020-01-01T00:00:00.000Z').getTime(), 10) + ulid().slice(10); + assert.deepEqual(isValidApiKey(fakeUlid), { valid: true, key: fakeUlid }); + }); + it('should generate new keys after they expire', (t) => { const setSpy = t.mock.method(localStorage, 'setItem'); // Generate a key that is about 31 days old diff --git a/packages/shared/src/api.ts b/packages/shared/src/api.ts index cfb7b63d0..c3ffba447 100644 --- a/packages/shared/src/api.ts +++ b/packages/shared/src/api.ts @@ -4,7 +4,7 @@ const hasLocalStorage = (): boolean => typeof localStorage !== 'undefined'; export const OneDayMs = 24 * 60 * 60 * 1000; /** Generate a new api key for the user every 30 days */ const ApiKeyExpireMs = 30 * OneDayMs; -const ApiKeyMaxAgeMs = 91 * OneDayMs; +export const ApiKeyMaxAgeMs = 91 * OneDayMs; function newApiKey(): string { const newKey = 'c' + ulid().toLowerCase(); @@ -46,10 +46,11 @@ export function isValidApiKey(apiKey?: string | null): ApiKeyStatus { if (!apiKey.startsWith('c') && !apiKey.startsWith('d')) return { valid: false, message: 'malformed' }; const ulidId = apiKey.slice(1).toUpperCase(); try { - const ulidTime = decodeTime(ulidId); + decodeTime(ulidId); // validate the key looks valid if (apiKey.startsWith('d')) return { valid: true, key: apiKey }; - if (Date.now() - ulidTime > ApiKeyMaxAgeMs) return { valid: false, message: 'expired' }; + // Re-enable to disable older api keys + // if (Date.now() - ulidTime > ApiKeyMaxAgeMs) return { valid: false, message: 'expired' }; } catch (e) { return { valid: false, message: 'malformed' }; }