Skip to content
IRC-CodingIRC-Coding
REST API безопасностьАутентификацияАвторизацияOAuth 2.0JWTRBACCORSAPI Security

REST API безопасность: аутентификация и авторизация

REST API безопасность: OAuth 2.0, JWT, Session-Auth, RBAC, ABAC, CORS, CSRF и лучшие практики.

S

schutzgeist

11 min read
REST API безопасность: аутентификация и авторизация

Безопасность REST API: аутентификация, авторизация и защитные механизмы

Безопасность REST API гарантирует, что доступ к ресурсам получают только авторизованные клиенты. Если вы разрабатываете API, необходимо понимать аутентификацию и авторизацию — это фундамент любого защищённого интерфейса.

Что такое безопасность REST API?

Безопасность REST API включает все меры, которые защищают RESTful API от несанкционированного доступа, изменения данных и атак. Она основана на двух ключевых опорах:

Аутентификация отвечает на вопрос: Кто ты? Клиент доказывает свою идентичность через токены, API-ключи, сертификаты или сессионные cookies.

Авторизация отвечает на вопрос: Можешь ли ты это делать? После аутентификации проверяется, имеет ли определённый клиент право выполнить запрошенное действие.

Разделение между ними критически важно. Аутентифицированный пользователь не автоматически имеет доступ ко всему. Пользователь может читать свои данные, но не данные других. Администратор может больше, чем редактор. Такие отношения моделируются через RBAC (Role-Based Access Control) или ABAC (Attribute-Based Access Control).

Кто использует REST API Security?

  • Backend-разработчики реализуют middleware аутентификации и логику авторизации
  • Проектировщики API определяют, какие endpoints требуют какой уровень защиты
  • DevOps-инженеры настраивают TLS, Rate Limiting и API Gateway
  • Security-инженеры проводят аудит API на уязвимости
  • Frontend-разработчики должны правильно передавать auth-токены

Почему этот вопрос важен в информатике и на экзаменах?

OWASP Top 10 размещает Broken Access Control на первом месте, а Cryptographic Failures на втором — оба прямо касаются API-безопасности. На экзаменах IHK, в курсах информатики и сертификациях регулярно проверяют различия между аутентификацией и авторизацией, знание OAuth 2.0, JWT и заголовков безопасности.

Ключевые концепции в деталях

Методы аутентификации для REST API

API-Key

Клиент отправляет статический ключ в заголовке X-API-Key. Сервер сравнивает его с записью в базе данных.

Преимущества: простота, удобство для общения сервер-сервер. Недостатки: нет срока действия, отсутствие детализированных прав, при компрометации полный доступ.

Аутентификация на основе сессий

Клиент отправляет учётные данные (имя пользователя и пароль). Сервер создаёт сессию, сохраняет её на стороне сервера и возвращает ID сессии в cookie. При каждом последующем запросе cookie отправляется автоматически.

Преимущества: контроль на стороне сервера, сессия может быть аннулирована в любой момент. Недостатки: плохая масштабируемость при большом количестве инстансов (требуется общее хранилище сессий), риск CSRF с cookies.

Аутентификация на основе токенов (JWT)

Клиент отправляет учётные данные. Сервер создаёт JSON Web Token (JWT) содержащий claims вроде ID пользователя, ролей и времени истечения. Токен криптографически подписан. Клиент отправляет его при каждом запросе в заголовке Authorization: Bearer <token>.

Преимущества: без состояния (stateless), хорошо масштабируется, не требует хранилища сессий. Недостатки: токен трудно отозвать до истечения срока (если не использовать Revocation Lists или Blacklists).

OAuth 2.0

OAuth 2.0 — это фреймворк для делегированной авторизации. Клиент получает Access Token от Authorization Server после согласия Resource Owner (пользователя). Токен разрешает доступ к определённым ресурсам в течение ограниченного времени.

