Spaces:
Paused
Paused
File size: 1,422 Bytes
020ed68 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | import crypto from 'crypto'
export function verifyHMAC(
rawBody: Buffer,
timestamp: string,
signature: string,
clientSecret: string
): boolean {
const now = Math.floor(Date.now() / 1000)
const ts = parseInt(timestamp, 10)
if (isNaN(ts) || Math.abs(now - ts) > 300) return false
const msg = Buffer.concat([Buffer.from(timestamp), Buffer.from('.'), rawBody])
const expected = crypto.createHmac('sha256', clientSecret).update(msg).digest('hex')
try {
return crypto.timingSafeEqual(Buffer.from(signature, 'hex'), Buffer.from(expected, 'hex'))
} catch {
return false
}
}
export function checkAuth(
rawBody: Buffer,
headers: Headers
): { ok: boolean; error?: string } {
const clientId = process.env.REPORTING_CLIENT_ID
const clientSecret = process.env.REPORTING_CLIENT_SECRET
// If credentials not configured, skip auth (dev mode)
if (!clientId || !clientSecret) return { ok: true }
const reqClientId = headers.get('x-client-id')
const timestamp = headers.get('x-timestamp')
const signature = headers.get('x-signature')
if (!reqClientId || !timestamp || !signature) {
return { ok: false, error: 'Missing auth headers' }
}
if (reqClientId !== clientId) {
return { ok: false, error: 'Invalid client ID' }
}
if (!verifyHMAC(rawBody, timestamp, signature, clientSecret)) {
return { ok: false, error: 'Invalid signature' }
}
return { ok: true }
}
|