Spaces:
Paused
Paused
Download lib/auth.ts from imkrish/ig-costing: direct link, hf CLI and curl.
- Browser
- Download file 1.42 kB
-
https://huggingface.co/spaces/imkrish/ig-costing/resolve/main/lib/auth.ts
- Command line
-
hf download hf://spaces/imkrish/ig-costing/lib/auth.ts
-
curl -L -o auth.ts https://huggingface.co/spaces/imkrish/ig-costing/resolve/main/lib/auth.ts
1.42 kB
| 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 } | |
| } | |