Files
KalBot/lib/auth.js

58 lines
1.8 KiB
JavaScript

/**
* Edge-compatible session signer/verifier using Web Crypto API.
*/
async function getSessionKey() {
const secret = process.env.CAPTCHA_SECRET || 'dev_secret_meow';
const encoder = new TextEncoder();
return await crypto.subtle.importKey(
'raw',
encoder.encode(secret),
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign', 'verify']
);
}
export async function signSession() {
const expires = Date.now() + 24 * 60 * 60 * 1000; // 24 hours validity
const data = `admin.${expires}`;
const encoder = new TextEncoder();
const key = await getSessionKey();
const signatureBuffer = await crypto.subtle.sign('HMAC', key, encoder.encode(data));
const signatureArray = Array.from(new Uint8Array(signatureBuffer));
const signatureHex = signatureArray.map(b => b.toString(16).padStart(2, '0')).join('');
return `${data}.${signatureHex}`;
}
export async function verifySession(token) {
if (!token) return false;
const parts = token.split('.');
if (parts.length !== 3) return false;
const [user, expires, signatureHex] = parts;
if (user !== 'admin') return false;
// Check if token expired
if (Date.now() > parseInt(expires, 10)) return false;
const data = `${user}.${expires}`;
const encoder = new TextEncoder();
const key = await getSessionKey();
// Convert hex string back to Uint8Array
const signatureBytes = new Uint8Array(
signatureHex.match(/.{1,2}/g).map(byte => parseInt(byte, 16))
);
try {
// Verify the HMAC signature ensures the token hasn't been tampered with
return await crypto.subtle.verify('HMAC', key, signatureBytes, encoder.encode(data));
} catch {
return false;
}
}