aboutsummaryrefslogtreecommitdiffstats
path: root/packages/shared/signedTokens.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/shared/signedTokens.ts')
-rw-r--r--packages/shared/signedTokens.ts42
1 files changed, 38 insertions, 4 deletions
diff --git a/packages/shared/signedTokens.ts b/packages/shared/signedTokens.ts
index b5e27f3e..14a26f60 100644
--- a/packages/shared/signedTokens.ts
+++ b/packages/shared/signedTokens.ts
@@ -1,8 +1,6 @@
import crypto from "node:crypto";
import { z } from "zod";
-import serverConfig from "./config";
-
const zTokenPayload = z.object({
payload: z.unknown(),
expiresAt: z.number(),
@@ -13,10 +11,45 @@ const zSignedTokenPayload = z.object({
signature: z.string(),
});
+/**
+ * Returns the expiry date aligned to the specified interval.
+ * If the time left until the next interval is less than the grace period,
+ * it skips to the following interval.
+ *
+ * @param now - The current date and time (defaults to new Date()).
+ * @param intervalSeconds - The interval in seconds (e.g., 1800 for 30 mins).
+ * @param gracePeriodSeconds - The grace period in seconds.
+ * @returns The calculated expiry Date.
+ */
+export function getAlignedExpiry(
+ intervalSeconds: number,
+ gracePeriodSeconds: number,
+ now: Date = new Date(),
+): number {
+ const ms = now.getTime();
+ const intervalMs = intervalSeconds * 1000;
+
+ // Find the next interval
+ const nextIntervalTime =
+ Math.floor(ms / intervalMs) * intervalMs + intervalMs;
+
+ // Time left until the next interval
+ const timeLeft = nextIntervalTime - ms;
+
+ // Decide which interval to use
+ const finalIntervalTime =
+ timeLeft < gracePeriodSeconds * 1000
+ ? nextIntervalTime + intervalMs
+ : nextIntervalTime;
+
+ return finalIntervalTime;
+}
+
export type SignedTokenPayload = z.infer<typeof zSignedTokenPayload>;
export function createSignedToken(
payload: unknown,
+ secret: string,
expiryEpoch?: number,
): string {
const expiresAt = expiryEpoch ?? Date.now() + 5 * 60 * 1000; // 5 minutes from now
@@ -28,7 +61,7 @@ export function createSignedToken(
const payloadString = JSON.stringify(toBeSigned);
const signature = crypto
- .createHmac("sha256", serverConfig.signingSecret())
+ .createHmac("sha256", secret)
.update(payloadString)
.digest("hex");
@@ -42,6 +75,7 @@ export function createSignedToken(
export function verifySignedToken<T>(
token: string,
+ secret: string,
schema: z.ZodSchema<T>,
): T | null {
try {
@@ -52,7 +86,7 @@ export function verifySignedToken<T>(
// Verify signature
const expectedSignature = crypto
- .createHmac("sha256", serverConfig.signingSecret())
+ .createHmac("sha256", secret)
.update(JSON.stringify(payload))
.digest("hex");