41 lines
1.2 KiB
TypeScript
41 lines
1.2 KiB
TypeScript
import { createHmac, randomBytes } from "node:crypto";
|
|
|
|
export const ACCESS_KEY_PREFIX = "ydr_live_";
|
|
|
|
export function generateAccessKey() {
|
|
const visibleId = randomBytes(6).toString("hex");
|
|
const secret = randomBytes(32).toString("base64url");
|
|
const token = `${ACCESS_KEY_PREFIX}${visibleId}_${secret}`;
|
|
|
|
return {
|
|
token,
|
|
tokenPrefix: `${ACCESS_KEY_PREFIX}${visibleId}`,
|
|
};
|
|
}
|
|
|
|
export function hashAccessKey(token: string, pepper: string) {
|
|
const normalizedToken = String(token || "").trim();
|
|
const normalizedPepper = String(pepper || "").trim();
|
|
if (!normalizedToken || !normalizedPepper) {
|
|
throw new Error("Access Key token and pepper are required");
|
|
}
|
|
|
|
return createHmac("sha256", normalizedPepper)
|
|
.update(normalizedToken)
|
|
.digest("hex");
|
|
}
|
|
|
|
export function getAccessKeyPrefix(token: string) {
|
|
const normalized = String(token || "").trim();
|
|
const match = /^(ydr_live_[a-f0-9]{12})_[A-Za-z0-9_-]{20,}$/.exec(
|
|
normalized
|
|
);
|
|
return match?.[1] || null;
|
|
}
|
|
|
|
export function parseBearerAccessKey(header: string | null | undefined) {
|
|
const match = /^Bearer\s+(.+)$/i.exec(String(header || "").trim());
|
|
const token = match?.[1]?.trim() || "";
|
|
return getAccessKeyPrefix(token) ? token : null;
|
|
}
|