Wszystkie artykuły
Bezpieczne testowanie webhooków Linear na localhost
Linearwebhookslocalhostdeveloper integrations

Bezpieczne testowanie webhooków Linear na localhost

Usługa zewnętrzna nie połączy się z localhost. Tunel udostępnia publiczny adres HTTPS i przekazuje prawdziwe nagłówki oraz niezmienione body do lokalnego serwera. Zachowaj surowe body przed parserem JSON. Najpierw sprawdź podpis i dane, trwale zapisz dostawę, a dopiero potem uruchom logikę biznesową.

Jak webhook Linear trafia do aplikacji lokalnej

Usługa zewnętrzna nie połączy się z localhost. Tunel udostępnia publiczny adres HTTPS i przekazuje prawdziwe nagłówki oraz niezmienione body do lokalnego serwera. >oficjalna dokumentacja

1. Zbuduj endpoint zachowujący surowe body

Zachowaj surowe body przed parserem JSON. Najpierw sprawdź podpis i dane, trwale zapisz dostawę, a dopiero potem uruchom logikę biznesową.

import express from "express";
import crypto from "node:crypto";

const app = express();
const secret = process.env.LINEAR_WEBHOOK_SECRET;

app.post(
  "/webhooks/linear",
  express.raw({ type: "application/json", limit: "1mb" }),
  async (req, res) => {
    const rawBody = req.body;
    const signature = req.get("linear-signature");

    if (!verifyLinearSignature(signature, rawBody, secret)) {
      return res.sendStatus(401);
    }

    let payload;
    try {
      payload = JSON.parse(rawBody.toString("utf8"));
    } catch {
      return res.sendStatus(400);
    }

    if (!Number.isFinite(payload.webhookTimestamp) ||
        Math.abs(Date.now() - payload.webhookTimestamp) > 60_000) {
      return res.sendStatus(401);
    }

    const deliveryId = req.get("linear-delivery") || payload.webhookId;
    if (!deliveryId) return res.sendStatus(400);

    try {
      await recordAndEnqueueOnce(deliveryId, payload);
      return res.sendStatus(200);
    } catch (error) {
      console.error("Linear webhook persistence failed", error);
      return res.sendStatus(500);
    }
  }
);

app.use(express.json());
app.listen(3000);

Zachowaj surowe body przed parserem JSON. Najpierw sprawdź podpis i dane, trwale zapisz dostawę, a dopiero potem uruchom logikę biznesową. >oficjalna dokumentacja

2. Udostępnij port lokalny przez HTTPS

Uruchom serwer i tunel w drugim terminalu. Odpowiedź 401 na niepodpisany request potwierdza poprawny routing i odrzucenie uwierzytelnienia.

npx portpreview 3000
https://example.portpreview.dev/webhooks/linear

Uruchom serwer i tunel w drugim terminalu. Odpowiedź 401 na niepodpisany request potwierdza poprawny routing i odrzucenie uwierzytelnienia.

3. Skonfiguruj webhook w Linear

Zapisz pełny adres HTTPS, wybierz tylko potrzebne zdarzenia i wywołaj je na koncie testowym. Sekret przechowuj poza repozytorium.

Zapisz pełny adres HTTPS, wybierz tylko potrzebne zdarzenia i wywołaj je na koncie testowym. Sekret przechowuj poza repozytorium.

Zweryfikuj podpis na dokładnych bajtach

Oblicz HMAC z sekretem webhooka i dokładnymi danymi wskazanymi przez dostawcę. Porównuj w stałym czasie i nie zapisuj sekretu w logach.

function verifyLinearSignature(signature, rawBody, secret) {
  if (!secret || typeof signature !== "string" ||
      !/^[0-9a-f]{64}$/i.test(signature)) {
    return false;
  }

  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest();
  const actual = Buffer.from(signature, "hex");

  return actual.length === expected.length &&
    crypto.timingSafeEqual(actual, expected);
}

Oblicz HMAC z sekretem webhooka i dokładnymi danymi wskazanymi przez dostawcę. Porównuj w stałym czasie i nie zapisuj sekretu w logach. >poradnik

Zastosuj ochronę przed replay

