Files
modstagram-back/utils/metaSignedRequest.js
payacom 3f416a7a60 full
2026-08-31 20:45:41 +03:30

44 lines
1.4 KiB
JavaScript

const crypto = require('crypto')
function base64UrlDecode (input) {
const normalized = String(input).replace(/-/g, '+').replace(/_/g, '/')
const padded = normalized + '='.repeat((4 - (normalized.length % 4)) % 4)
return Buffer.from(padded, 'base64')
}
/**
* Verifies + decodes a Meta `signed_request` (used by the Instagram deauthorize
* and data-deletion callbacks). Returns the decoded payload, or null if the
* signature doesn't match / the value is malformed — callers must treat null
* as "reject the request", never fall back to trusting the unverified payload.
*/
function parseSignedRequest (signedRequest, appSecret) {
if (!signedRequest || typeof signedRequest !== 'string' || !appSecret) return null
const parts = signedRequest.split('.')
if (parts.length !== 2) return null
const [encodedSig, encodedPayload] = parts
let providedSig
try {
providedSig = base64UrlDecode(encodedSig)
} catch {
return null
}
const expectedSig = crypto.createHmac('sha256', appSecret).update(encodedPayload).digest()
if (providedSig.length !== expectedSig.length || !crypto.timingSafeEqual(providedSig, expectedSig)) {
return null
}
try {
const data = JSON.parse(base64UrlDecode(encodedPayload).toString('utf8'))
if (data.algorithm !== 'HMAC-SHA256') return null
return data
} catch {
return null
}
}
module.exports = { parseSignedRequest }