feat: add shared auth proof helpers

This commit is contained in:
nav
2026-04-08 22:04:37 +00:00
parent fbe1457ab6
commit 7e69a08443
2 changed files with 74 additions and 0 deletions

73
src/auth.ts Normal file
View File

@@ -0,0 +1,73 @@
import type { AuthRequestPayload } from "./types.js";
export const AUTH_NONCE_LENGTH = 24;
export const AUTH_MAX_TIMESTAMP_DRIFT_SECONDS = 10;
export const AUTH_MAX_ATTEMPTS_PER_WINDOW = 10;
export const AUTH_ATTEMPT_WINDOW_SECONDS = 10;
export const AUTH_RECENT_NONCE_WINDOW_SIZE = 10;
export interface AuthProofMaterial {
secret: string;
nonce: string;
timestamp: number;
}
export function createAuthProofMaterial(input: AuthProofMaterial): AuthProofMaterial {
return {
secret: input.secret,
nonce: input.nonce,
timestamp: input.timestamp
};
}
export function serializeAuthProofMaterial(input: AuthProofMaterial): string {
const material = createAuthProofMaterial(input);
return JSON.stringify({
secret: material.secret,
nonce: material.nonce,
timestamp: material.timestamp
});
}
export function isValidAuthNonce(nonce: string): boolean {
return /^[A-Za-z0-9_-]{24}$/.test(nonce);
}
export function isTimestampFresh(
proofTimestamp: number,
now: number,
maxDriftSeconds: number = AUTH_MAX_TIMESTAMP_DRIFT_SECONDS
): { ok: true } | { ok: false; reason: "stale_timestamp" | "future_timestamp" } {
const drift = proofTimestamp - now;
if (Math.abs(drift) < maxDriftSeconds) {
return { ok: true };
}
return {
ok: false,
reason: drift < 0 ? "stale_timestamp" : "future_timestamp"
};
}
export function createAuthRequestSigningInput(input: {
secret: string;
nonce: string;
proofTimestamp: number;
}): string {
return serializeAuthProofMaterial({
secret: input.secret,
nonce: input.nonce,
timestamp: input.proofTimestamp
});
}
export function extractAuthRequestSigningInput(
payload: Pick<AuthRequestPayload, "nonce" | "proofTimestamp">,
secret: string
): string {
return createAuthRequestSigningInput({
secret,
nonce: payload.nonce,
proofTimestamp: payload.proofTimestamp
});
}

View File

@@ -1,3 +1,4 @@
export * from "./types.js"; export * from "./types.js";
export * from "./codec.js"; export * from "./codec.js";
export * from "./errors.js"; export * from "./errors.js";
export * from "./auth.js";