'use strict'; class Jwk { #kid; // Key ID #value; // PEM-encoded public key #expirationTime; // Expiration time in milliseconds #createdAt; // UNIX timestamp of object construction constructor(kid, value, expirationTime = Infinity) { if(!kid) { throw new Error("JWK must have a non-empty kid.") } if(!value) { throw new Error("JWK must have a non-empty value.") } if(expirationTime < 0) { throw new Error("JWK must have an expiration time (ms) > 0.") } this.#kid = kid; this.#value = value; this.#expirationTime = expirationTime; this.#createdAt = Date.now(); } get kid() {return this.#kid;} get value() {return this.#value;} get expirationTime() {return this.#expirationTime;} get createdAt() {return this.#createdAt;} /** Calculates the remaining time until the entry is discarded. * @returns time from until expiration or 0 if already expired */ get remainingTime() { const elapsedTime = Date.now() - this.createdAt; return Math.max(0, this.#expirationTime - elapsedTime); } // Checks if the entry is expired. get expired() { return this.remainingTime <= 0; } /** Checks if the Jwk is considered stale given the refresh period. Stale Jwks should be refreshed but may still be used until expiration. * @param refreshPeriod time period (in ms) before expiration time in which the Jwk should count as stale (but not yet as expired) * @returns true if the JWK is already expired or will expire within the given refresh period. */ stale(refreshPeriod) { return this.expired || this.remainingTime < refreshPeriod; } } module.exports = Jwk;