Dịch vụ bên ngoài không thể gọi trực tiếp localhost. Tunnel cung cấp URL HTTPS công khai và chuyển tiếp headers thật cùng body nguyên bản tới server cục bộ. Giữ raw body trước JSON parser. Xác minh chữ ký và dữ liệu, lưu lần gửi bền vững rồi mới chạy business logic.
Cách Linear webhook đi tới ứng dụng cục bộ
Dịch vụ bên ngoài không thể gọi trực tiếp localhost. Tunnel cung cấp URL HTTPS công khai và chuyển tiếp headers thật cùng body nguyên bản tới server cục bộ. >tài liệu chính thức
1. Tạo endpoint giữ nguyên raw body
Giữ raw body trước JSON parser. Xác minh chữ ký và dữ liệu, lưu lần gửi bền vững rồi mới chạy business logic.
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);
Giữ raw body trước JSON parser. Xác minh chữ ký và dữ liệu, lưu lần gửi bền vững rồi mới chạy business logic. >tài liệu chính thức
2. Công khai cổng cục bộ qua HTTPS
Khởi động server và giữ tunnel chạy trong terminal khác. Phản hồi 401 cho request không ký xác nhận routing hoạt động và xác thực từ chối đúng.
npx portpreview 3000
https://example.portpreview.dev/webhooks/linear
Khởi động server và giữ tunnel chạy trong terminal khác. Phản hồi 401 cho request không ký xác nhận routing hoạt động và xác thực từ chối đúng.
3. Cấu hình webhook trong Linear
Đăng ký URL HTTPS đầy đủ, chỉ chọn event cần thiết và kích hoạt trường hợp thật trong môi trường thử nghiệm. Lưu secret ngoài repository.
Đăng ký URL HTTPS đầy đủ, chỉ chọn event cần thiết và kích hoạt trường hợp thật trong môi trường thử nghiệm. Lưu secret ngoài repository.
Xác minh chữ ký trên đúng chuỗi byte
Tính HMAC bằng webhook secret và dữ liệu chính xác theo đặc tả. So sánh constant-time và không ghi secret vào log.
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);
}
Tính HMAC bằng webhook secret và dữ liệu chính xác theo đặc tả. So sánh constant-time và không ghi secret vào log. >hướng dẫn thực hành
Chống replay bằng timestamp
Kiểm tra độ mới của timestamp sau khi chữ ký hợp lệ và đồng bộ đồng hồ host.
Kiểm tra độ mới của timestamp sau khi chữ ký hợp lệ và đồng bộ đồng hồ host.
Hiểu payload và mã định danh lần gửi
Chỉ xử lý type đã biết, chấp nhận field bổ sung và khử trùng lặp bằng ID lần gửi ổn định trong storage bền vững.
Chỉ xử lý type đã biết, chấp nhận field bổ sung và khử trùng lặp bằng ID lần gửi ổn định trong storage bền vững.
Phản hồi nhanh và xử lý idempotent
Giữ ID lần gửi và tạo job trong cùng transaction trước khi trả 200. Nếu không thể lưu bền vững, trả lỗi để nhà cung cấp retry.
Giữ ID lần gửi và tạo job trong cùng transaction trước khi trả 200. Nếu không thể lưu bền vững, trả lỗi để nhà cung cấp retry. >hướng dẫn thực hành
Kiểm thử toàn bộ luồng cục bộ
- Khởi động server và giữ tunnel chạy trong terminal khác. Phản hồi 401 cho request không ký xác nhận routing hoạt động và xác thực từ chối đúng.
- Đăng ký URL HTTPS đầy đủ, chỉ chọn event cần thiết và kích hoạt trường hợp thật trong môi trường thử nghiệm. Lưu secret ngoài repository.
- Tính HMAC bằng webhook secret và dữ liệu chính xác theo đặc tả. So sánh constant-time và không ghi secret vào log.
- Giữ ID lần gửi và tạo job trong cùng transaction trước khi trả 200. Nếu không thể lưu bền vững, trả lỗi để nhà cung cấp retry.
Kiểm tra routing, headers, chữ ký, thời gian phản hồi và idempotency. Request tổng hợp phù hợp nhất để thử nhánh từ chối.
Khắc phục lỗi Linear webhook
- Khởi động server và giữ tunnel chạy trong terminal khác. Phản hồi 401 cho request không ký xác nhận routing hoạt động và xác thực từ chối đúng.
- Tính HMAC bằng webhook secret và dữ liệu chính xác theo đặc tả. So sánh constant-time và không ghi secret vào log.
- Kiểm tra độ mới của timestamp sau khi chữ ký hợp lệ và đồng bộ đồng hồ host.
- Kiểm tra POST path, port của tunnel, raw body, secret, đồng hồ hệ thống và độ trễ cơ sở dữ liệu.
Danh sách bảo mật cho môi trường local và production
- Bắt buộc HTTPS, giới hạn kích thước và method, bảo vệ secrets, che dữ liệu log và xóa URL thử nghiệm cũ.
- Giữ raw body trước JSON parser. Xác minh chữ ký và dữ liệu, lưu lần gửi bền vững rồi mới chạy business logic.
- Giữ ID lần gửi và tạo job trong cùng transaction trước khi trả 200. Nếu không thể lưu bền vững, trả lỗi để nhà cung cấp retry.
Bắt buộc HTTPS, giới hạn kích thước và method, bảo vệ secrets, che dữ liệu log và xóa URL thử nghiệm cũ. >hướng dẫn thực hành
