# JFrog Webhooks

JFrog platform webhooks notify your app when something happens in Artifactory, such as an
artifact deployed, a Docker tag pushed or a build uploaded. In the default **token mode**,
JFrog sends the secret token you configured as-is in the `X-JFrog-Event-Auth` header. There
is no payload signature to compute: you authenticate the request by comparing that header to
your secret.

## When to Use This Skill

* How do I receive JFrog Artifactory webhooks?
* How do I verify the `X-JFrog-Event-Auth` header on a JFrog webhook?
* How do I handle `artifact` `deployed` / `moved` or `docker` `pushed` events?
* Why does my JFrog webhook endpoint get 401s or fail the Test button?
* Does JFrog sign webhook payloads? (Only in signing mode, which this skill doesn't cover.)

## Verification (core)

```javascript
const crypto = require('crypto');

// Hash both sides: equal-length buffers, so timingSafeEqual never throws.
function safeEqual(a, b) {
  const ha = crypto.createHash('sha256').update(String(a)).digest();
  const hb = crypto.createHash('sha256').update(String(b)).digest();
  return crypto.timingSafeEqual(ha, hb);
}

function verifyJfrogRequest(headers, secret) {
  if (!secret) return false;                    // never accept when unconfigured
  const token = headers['x-jfrog-event-auth'];  // the secret token, sent as-is
  return Boolean(token) && safeEqual(token, secret);
}

```

Python: `hmac.compare_digest(received.encode(), secret.encode())`. Return `401` when this
fails, `400` for a body that isn't a JSON object, and `200` once handled.

**Signing mode is not covered.** The webhook form also has a "use secret for signing" option
(`use_secret_for_signing=true`) that signs the payload with HMAC-SHA256 instead of sending the
secret. JFrog's docs don't say which header carries that signature, so this skill only
supports token mode (the default, signing off). See
[references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/jfrog-webhooks/references/verification.md).

> **For complete handlers with tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/jfrog-webhooks/examples/express/),
> [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/jfrog-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/jfrog-webhooks/examples/fastapi/). The Express
> example reads the body with `express.raw({ type: '*/*' })` so any content type is accepted.

## Event Types

Every payload has a `domain` and an `event_type`; dispatch on both.

| domain | event_type | Triggered When |
| --- | --- | --- |
| `artifact` | `deployed` | An artifact is deployed to a repository |
| `artifact` | `deleted` | An artifact is deleted from a repository |
| `artifact` | `moved` | An artifact is moved to another repository |
| `docker` | `pushed` | A Docker or OCI image tag is pushed |
| `build` | `uploaded` | A new build is uploaded |
| `build` | `promoted` | A build is promoted |

Other domains (artifact `copied`/`cached`, `release_bundle`, `distribution`, `xray_scan_status`,
`app_trust`, ...) are listed in [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/jfrog-webhooks/references/overview.md).

## Environment Variables

```bash
JFROG_WEBHOOK_SECRET=replace-with-a-long-random-secret   # the "Secret token" set on the webhook

```

## Local Development

JFrog can't reach `localhost` (and blocks private-network targets by default). Tunnel with the
Hookdeck CLI (no account required):

```bash
npx hookdeck-cli listen 3000 jfrog --path /webhooks/jfrog

```

Use the printed URL as the webhook's **URL**.

## Resources

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/jfrog-webhooks/references/overview.md) - How JFrog webhooks work, domains, events and payloads
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/jfrog-webhooks/references/setup.md) - Create the webhook and set the secret token
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/jfrog-webhooks/references/verification.md) - Token check, gotchas, signing mode caveat, debugging 401s
* [examples/](https://github.com/hookdeck/webhook-skills/tree/main/skills/jfrog-webhooks/examples/) - Runnable Express, Next.js and FastAPI handlers with tests