Основные flows:

  • Authorization Code Flow: стандарт для веб-приложений с серверной частью
  • PKCE Flow: для SPA и мобильных приложений без Client Secret
  • Client Credentials Flow: для общения сервер-сервер без участия пользователя

Модели авторизации

RBAC (Role-Based Access Control)

Пользователям назначаются роли. Роли имеют разрешения. Проверка работает так: Имеет ли пользователь роль, которая разрешает это действие?

Пример: роль admin может всё, роль editor может читать и писать, роль viewer только читает.

Преимущества: просто понять, хорошо работает для небольших систем. Недостатки: взрыв количества ролей при детализированных разрешениях.

ABAC (Attribute-Based Access Control)

Контроль доступа основан на атрибутах субъекта, ресурса, действия и окружения. Проверка работает так: Все ли атрибуты в совокупности удовлетворяют политике?

Пример: доктор может читать данные пациентов только во время своего рабочего времени и только для пациентов своего отделения.

Преимущества: очень детализировано, основано на политиках. Недостатки: сложнее в реализации и обслуживании.

Авторизация на основе владения ресурсом

Пользователь может обращаться только к ресурсам, которые ему принадлежат. Заказ можно просмотреть только владельцу. Проверка требует запроса к базе данных: Этот ресурс принадлежит текущему пользователю?

Дополнительные защитные механизмы

TLS (Transport Layer Security)

Каждый API должен работать по HTTPS. Без TLS токены и учётные данные могут быть перехвачены. TLS шифрует транспортный канал и гарантирует целостность передаваемых данных.

CORS (Cross-Origin Resource Sharing)

CORS регулирует, какие внешние origins могут обращаться к API. Сервер отправляет заголовок Access-Control-Allow-Origin. Без правильной настройки CORS браузерные клиенты могут быть заблокированы, или напротив, произвольные origins получат доступ.

Защита от CSRF

При аутентификации на основе cookies существует риск CSRF. Злоумышленник может заставить браузер автоматически отправить cookie. Защита: CSRF-токены, атрибут SameSite для cookies, использование заголовка Authorization вместо cookies.

Rate Limiting

Ограничивает количество запросов от одного клиента в заданный период. Защищает от перебора паролей, credential stuffing и DoS. Типично: 100 запросов в минуту на токен.

Валидация входных данных

Каждый вход должен быть проверен. SQL Injection, XSS и Command Injection возникают из-за отсутствия или недостаточной валидации. Используйте Prepared Statements, валидацию схемы и whitelisting.

Почему REST API Security важна на практике?

Незащищённый API это открытое окно к вашим данным. Реальные сценарии:

  • Утечка токена: Access Token сохраняется в логах или жёстко закодирован в коде клиента. Злоумышленник находит его и получает доступ ко всем данным затронутого пользователя.
  • Broken Object Level Authorization (BOLA): API проверяет только, аутентифицирован ли пользователь, но не проверяет, имеет ли он право на запрошенный ресурс. Пользователь обращается к /api/orders/42 и видит заказ другого пользователя.
  • Mass Assignment: Клиент отправляет поле типа {"role":"admin"} при обновлении профиля. Сервер принимает его без проверки. Пользователь сам себя делает админом.
  • Отсутствие Rate Limiting: Злоумышленник перебирает 10.000 паролей в секунду. Без Rate Limiting пароль будет сломан за минуты.

Практический пример: Express.js API с JWT и RBAC

Этот пример показывает полноценный REST API с аутентификацией (JWT) и авторизацией (RBAC). Выбран потому что объединяет важнейшие концепции в компактном коде: создание токенов, middleware-проверка auth, ролевой контроль доступа и проверка владения ресурсом.

