Эта страница переведена машинным способом. Английская версия является источником и может быть точнее или новее. Открыть на английском

Аутентификация вебхуков - Защитите свои эндпоинты

finlight предоставляет несколько методов аутентификации для защиты доставки вебхуков. Каждый вебхук по умолчанию включает проверку подписи с необязательными дополнительными уровнями аутентификации для повышенной безопасности.

finlight поддерживает четыре метода аутентификации, которые можно использовать по отдельности или в сочетании:

НЕТБез доп. аутентификации

Нет

Никакой дополнительной аутентификации, кроме стандартной проверки подписи.

Когда использовать:

  • Среды тестирования и разработки
  • Внутренние эндпоинты за защищёнными сетями
  • Когда проверки подписи достаточно для безопасности

Примечание. Проверка подписи по-прежнему включается в каждый запрос вебхука независимо от этой настройки.


FINLIGHT_KEYПользовательский заголовок

Заголовок X-Finlight-Key

Отправляет ваш ключ API в пользовательском заголовке X-Finlight-Key с каждым запросом вебхука.

Конфигурация:

  • Укажите ключ API при настройке вебхука
  • Ключ будет включён в заголовок X-Finlight-Key

Реализация: Ваш эндпоинт должен проверять входящий заголовок:

const finlightKey = req.headers['x-finlight-key']
if (finlightKey !== 'your-expected-api-key') {
  return res.status(401).send('Invalid API key')
}

Отправляемые заголовки:

X-Finlight-Key: your-api-key-value
X-Webhook-Signature: sha256=signature
X-Webhook-Timestamp: 2024-01-15T10:30:00.000Z

BASICЛогин/Пароль

Базовая аутентификация

HTTP-аутентификация Basic с учётными данными логин/пароль.

Конфигурация:

  • Задайте логин и пароль при настройке вебхука
  • Учётные данные кодируются в base64 и отправляются в заголовке Authorization

Реализация: Ваш эндпоинт получает стандартную HTTP Basic Auth:

const auth = req.headers.authorization
if (!auth || !auth.startsWith('Basic ')) {
  return res.status(401).send('Missing Basic Auth')
}

const credentials = Buffer.from(auth.slice(6), 'base64').toString()
const [username, password] = credentials.split(':')

if (username !== 'expected-user' || password !== 'expected-pass') {
  return res.status(401).send('Invalid credentials')
}

Отправляемые заголовки:

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
X-Webhook-Signature: sha256=signature
X-Webhook-Timestamp: 2024-01-15T10:30:00.000Z

SIGNATUREВсегда включена

Проверка подписи

Автоматическая безопасность: Каждый запрос вебхука включает проверку подписи независимо от выбранного метода аутентификации.

Как это работает:

  1. finlight генерирует метку времени при отправке вебхука
  2. Создаёт сообщение путём конкатенации: timestamp + '.' + payload
  3. Подписывает сообщение с помощью HMAC-SHA256, используя секретный ключ вашего вебхука
  4. Отправляет в заголовках и подпись, и метку времени

Включаемые заголовки:

X-Webhook-Signature: sha256=computed-signature
X-Webhook-Timestamp: 2024-01-15T10:30:00.000Z

Алгоритм подписи:

message = timestamp + '.' + raw_request_body
signature = HMAC-SHA256(message, webhook_secret)

Если заголовок X-Webhook-Timestamp отсутствует, сообщением является само необработанное тело запроса. Сравнивайте результат за постоянное время и отклоняйте доставки, метка времени которых старше пяти минут.

Проверка с помощью официального клиента

Каждая клиентская библиотека содержит помощник, выполняющий всю проверку за вас: он принимает префикс sha256= в подписи, сравнивает за постоянное время, применяет пятиминутное окно защиты от повторов и возвращает разобранную статью. При неудачной проверке он выбрасывает исключение или возвращает ошибку — всегда отвечайте на это кодом 4xx и никогда не обрабатывайте полезную нагрузку.

Проверка вебхука

import express from 'express'
import { WebhookService } from 'finlight-client'

const app = express()

app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  try {
    const article = WebhookService.constructEvent(
      req.body.toString(),
      req.headers['x-webhook-signature'] as string,
      process.env.WEBHOOK_SECRET!,
      req.headers['x-webhook-timestamp'] as string,
    )

    console.log('New article:', article.title)
    res.sendStatus(200)
  } catch (err) {
    console.error('Webhook verification failed:', err)
    res.sendStatus(400)
  }
})

SECURITYКлючевые рекомендации

Лучшие практики безопасности

Проверка метки времени

Показанные выше помощники constructEvent уже применяют пятиминутное окно защиты от повторов, поэтому это нужно, только если вы проверяете подписи вручную:

function isTimestampValid(timestamp, toleranceSeconds = 300) {
  const now = Date.now()
  const requestTime = new Date(timestamp).getTime()
  const difference = Math.abs(now - requestTime) / 1000

  return difference <= toleranceSeconds
}

Безопасное хранение учётных данных

  • Переменные окружения: Храните все секреты в переменных окружения
  • Управление секретами: Используйте AWS Secrets Manager, HashiCorp Vault или аналог
  • Никогда не хардкодьте: Никогда не коммитьте секреты в систему контроля версий
  • Регулярная ротация: Периодически обновляйте секреты вебхуков

Рекомендации по настройке вебхуков см. в основной документации по вебхукам. Для всестороннего тестирования см. руководство по тестированию вебхуков.