Po poprawnej weryfikacji podpisu sprawdź znacznik czasu i odrzuć stare wiadomości. Synchronizuj zegar hosta.

Po poprawnej weryfikacji podpisu sprawdź znacznik czasu i odrzuć stare wiadomości. Synchronizuj zegar hosta.

Poznaj payload i identyfikatory dostawy

Obsługuj znane typy, toleruj dodatkowe pola i deduplikuj za pomocą stabilnego identyfikatora dostawy.

Obsługuj znane typy, toleruj dodatkowe pola i deduplikuj za pomocą stabilnego identyfikatora dostawy.

Odpowiadaj szybko i przetwarzaj idempotentnie

Zarezerwuj identyfikator i utwórz zadanie w jednej transakcji przed odpowiedzią 200. Przy awarii trwałego storage zwróć błąd.

Zarezerwuj identyfikator i utwórz zadanie w jednej transakcji przed odpowiedzią 200. Przy awarii trwałego storage zwróć błąd. >poradnik

Przetestuj cały przepływ lokalnie

  1. Uruchom serwer i tunel w drugim terminalu. Odpowiedź 401 na niepodpisany request potwierdza poprawny routing i odrzucenie uwierzytelnienia.
  2. Zapisz pełny adres HTTPS, wybierz tylko potrzebne zdarzenia i wywołaj je na koncie testowym. Sekret przechowuj poza repozytorium.
  3. Oblicz HMAC z sekretem webhooka i dokładnymi danymi wskazanymi przez dostawcę. Porównuj w stałym czasie i nie zapisuj sekretu w logach.
  4. Zarezerwuj identyfikator i utwórz zadanie w jednej transakcji przed odpowiedzią 200. Przy awarii trwałego storage zwróć błąd.

Sprawdź routing, nagłówki, podpis, czas odpowiedzi i idempotencję. Syntetyczne requesty najlepiej nadają się do testowania odrzuceń.

Rozwiązywanie problemów z webhookiem Linear

  • Uruchom serwer i tunel w drugim terminalu. Odpowiedź 401 na niepodpisany request potwierdza poprawny routing i odrzucenie uwierzytelnienia.
  • Oblicz HMAC z sekretem webhooka i dokładnymi danymi wskazanymi przez dostawcę. Porównuj w stałym czasie i nie zapisuj sekretu w logach.
  • Po poprawnej weryfikacji podpisu sprawdź znacznik czasu i odrzuć stare wiadomości. Synchronizuj zegar hosta.
  • Sprawdź ścieżkę POST, port tunelu, surowe body, sekret, zegar i opóźnienia bazy danych.

>poradnik

Lista zabezpieczeń dla środowiska lokalnego i produkcji

  • Wymagaj HTTPS, ogranicz rozmiar i metodę, chroń sekrety, maskuj dane w logach i usuwaj nieaktualne adresy testowe.
  • Zachowaj surowe body przed parserem JSON. Najpierw sprawdź podpis i dane, trwale zapisz dostawę, a dopiero potem uruchom logikę biznesową.
  • Zarezerwuj identyfikator i utwórz zadanie w jednej transakcji przed odpowiedzią 200. Przy awarii trwałego storage zwróć błąd.

Wymagaj HTTPS, ogranicz rozmiar i metodę, chroń sekrety, maskuj dane w logach i usuwaj nieaktualne adresy testowe. >poradnik

Najczęściej zadawane pytania

Jak przetestować webhook Linear na localhost?
Uruchom serwer i tunel w drugim terminalu. Odpowiedź 401 na niepodpisany request potwierdza poprawny routing i odrzucenie uwierzytelnienia.
Jak zweryfikować podpis webhooka Linear?
Oblicz HMAC z sekretem webhooka i dokładnymi danymi wskazanymi przez dostawcę. Porównuj w stałym czasie i nie zapisuj sekretu w logach.
Dlaczego Linear ponawia dostawę webhooka?
Zarezerwuj identyfikator i utwórz zadanie w jednej transakcji przed odpowiedzią 200. Przy awarii trwałego storage zwróć błąd.
Jakiego klucza użyć do idempotencji?
Obsługuj znane typy, toleruj dodatkowe pola i deduplikuj za pomocą stabilnego identyfikatora dostawy.