// auth-middleware.js
// Middleware: Проверяет JWT из заголовка Authorization
function authenticate(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({
      error: 'UNAUTHORIZED',
      message: 'Authentifizierung erforderlich. Senden Sie einen Bearer Token.'
    });
  }

  const token = authHeader.split(' ')[1];
  try {
    // jwt.verify выбрасывает исключение при невалидном или устаревшем токене
    const payload = jwt.verify(token, process.env.JWT_SECRET);
    req.user = payload; // { userId: 42, role: 'editor', exp: 1234567890 }
    next();
  } catch (err) {
    return res.status(401).json({
      error: 'INVALID_TOKEN',
      message: 'Token ist ungültig oder abgelaufen.'
    });
  }
}

// Middleware: Проверяет, имеет ли пользователь одну из требуемых ролей
function authorize(...roles) {
  return (req, res, next) => {
    if (!req.user) {
      return res.status(401).json({
        error: 'UNAUTHORIZED',
        message: 'Authentifizierung erforderlich.'
      });
    }
    if (!roles.includes(req.user.role)) {
      return res.status(403).json({
        error: 'FORBIDDEN',
        message: `Erforderliche Rolle: ${roles.join(' oder ')}.`
      });
    }
    next();
  };
}

// Middleware: Проверяет, является ли пользователь владельцем ресурса
function checkOwnership(getResourceId) {
  return async (req, res, next) => {
    const resourceId = getResourceId(req);
    const resource = await db.orders.findById(resourceId);
    if (!resource) {
      return res.status(404).json({
        error: 'NOT_FOUND',
        message: 'Ressource nicht gefunden.'
      });
    }
    // Админы могут всё, остальные только свои ресурсы
    if (req.user.role !== 'admin' && resource.userId !== req.user.userId) {
      return res.status(403).json({
        error: 'FORBIDDEN',
        message: 'Sie dürfen nur auf eigene Ressourcen zugreifen.'
      });
    }
    req.resource = resource;
    next();
  };
}
// routes.js
// Применение middleware к различным endpoints

// Login: Аутентификация -> выдача JWT
app.post('/api/login', async (req, res) => {
  const { email, password } = req.body;
  const user = await db.users.findByEmail(email);
  if (!user || !await bcrypt.compare(password, user.passwordHash)) {
    return res.status(401).json({
      error: 'INVALID_CREDENTIALS',
      message: 'E-Mail oder Passwort falsch.'
    });
  }
  const token = jwt.sign(
    { userId: user.id, role: user.role },
    process.env.JWT_SECRET,
    { expiresIn: '15m' }
  );
  res.json({ token });
});

// Защищённые маршруты: authenticate для всех, authorize для специфичных ролей
app.get('/api/orders', authenticate, async (req, res) => {
  // Обычные пользователи видят только свои заказы
  if (req.user.role === 'admin') {
    const orders = await db.orders.findAll();
    res.json(orders);
  } else {
    const orders = await db.orders.findByUserId(req.user.userId);
    res.json(orders);
  }
});

app.get('/api/orders/:id', authenticate, checkOwnership(req => req.params.id), (req, res) => {
  res.json(req.resource);
});

app.post('/api/orders', authenticate, async (req, res) => {
  const order = await db.orders.create({
    ...req.body,
    userId: req.user.userId
  });
  res.status(201).json(order);
});

app.delete('/api/orders/:id', authenticate, authorize('admin'), checkOwnership(req => req.params.id), async (req, res) => {
  await db.orders.delete(req.params.id);
  res.status(204).send();
});

Подробная информация

Время жизни токенов и Refresh Tokens

Access Token должен быть короткоживущим (15 минут). Refresh Token живёт дольше (дни или недели) и используется только для получения новых Access Tokens. Если Access Token скомпрометирован, его можно использовать только в течение короткого времени. Если скомпрометирован Refresh Token, он может быть отозван на стороне сервера.

Структура JWT

JWT состоит из трёх частей, закодированных в Base64: Header, Payload и Signature. Header содержит алгоритм и тип. Payload содержит Claims, такие как sub (Subject), exp (Expiration), iat (Issued At), role, userId. Signature вычисляется с помощью Secret или Private Key.

