refactor(jwt): improve key rotation logic and test cases for cooldown handling

This commit is contained in:
Bereket Engida
2025-11-29 22:47:02 -08:00
parent 2082671c36
commit 7c5d0c2cf3
2 changed files with 11 additions and 18 deletions
@@ -35,8 +35,8 @@ describe("jwt rotation", async () => {
expect(storage.length).toBe(1);
const firstKey = storage[0];
// Advance time past rotation interval
vi.advanceTimersByTime(1100);
// Advance time past rotation interval (and cooldown)
vi.advanceTimersByTime(5 * 60 * 1000 + 100);
// Second key creation (should rotate)
await auth.api.signJWT({
@@ -83,8 +83,8 @@ describe("jwt rotation", async () => {
// Advance time past rotation interval but within grace period
vi.advanceTimersByTime(1100);
// Trigger rotation by signing
await auth.api.signJWT({ body: { payload: { sub: "user1" } } });
// Trigger rotation (override cooldown to allow rotation)
await auth.api.rotateKey({ body: { cooldown: 500 } });
expect(storage.length).toBe(2);
// Check JWKS endpoint
@@ -131,8 +131,8 @@ it("should respect cooldown period and prevent rapid rotation", async () => {
await auth.api.signJWT({ body: { payload: { sub: "user1" } } });
expect(storage.length).toBe(1);
// Advance time past rotation interval
vi.advanceTimersByTime(1100);
// Advance time past rotation interval (and cooldown)
vi.advanceTimersByTime(5 * 60 * 1000 + 100);
// Trigger rotation
await auth.api.signJWT({ body: { payload: { sub: "user1" } } });
+5 -12
View File
@@ -177,11 +177,11 @@ export async function createJwk(
/**
* Rotates the JWT signing key if needed.
*
*
* Rotation occurs when:
* - No key exists, OR
* - Latest key is expired AND was created more than the cooldown period ago
*
*
* @param ctx - The endpoint context
* @param options - JWT plugin options
* @param config - Rotation configuration
@@ -210,22 +210,15 @@ export async function rotateJwk(
const ROTATION_COOLDOWN = config?.cooldown ?? 5 * 60 * 1000; // 5 minutes default
const now = Date.now();
let shouldRotate = false;
if (config?.force) {
shouldRotate = true;
} else if (!latestKey) {
shouldRotate = true;
} else if (latestKey.expiresAt && latestKey.expiresAt < new Date()) {
const wasCreatedAfterExpiration = latestKey.createdAt.getTime() > latestKey.expiresAt.getTime();
if (wasCreatedAfterExpiration) {
const keyAge = now - latestKey.createdAt.getTime();
shouldRotate = keyAge >= ROTATION_COOLDOWN;
} else {
shouldRotate = true;
}
shouldRotate = now - latestKey.createdAt.getTime() >= ROTATION_COOLDOWN;
}
if (shouldRotate) {