Вопрос или проблема
Я создаю приложение с многопользовательским доступом, которое имеет необычное требование позволять арендаторам использовать свои собственные внешние системы для входа/аутентификации.
То есть: арендатор 1 использует Azure AD, арендатор 2 использует Auth0, арендатор 3 использует Github и т.д.
План состоит в том, что приложение распознает арендатора (по URL) и предлагает соответствующую ссылку для входа к их провайдеру идентичности, который при успешном завершении возвращает id_token клиентскому приложению.
Приложение (одностраничное приложение, поэтому не конфиденциальное) затем передает id_token в каждом запросе к API Gateway, который проверяет, действителен ли токен, а затем использует токен для поиска прав авторизации пользователей в внутренней пользовательской базе данных. Эти области затем передаются внутренним бэкенд-API.
Я понимаю, что id-токены предназначены для клиента, а для аутентификации следует использовать токены доступа – но в данном случае внешние провайдеры идентичности не знают о областях пользователей (readCustomer, writeInvoice и т.д.), поэтому не могут выдать токен доступа, содержащий их.
МОЙ ВОПРОС: не создаю ли я потенциально небезопасный мир страданий для себя – или, с учетом обстоятельств, это практичное решение?
Будет ли лучше передать id_token только один раз в API Gateway/внутреннему провайдеру идентичности, контролируемому нами, а затем получать токены доступа/обновления с этого момента?
Существует ли лучший способ достижения этих требований?
Вы можете использовать несколько провайдеров идентичности для каждого арендатора. Однако вы теряете преимущества использования JWT, извлекая области из базы данных. JWT можно проверять в памяти, и информация, содержащаяся в нем, сразу становится доступной для API после проверки. Поиск в базе данных для получения связанных областей является ненужной операцией ввода-вывода, которую можно избежать, если вы заранее настроите области для вашего OIDC-клиента в момент онбординга арендатора. Существуют адаптеры для OIDC-клиентов, которые позволяют программно настраивать клиента с провайдером идентичности.
Когда вы идентифицируете арендатора и токены доступа и ID токен выданы, приложение арендатора должно отправлять оба токена в API Gateway с каждым запросом. API Gateway должен проверять их оба, и если ID токен истек, вы можете получить новый ID токен, используя токен доступа. Затем прочитайте области из токена доступа и передайте ID токен и области внутренним API. Не пересылайте токен доступа во внутренние API, так как авторизация запроса выполняется только API Gateway.
С вышеописанным подходом вам не нужно настраивать свой собственный провайдер идентичности в качестве шлюза, если у вас нет арендаторов, которые не используют внешние провайдеры идентичности. Служба промежуточного программного обеспечения между вашими внутренними API и приложением арендатора также может обрабатывать аутентификацию и авторизацию без выполнения поиска в базе данных. Это промежуточное программное обеспечение также может взаимодействовать с вашим собственным провайдером идентичности при необходимости так же, как оно взаимодействует с внешними.
Ответ или решение
Создание многоарендного приложения с поддержкой нескольких провайдеров идентификации OpenID Connect (OIDC) – это задача, которая требует тщательного подхода с точки зрения безопасности и удобства для пользователей. Рассмотрим, как можно реализовать такое решение.
Архитектура приложения
-
Определение арендатора по URL: При входе в систему ваше приложение должно уметь определять арендатора по URL. Это позволит предлагать пользователю соответствующую ссылку для входа в систему через его провайдера идентификации.
-
Аутентификация через разные OIDC провайдеры: Каждому арендатору будет предложен свой провайдер для аутентификации, основанный на его предпочтениях (например, Azure AD, Auth0, Github и т.д.). После успешной аутентификации от провайдера будет получен ID Token.
-
Использование ID Token и Access Token: ID Token предназначен для клиента и содержит идентификационные данные пользователя. Access Token, однако, предназначен для авторизации и обычно содержит права доступа. Если у вас есть возможность настраивать различные OIDC провайдеры, рассмотрите вариант, когда вы будете получать как Access Token, так и ID Token одновременно.
-
Классическая схема работы:
- После входа в систему через OIDC провайдер приложение отправляет как ID Token, так и Access Token в API Gateway.
- API Gateway проверяет оба токена:
- Если ID Token истек, вы можете использовать Access Token для получения нового ID Token через стандартный механизм обновления.
- С помощью Access Token вы сможете извлекать права доступа (scopes), связанные с пользователем.
-
Извлечение прав доступа: Вместо того чтобы извлекать права доступа из базы данных, вы можете заранее конфигурировать эти права во время онбординга арендаторов. Это избавит вас от лишних запросов к базе данных, что в свою очередь повысит производительность системы.
Безопасность и рекомендации
-
Избегайте пересылки Access Token: Ваш API Gateway должен быть единственной точкой, которая работает с Access Token для обеспечения безопасности. Не передавайте Access Token внутренним API, так как авторизация должна проверяться именно на уровне шлюза.
-
Рассмотрите промежуточный сервис: Вы можете создать промежуточный сервис между внутренними API и приложением арендатора, который будет обрабатывать аутентификацию и авторизацию, используя при этом ваше собственное решение для идентификации, когда это необходимо.
-
Постоянный аудит и мониторинг: Внедрите механизмы для постоянного мониторинга и аудита аутентификации и авторизации для выявления любых аномалий или потенциально несоответствующих действий.
Заключение
Ваша концепция является практичным решением, однако важно соблюдать осторожность, чтобы минимизировать потенциальные проблемы с безопасностью и производительностью. Вы можете реализовать эффективную и безопасную архитектуру, следуя вышеизложенным рекомендациям. Таким образом, вы сможете предложить владельцам арендаторов гибкость в выборе провайдеров аутентификации без ущерба для безопасности и производительности вашего приложения.