Важно: Payload только закодирован в Base64, но не зашифрован. Никогда не храните чувствительные данные в JWT. Безопасность обеспечивается подписью — она гарантирует, что токен не был изменён.

Заголовки безопасности для REST API

HeaderНазначение
Strict-Transport-SecurityТребует HTTPS
X-Content-Type-Options: nosniffПредотвращает MIME Sniffing
X-Frame-Options: DENYПредотвращает Clickjacking
Cache-Control: no-storeПредотвращает кеширование чувствительных ответов
Access-Control-Allow-OriginКонфигурация CORS

Распространённые уязвимости (OWASP API Security Top 10)

  1. BOLA (Broken Object Level Authorization): Отсутствие проверки прав собственности на объект
  2. Broken Authentication: Слабое создание токенов, отсутствие Rate Limits
  3. Excessive Data Exposure: API возвращает больше полей, чем необходимо
  4. Lack of Resources & Rate Limiting: Отсутствие ограничения на количество запросов
  5. Broken Function Level Authorization: Отсутствие проверки ролей для каждого эндпоинта
  6. Mass Assignment: Неотфильтрованное принятие всех входных полей
  7. Security Misconfiguration: Стандартные секреты, режим отладки, открытый CORS

Резюме лучших практик

  • Используйте HTTPS всегда и только
  • Access Token короткоживущий (15 мин), Refresh Token можно отозвать
  • RBAC для грубой разбивки прав, ABAC для детальных политик
  • Проверка владения ресурсом для каждого эндпоинта с доступом к конкретным объектам
  • Rate Limiting на уровне IP и токена
  • Input Validation со схемой и белым списком
  • Никаких чувствительных данных в JWT Payload
  • Установите заголовки безопасности
  • Ошибки без внутренних деталей
  • Регулярные аудиты безопасности и тесты на проникновение

FAQ: безопасность REST API

1. В чём разница между аутентификацией и авторизацией?

Аутентификация проверяет идентичность клиента (Кто ты?), тогда как авторизация проверяет, имеет ли аутентифицированный клиент право выполнять определённое действие (Можешь ли ты это делать?). Аутентификация обычно происходит через вход с использованием учётных данных, авторизация — через проверку ролей или атрибутов.

2. Что такое RBAC?

RBAC (Role-Based Access Control) — это модель авторизации, при которой пользователям назначаются роли, а роли имеют разрешения. Контроль доступа проверяет, есть ли у пользователя требуемая роль. Это просто для понимания, но при детальных разрешениях может привести к взрыву ролей.

3. Что такое ABAC?

ABAC (Attribute-Based Access Control) — это модель авторизации, при которой контроль доступа основан на атрибутах субъекта, ресурса, действия и окружения. Политики определяют, какие комбинации атрибутов разрешают доступ. ABAC более детальна, чем RBAC, но сложнее в реализации.

4. Что такое Broken Object Level Authorization (BOLA)?

BOLA — это наиболее распространённая уязвимость API по версии OWASP. API проверяет аутентификацию пользователя, но не проверяет, имеет ли он доступ к запрашиваемому ресурсу. Пользователь может получить доступ к чужим данным, изменив ID в URL. Защита: проверка владения ресурсом для каждого эндпоинта.

5. Почему Access Token должен быть короткоживущим?

Access Token должен быть короткоживущим (например, 15 минут), потому что при компрометировании он может быть использован только в течение короткого времени. Более долгое время жизни означает более высокий риск. Для длительных сеансов используются Refresh Tokens, которые можно отозвать на сервере.

6. В чём разница между JWT и Session Cookies?

JWT является stateless — сервер не хранит сессию, вся информация находится в токене. Session Cookies требуют хранилища сессии на сервере. JWT лучше масштабируется, но сложнее отозвать. Сессии проще аннулировать, но требуют общего состояния на нескольких серверах.

7. Что такое Mass Assignment и как его предотвратить?

