Полное руководство по интеграции OIDC-сервера в ваш проект
Узнайте лучшие практики интеграции OIDC-сервера (OpenID Connect) в ваш проект и поймите, как компоненты взаимодействуют друг с другом на сцене.
Узнайте лучшие практики интеграции OIDC-сервера (OpenID Connect) в ваш проект и поймите, как компоненты взаимодействуют друг с другом на сцене.
Вы можете столкнуться с ситуацией, когда вам потребуется централизованная система аутентификации и авторизации, также известная как управление доступом к идентификации (IAM) или поставщик удостоверений (IdP). Иногда люди добавляют слово, обозначающее бизнес, например IAM для клиентов или IAM для персонала.
Давайте на мгновение оставим эти модные названия. Необходимость в IAM может возникнуть из-за роста вашего приложения, или вы планируете с самого начала переложить эту сложную задачу на вендора. Тем не менее, вы достигли точки, когда систему идентификации придется интегрировать в ваш проект.
Учитывая популярность OAuth 2.0, OpenID Connect (OIDC) является естественным выбором для многих разработчиков. Поскольку OIDC представляет собой слой аутентификации, построенный поверх OAuth 2.0, вы можете почувствовать некую схожесть, когда начнёте работать с OIDC. Давайте начнем!
OIDC-сервер, или поставщик идентификации, — это централизованная система, которая управляет аутентификацией и авторизацией пользователей. Как мы обсуждали в статье Почему вам нужна централизованная система идентификации для многоприложенческого бизнеса, у централизованной системы идентификации есть множество преимуществ.
Предположим, ваш проект начинается с простого веб-приложения, и в нем встроена аутентификация:
По мере роста вашего проекта вам нужно ввести мобильную версию:
Пользователям будет неприятно, если им придется создавать учетную запись для каждого приложения. Поскольку вы начали с веб-приложения, вы дали возможность мобильному приложению взаимодействовать с веб-приложением для аутентификации:
Теперь вводится новая служба API. Поскольку это услуга для платных пользователей, вы должны убедиться, что пользователь аутентифицирован и авторизован для доступа к этой услуге. Чтобы добиться этого, вы можете предоставлять доступ к услуге через веб-приложение:
Или используйте метод токенов для аутентификации пользователя и проверьте токен, связываясь с веб-приложением в сервисе. Таким образом, мобильное приложение может использовать сервис напрямую:
Все усложняется. Поэтому вы решаете вынести логику аутентификации и авторизации в отдельный сервис:
Процесс рефакторинга может быть болезненным. Вы можете заметить, что его сложность будет увеличиваться экспоненциально по мере добавления приложений и сервисов в проект. Еще хуже то, что вам, возможно, придется поддерживать несколько методов аутентификации, таких как вход без пароля, социальный вход, SAML и т.д.
Вот почему стоит внедрить поставщика идентификации в самом начале, если у вас есть планы масштабировать проект.
На рынке представлено множество поставщиков OIDC. Вы можете выбрать одного на основе ваших требований и предпочтений. Пока поставщик соответствует стандартам OIDC, он будет выполнять ту же роль в вашем проекте.
Чтобы упростить концепцию, можно считать, что субъект — это сущность, запрашивающая доступ к аудитории через клиента.
Рассмотрим некоторые типичные сценарии:
В традиционном веб-приложении с серверным рендерингом фронтенд и бэкенд связаны. Предположим, что веб-приложение обслуживает как фронтенд, так и бэкенд:
Может показаться, что аудитория является OIDC-сервером. В действительности, это ключ к реализации опыта SSO (Single Sign-On) для конечных пользователей. Рассмотрим упрощенную диаграмму последовательности для кодового потока авторизации:
код — это одноразовый код, который может быть обменен на различные токены, такие как токен доступа, ID-токен и обновляющий токен. Ничего страшного, если вы не понимаете все эти токены в данный момент. По мере продвижения вперед вы лучше поймете их.
В вышеописанном случае пользователю не нужно снова входить в систему, когда он переключается на другое приложение, потому что пользователь (субъект) уже аутентифицирован на OIDC-сервере (аудитория).
В одностраничном приложении (или мобильном приложении) фронтенд и бэкенд разделены. Предположим, что бэкенд представляет собой сервис API:
Упрощенная диаграмма последовательности с потоком кодов авторизации:
Поскольку сервис API является неинтерактивным, SPA использует токен доступа, в котором сервис API указан как аудитория (значение aud в токене).
Почему OIDC-сервер все еще является аудиторией?
Технически вы можете исключить OIDC-сервер из списка аудиторий. Поскольку в большинстве случаев вам потребуется информация о пользователе от OIDC-сервера (это требует, чтобы OIDC-сервер был аудиторией), всегда лучше включать OIDC-сервер в список аудиторий, когда взаимодействие связано с пользователем.
Подождите, вы говорите, что в запросе авторизации возможно иметь несколько аудиторий?
Именно так! Помните, что OIDC построен поверх OAuth 2.0, и возможно использовать RFC 8707: Resource Indicators for OAuth 2.0 в запросе авторизации для указания нескольких аудиторий. Это требует поддержки как от гранта, так и от сервера OIDC. Logto поддерживает эту функцию нативно.
Предположим, у вас есть сервис А, который должен вызвать сервис B:
Упрощенная диаграмма последовательности с использованием гранта клиентских полномочий:
Когда сервис B должен вызвать сервис A, роли просто меняются местами.
Существуют три типа токенов, с которыми вы можете столкнуться при работе с OIDC:
Для подробного объяснения этих токенов вы можете обратиться к статье Понимание обновляющих токенов, токенов доступа и ID-токенов в протоколе OIDC.
В вышеописанных сценариях 1 и 2 термин запрос авторизации относится к запросу на получение набора токенов через определенный грант.
Когда все проходит гладко, набор токенов будет возвращен на шаге "Обмен токенами с использованием кода". Доступные токены в наборе зависят от множества факторов, особенно от параметра scope в запросе авторизации. Ради простоты мы предположим, что все токены возвращаются в наборе. Как только токен доступа истекает, клиент может использовать обновляющий токен для получения нового набора токенов без взаимодействия с пользователем.
Для сценария 3 это проще, потому что на основе клиентских полномочий возвращается только токен доступа.
Вы можете заметить, что за один раз возвращается только один токен доступа. Как же обрабатывать случай, когда клиент должен получить доступ к нескольким аудиториям?
Существуют два общих решения:
resource в запросе обмена кодаКогда клиент обменивает код на токены, он может указать параметр resource в запросе. OIDC-сервер вернет токен доступа для указанной аудитории, если это применимо.
Вот неформальный пример:
Затем OIDC-сервер вернет токен доступа для аудитории API_SERVICE, если это применимо.
С RFC 8707 клиент даже может указать несколько аудиторий, используя параметр resource несколько раз. Теперь, если у клиента есть доступ к обновляющим токенам, он может указать аудиторию в параметре resource, обновляя токен.
Вот неформальный пример:
Это оказывает тот же эффект, что и предыдущее решение. Между тем, другие предоставленные аудитории будут по-прежнему доступны в будущих запросах токенов.
Вы также можете использовать параметр resource в гранте клиентских полномочий, чтобы указать аудиторию. В этом гранте нет проблем с несколькими аудиториями, поскольку вы всегда можете запросить новый токен доступа для другой аудитории, просто отправив очередной запрос токена.
"API-сервис" в сценарии 2 и "Сервис B" в сценарии 3 имеют одно общее: они должны проверить токен доступа, чтобы определить, авторизован ли запрос. В зависимости от формата токена доступа процесс проверки может отличаться.
jwks_uri), чтобы API-сервис мог получить открытый ключ и проверить подпись. Если вы новичок в работе с JWT, вы можете обратиться к статье Что такое JSON Web Token (JWT)?. На самом деле, обычно нет необходимости проверять подпись и утверждения вручную, поскольку существуют множество библиотек, которые могут сделать это за вас, таких как jose для Node.js и веб-браузеров.В дополнение к проверке подписи JWT, API-сервис всегда должен проверять утверждения в токене:
iss: Эмитент токена. Он должен соответствовать URL эмитента OIDC-сервера.aud: Аудитория токена. Она должна соответствовать значению аудитории API-сервиса (обычно допустимому URI).exp: Время истечения срока действия токена. API-сервис должен отвергнуть токен, если он истек.scope: Области (разрешения) токена. API-сервис должен проверить, присутствует ли требуемая область в токене.Другие утверждения, такие как sub (субъект) и iat (время выдачи), также важны в некоторых случаях. Если у вас есть дополнительные меры безопасности, проверьте утверждения соответствующим образом.
Остался нерешённый вопрос: как определить, может ли область (т.е. разрешение) быть предоставлена субъекту?
Один вопрос ведет к целому новому миру авторизации, который выходит за рамки этой статьи. Вкратце, существуют некоторые общие методы, такие как RBAC (модель управления доступом на основе ролей) и ABAC (модель управления доступом на основе атрибутов). Вот некоторые ресурсы, чтобы начать:
Введение OIDC-сервера в ваш проект — это большой шаг. Он может значительно улучшить безопасность и масштабируемость вашего проекта. В то же время, может потребоваться некоторое время, чтобы понять концепции и взаимодействия между компонентами.
Выбор хорошего поставщика OIDC, который соответствует вашим требованиям и предпочтениям, может значительно снизить сложность процесса интеграции, поскольку поставщик обычно предлагает полный пакет, включая OIDC-сервер, механизмы авторизации, SDK и корпоративные функции, которые вам могут понадобиться в будущем.
Надеюсь, это руководство поможет вам понять основы интеграции OIDC-сервера. Если вы ищете, с чего начать, я бы эгоистично рекомендовал Logto, нашу инфраструктуру идентификации для разработчиков.