|
| 1 | +// Scripted REST API Resource Script: Webhook receiver with HMAC validation |
| 2 | +(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) { |
| 3 | + var SHARED_SECRET = gs.getProperty('x_acme.webhook.secret', ''); |
| 4 | + var TARGET_TABLE = 'x_acme_inbound_webhook'; // replace with your table |
| 5 | + |
| 6 | + try { |
| 7 | + var body = request.body && request.body.data ? request.body.data : ''; |
| 8 | + var signature = request.getHeader('X-Signature') || ''; // hex HMAC hash |
| 9 | + |
| 10 | + if (!SHARED_SECRET) { |
| 11 | + response.setStatus(500); |
| 12 | + response.setBody({ error: 'Server not configured' }); |
| 13 | + return; |
| 14 | + } |
| 15 | + if (!signature || !body) { |
| 16 | + response.setStatus(400); |
| 17 | + response.setBody({ error: 'Missing signature or body' }); |
| 18 | + return; |
| 19 | + } |
| 20 | + |
| 21 | + var util = new HmacUtils(); |
| 22 | + var expected = util.hmacSha256Hex(SHARED_SECRET, body); |
| 23 | + |
| 24 | + if (!util.constantTimeEquals(expected, signature)) { |
| 25 | + response.setStatus(401); |
| 26 | + response.setBody({ error: 'Invalid signature' }); |
| 27 | + return; |
| 28 | + } |
| 29 | + |
| 30 | + // Valid payload: insert a record for processing |
| 31 | + var rec = new GlideRecord(TARGET_TABLE); |
| 32 | + rec.initialize(); |
| 33 | + rec.payload = body; |
| 34 | + rec.signature = signature; |
| 35 | + rec.insert(); |
| 36 | + |
| 37 | + response.setStatus(200); |
| 38 | + response.setBody({ ok: true }); |
| 39 | + } catch (e) { |
| 40 | + response.setStatus(500); |
| 41 | + response.setBody({ error: String(e) }); |
| 42 | + } |
| 43 | +})(request, response); |
0 commit comments