Mass Assignment возникает, когда сервер беспроверочно принимает все входные поля. Клиент может отправить поле role: admin и дать себе права администратора. Защита: явный выбор полей (белый список), DTO с только разрешёнными полями и валидация входных данных.

8. Почему CORS важен для безопасности API?

CORS (Cross-Origin Resource Sharing) регулирует, какие внешние Origins из браузера могут обращаться к API. Без конфигурации CORS легитимные браузерные клиенты могут быть заблокированы или, при слишком открытой конфигурации, любые веб-сайты смогут получить доступ к API. Правильная настройка — это белый список конкретных Origins.

9. Что такое CSRF и как это влияет на REST API?

CSRF (Cross-Site Request Forgery) происходит, когда атакующий заставляет браузер пользователя отправить запрос к API, при этом Session Cookie отправляется автоматически. При аутентификации на основе токенов в заголовке Authorization CSRF не является риском, так как браузер не отправляет заголовок автоматически. При аутентификации на основе cookies следует использовать CSRF-токены и атрибут SameSite.

10. Зашифрованы ли JWT Payloads?

Нет, JWT Payload только закодирован в Base64, но не зашифрован. Любой, кто перехватит токен, сможет прочитать Payload. Безопасность обеспечивается подписью, которая предотвращает манипуляцию. Для конфиденциальных данных должна использоваться JWE (JSON Web Encryption).

11. Что такое PKCE Flow в OAuth 2.0?

PKCE (Proof Key for Code Exchange) расширяет Authorization Code Flow для SPA и мобильных приложений, которые не могут безопасно хранить Client Secret. Клиент генерирует Code Verifier и отправляет его хеш (Code Challenge) на Authorization Server. При обмене токена клиент должен отправить исходный Verifier, что делает перехват Authorization Code бесполезным.

12. Как работает Rate Limiting в API?

Rate Limiting ограничивает количество запросов от клиента за определённый период. Типичные методы: Fixed Window (например, 100 запросов в минуту), Sliding Window и Token Bucket. Ограничение может быть применено по IP-адресу, API-ключу или токену. При превышении сервер отвечает 429 Too Many Requests с заголовком Retry-After.

13. Какие HTTP-статус-коды релевантны для ошибок аутентификации?

401 Unauthorized означает, что аутентификация отсутствует или неверна. 403 Forbidden означает, что клиент аутентифицирован, но не имеет прав на выполнение запрашиваемого действия. 429 Too Many Requests показывает, что было отправлено слишком много запросов.

14. Что такое Principle of Least Privilege?

Principle of Least Privilege гласит, что каждый клиент и каждый пользователь должны получать только минимальные разрешения, необходимые для выполнения своих задач. Клиент с доступом на чтение не получает прав на запись. Редактор не получает прав администратора. Это снижает поверхность атаки при компрометировании.

15. Как отозвать JWT до истечения срока?

Поскольку JWT является stateless, его нельзя просто отозвать. Решения: вести Revocation List (чёрный список) на сервере и проверять его при каждом запросе, или использовать короткоживущие токены с Refresh Tokens, которые можно отозвать. При logout соответствующий Refresh Token может быть инвалидирован, чтобы новые Access Tokens больше не выдавались.

Продолжение пути обучения API

Следующая статья в пути обучения API рассказывает о API Security Best Practices: защита, обеспечение безопасности и управление API — основные меры безопасности при работе с API согласно OWASP и лучшим практикам.

Источники и дополнительные ресурсы

  1. https://owasp.org/API-Security/editions/2023/en/0x11-t10/
  2. https://datatracker.ietf.org/doc/html/rfc6749 (OAuth 2.0)
  3. https://datatracker.ietf.org/doc/html/rfc7519 (JWT)
  4. https://owasp.org/www-project-top-ten/
  5. https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html

Книги по разработке API

Keine Bücher für Kategorie "api-development" gefunden.

Назад к блогу
Share:

Похожие статьи