API (application programming interfaces — интерфейсы прикладного программирования) — это своего рода потайные двери, позволяющие взаимодействовать различным программам. Но не у всех должны быть ключи от каждой двери, как и не у всех программ должен быть неограниченный доступ к каждому API.
Эти API соединяют все — от мобильного приложения банка до платформы социальных сетей, — обрабатывая конфиденциальные данные и выполняя критически важные функции.
Без строгих протоколов авторизации API могут быть использованы не по назначению, что приведет к утечке данных, сбоям в работе сервисов и потере доверия пользователей.
Именно здесь на помощь приходит авторизация API.
Авторизация API следит за тем, чтобы только правильное программное обеспечение с правильным ключом могло открывать дверь и использовать внутренние ресурсы. Эффективная авторизация API — это больше, чем просто вопрос безопасности: она создает беспроблемный и безопасный пользовательский опыт. Она гарантирует получение доступа к личной информации только авторизованными приложениями, действующими исключительно в рамках разрешенной им области.
Что такое авторизация API
Прежде чем перейти к лучшим практикам авторизации API, уточним разницу между авторизацией и аутентификацией. Эти понятия часто путают.
- Аутентификация — это проверка личности. Речь идет о подтверждении личности пользователя с помощью имени пользователя, пароля или биометрических данных.
- Авторизация — это предоставление доступа к ресурсам или функциональным возможностям после подтверждения личности. Фигурально выражаясь, можно определить аутентификацию как доступ ко входной двери, а авторизацию — как доступ к помещениям и службам внутри здания.
Лучшие практики авторизации API
1. Авторизации на основе токенов (JWT, OAuth)
Авторизация на основе токенов, особенно с использованием токенов JWT (JSON Web) и OAuth, предлагает безопасный и эффективный способ управления взаимодействием с API. Это выражается в следующем.
- Токены обеспечивают аутентификацию без состояния, то есть серверу не нужно сохранять состояние сессии для каждого пользователя, что обеспечивает более высокий уровень масштабируемости.
- Токены могут безопасно передаваться различными способами и менее подвержены атакам CSRF, чем традиционная аутентификация на основе сессий.
- Токены можно использовать в разных доменах, что делает их идеальным решением для архитектуры микросервисов и приложений единого входа (SSO).
- Токены, особенно OAuth, могут включать области видимости и разрешения, обеспечивая точный контроль над действиями аутентифицированного пользователя.
Как реализовать авторизацию на основе токенов с использованием JWT
Токены JWT обычно генерируются после успешной аутентификации пользователя. Они содержат полезную нагрузку с информацией о пользователе и, возможно, его разрешениями. Для реализации JWT-авторизации можно использовать такие библиотеки, как jsonwebtoken в Node.js и PyJWT в Python.
Сначала нужно сгенерировать JWT-токен. Вот как это сделать с помощью PyJWT:
import jwt
from datetime import datetime, timedelta
secret_key = 'YOUR_SECRET_KEY'
payload = {
'sub': user_id,
'iat': datetime.utcnow(),
'exp': datetime.utcnow() + timedelta(days=1)
}
token = jwt.encode(payload, secret_key, algorithm='HS256')
После этого следует проверить каждый запрос, чтобы выяснить, разрешено ли пользователю выполнять запрос. Токен обычно отправляется в заголовок Authorization каждого запроса. Сервер может расшифровать JWT с помощью секретного ключа и проверить его. Если он валиден, сервер обрабатывает запрос, если нет — возвращает ошибку.
from flask import Flask, request, jsonify
import jwt
import datetime
app = Flask(name)
SECRET_KEY = "your_secret_key" # Замените на свой секретный ключ
Sample route that requires token-based authorization
@app.route('/protected', methods=['GET'])
def protected():
token = request.headers.get('Authorization')
if not token:
return jsonify({'message': 'Token is missing!'}), 403
try:
# Дешифровка токена
data = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
# Можете использовать данные в токене по своему усмотрению, например:
# user_id = data['user_id']
except jwt.ExpiredSignatureError:
return jsonify({'message': 'Token has expired!'}), 403
except jwt.InvalidTokenError:
return jsonify({'message': 'Invalid token!'}), 403
# Токен валиден, обработка запроса
return jsonify({'message': 'Token is valid! You have access to protected routes.'})
2. Тонкий (детальный) контроль доступа
Тонкий контроль доступа (fine-grained access control) — это подход к управлению безопасностью, который обеспечивает детальный контроль над разрешениями и правами доступа приложения. Он обеспечивает пользователям и службам только необходимый им доступ, придерживаясь принципа минимума полномочий.
Как реализовать тонкий контроль доступа
Реализация тонкого контроля доступа включает несколько этапов.
- Определение ролей и разрешений. Определите различные роли пользователей в системе и конкретные действия для каждой роли.
- Использование контроля доступа на основе ролей (RBAC). Внедрите RBAC, при котором доступ к ресурсам предоставляется на основе ролей. Каждой роли назначаются определенные разрешения.
- Рассмотрение возможности контроля доступа на основе атрибутов (ABAC). Для более сложных сценариев можно использовать ABAC, когда решения о доступе принимаются на основе комбинации атрибутов (пользователь, ресурс, среда).
Допустим, у вас есть API, доступ к которому различается для администратора и пользователя. Механизмы управления доступом можно реализовать с помощью независимых компонентов, повторно используемых во всех приложениях.
Можете использовать такие инструменты, как Bit, для создания независимого компонента авторизатора, который будет отвечать за авторизацию запросов к API.
Вот все, что вам нужно сделать.
1. Создайте компонент Node.js под названием “authorizer”, который позволит реализовать логику авторизации, с помощью команды:
bit create node util/authorizer
Если все сделаете правильно, увидите результат:
2. Реализуйте логику авторизатора:
export function authorizer(userId: string) {
// Реализуйте логику для получения роли пользователя
if (userId === 'U001') {
return "admin";
}
return "customer"
}
3. Создайте приложение Express App с помощью команды:
bit create express-app api
Увидите результат:
4. Подключите авторизатор к приложению, обновив файл mock-route.ts
. Изначально увидите следующее:
5. Добавьте новую промежуточную программу:
Это обеспечит запуск компонента авторизатора до вызова бизнес-логики. После запуска API увидите следующий результат:
С помощью цепочки функций обеспечен контроль доступа на основе ролей. Декоратор проверяет, соответствует ли роль пользователя требуемым ролям для конечной точки. Если нет — возвращает сообщение об отказе в доступе.
По мере обновления логики авторизатора и приложения сервер CI Bit — Ripple CI — автоматически обновляет изменения во всем дереве.
С полной реализацией можно ознакомиться в Bit Scope.
3. Конфигурация безопасного API-шлюза
Шлюз API действует как входная дверь для всех запросов API, уделяя основное внимание соблюдению мер безопасности и правил эксплуатации. Шлюзы API обеспечивают:
- Повышенную безопасность. Предоставляют дополнительный уровень безопасности, защищая от таких угроз, как DDoS-атаки, несанкционированный доступ и злонамеренное использование API.
- Ограничение скорости и дросселирование пропускной способности. Предотвращает чрезмерное использование API и обеспечивает равномерный доступ пользователей.
- Преобразование и проверку данных. Обеспечивает соответствие поступающих данных ожидаемым форматам и стандартам.
Как реализовать конфигурацию безопасного API-шлюза
Существует множество провайдеров API-шлюзов для приложений. Самые популярные из них — Amazon API Gateway, Kong и Apigee от Google.
Планируя использовать AWS (Amazon Web Services), следуйте шагам, описанным в официальной документации, чтобы легко создать API-шлюз. Однако есть несколько дополнительных моментов, которые необходимо учесть, чтобы обеспечить безопасность и эффективность API-шлюза.
- Настройка ограничения скорости. В консоли управления AWS перейдите к Amazon API Gateway, выберите свой API и перейдите в раздел Throttling (Дросселирование) во вкладке Protect (Защита). Там установите ограничения скорости обработки запросов и скорости передачи данных.
- Включение SSL/TLS. Убедитесь, что ваше пользовательское доменное имя для шлюза API совместимо с сертификатом SSL/TLS в AWS Certificate Manager.
- Реализация ограничения по IP-адресам. Используйте авторизаторы AWS Lambda для проверки IP-адресов входящих запросов. После развертывания функции можете выбрать ее, создав новый авторизатор для шлюза API во вкладке Authorization (Авторизация). Вот пример функции Lambda на языке Python для ограничения IP-адресов:
import json
def lambda_handler(event, context):
ip_address = event['requestContext']['identity']['sourceIp']
allowed_ips = ['192.168.1.1'] # Список допсутимых IP
# Добавьте сюда логику, чтобы проверить, находится ли ip_address в списке allowed_ips или нет.
if ip_address not in allowed_ips:
raise Exception('Unauthorized')
return {
'principalId': 'user',
'policyDocument': {
'Version': '2012-10-17',
'Statement': [{
'Action': 'execute-api:Invoke',
'Effect': 'Allow',
'Resource': event['methodArn']
}]
}
}
- Включение CloudWatch Logs. В консоли управления AWS перейдите к настройкам API-шлюза. В разделе CloudWatch Settings (Настройки CloudWatch) отметьте опцию Enable CloudWatch Logs (Подключить логирование CloudWatch). Установите уровень логирования на INFO для записи всех запросов и ответов или ERROR для записи только ответов на ошибки.
4. Шифрование конфиденциальных данных при передаче и хранении
Шифрование конфиденциальных данных при передаче (in transit) и хранении (at rest) — один из основных методов обеспечения безопасности, позволяющий защитить данные от несанкционированного доступа и взлома. Шифрование при передаче обеспечивает защиту данных при их перемещении между клиентами и серверами, а шифрование при хранении защищает данные, хранящиеся на диске или в базе данных.
Как реализовать шифрование при передаче данных
При использовании собственного веб-сервера придется вручную настраивать и управлять сертификатами SSL/TLS. Прежде всего, получите сертификаты в удостоверяющем центре (Certificate Authority, CA), таком как Let’s Encrypt, DigiCert и GoDaddy. Затем настройте сервер на взаимодействие с этим центром. Вот как можно настроить SSL с помощью Nginx.
- Измените конфигурационный файл Nginx (обычно он находится по адресу
/etc/nginx/nginx.conf
или/etc/nginx/sites-available/your_site
). - Добавьте настройки SSL в блок сервера:
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /path/to/your/fullchain.pem; # Путь к fullchain.pem из CA
ssl_certificate_key /path/to/your/privkey.pem; # Путь к приватному ключу из CA
# Сильные настройки шифрования (используйте рекомендации генератора настроек SSL от Mozilla)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256...';
# Другие конфигурации сервера...
}
При использовании облачных сервисов в вашем распоряжении будут полностью управляемые службы для работы с SSL/TLS. Можете, например, использовать AWS Certificate Manager для служб, размещенных на AWS.
Как реализовать шифрование при хранении данных
Шифрование при хранении данных можно реализовать на уровне базы данных, на уровне приложения или с помощью облачных инструментов.
1. Шифрование на уровне базы данных. Многие современные базы данных предлагают встроенные функции шифрования.
- SQL Server: прозрачное шифрование данных.
- MySQL: шифрование табличного пространства InnoDB.
- MongoDB: механизм хранения Encrypted Storage Engine.
2. Шифрование на уровне приложений. Шифрование на уровне приложения следует использовать для высокочувствительных данных, чтобы зашифровать их еще до хранения в базе данных. Для этого можно использовать библиотеки типа cryptography:
from cryptography.fernet import Fernet
# Генерация ключа
key = Fernet.generate_key()
cipher_suite = Fernet(key)
# Шифрование данных
encrypted_data = cipher_suite.encrypt(b"Sensitive Data")
# Расшифровка данных
decrypted_data = cipher_suite.decrypt(encrypted_data)
Заключение
Надежная API- авторизация имеет решающее значение для защиты цифровых активов и поддержания доверия пользователей.
Внедряя лучшие практики, описанные здесь, разработчики могут значительно повысить безопасность API-приложений, обеспечив при этом соответствие требованиям и защиту от различных киберугроз.
Читайте также:
- Как создать сетевой API с помощью Express.js, Bun и MongoDB
- Как правильно объявлять API устаревшими и не сломать пользователям код
- Как структурировать API-вызовы при автоматизированном тестировании с Playwright и JavaScript
Читайте нас в Telegram, VK и Дзен
Перевод статьи Chameera Dulanga: Best-Practices for API Authorization