token image , api key header

This commit is contained in:
2026-04-11 14:22:45 +07:00
parent 6b7655aa16
commit 055ee69a71
9 changed files with 73 additions and 13 deletions

55
utils/signedUrl.js Normal file
View File

@@ -0,0 +1,55 @@
const crypto = require('crypto');
const SECRET = process.env.FILE_SIGN_SECRET || process.env.SESSION_SECRET || 'file-sign-secret';
const EXPIRY_SECONDS = 15 * 60; // 15 minutes
/**
* Generate a signed URL for a protected file
* @param {string} baseUrl - e.g. "https://host"
* @param {string} filename - basename of the file
* @returns {string} full signed URL
*/
function generateSignedUrl(baseUrl, filename) {
const expires = Math.floor(Date.now() / 1000) + EXPIRY_SECONDS;
const payload = `${filename}:${expires}`;
const token = crypto
.createHmac('sha256', SECRET)
.update(payload)
.digest('base64url');
return `${baseUrl}/secure-files/${encodeURIComponent(filename)}?token=${token}&expires=${expires}`;
}
/**
* Verify a signed URL token
* @param {string} filename
* @param {string} token
* @param {number} expires - unix timestamp
* @returns {{ valid: boolean, reason?: string }}
*/
function verifySignedUrl(filename, token, expires) {
const now = Math.floor(Date.now() / 1000);
if (!token || !expires) {
return { valid: false, reason: 'Missing token or expires' };
}
if (now > Number(expires)) {
return { valid: false, reason: 'URL has expired' };
}
const payload = `${filename}:${expires}`;
const expected = crypto
.createHmac('sha256', SECRET)
.update(payload)
.digest('base64url');
const valid = crypto.timingSafeEqual(
Buffer.from(token),
Buffer.from(expected)
);
return valid ? { valid: true } : { valid: false, reason: 'Invalid token' };
}
module.exports = { generateSignedUrl, verifySignedUrl };