• oidc
  • oauth
  • аутентификация
  • авторизация
  • jwt

Полное руководство по интеграции OIDC-сервера в ваш проект

Узнайте лучшие практики интеграции OIDC-сервера (OpenID Connect) в ваш проект и поймите, как компоненты взаимодействуют друг с другом на сцене.

Gao
Gao
Founder

Вы можете столкнуться с ситуацией, когда вам потребуется централизованная система аутентификации и авторизации, также известная как управление доступом к идентификации (IAM) или поставщик удостоверений (IdP). Иногда люди добавляют слово, обозначающее бизнес, например IAM для клиентов или IAM для персонала.

Давайте на мгновение оставим эти модные названия. Необходимость в IAM может возникнуть из-за роста вашего приложения, или вы планируете с самого начала переложить эту сложную задачу на вендора. Тем не менее, вы достигли точки, когда систему идентификации придется интегрировать в ваш проект.

Учитывая популярность OAuth 2.0, OpenID Connect (OIDC) является естественным выбором для многих разработчиков. Поскольку OIDC представляет собой слой аутентификации, построенный поверх OAuth 2.0, вы можете почувствовать некую схожесть, когда начнёте работать с OIDC. Давайте начнем!

Что такое OIDC-сервер, и почему я должен интегрировать OIDC-сервер?

OIDC-сервер, или поставщик идентификации, — это централизованная система, которая управляет аутентификацией и авторизацией пользователей. Как мы обсуждали в статье Почему вам нужна централизованная система идентификации для многоприложенческого бизнеса, у централизованной системы идентификации есть множество преимуществ.

Предположим, ваш проект начинается с простого веб-приложения, и в нем встроена аутентификация:

По мере роста вашего проекта вам нужно ввести мобильную версию:

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

Теперь вводится новая служба API. Поскольку это услуга для платных пользователей, вы должны убедиться, что пользователь аутентифицирован и авторизован для доступа к этой услуге. Чтобы добиться этого, вы можете предоставлять доступ к услуге через веб-приложение:

Или используйте метод токенов для аутентификации пользователя и проверьте токен, связываясь с веб-приложением в сервисе. Таким образом, мобильное приложение может использовать сервис напрямую:

Все усложняется. Поэтому вы решаете вынести логику аутентификации и авторизации в отдельный сервис:

Процесс рефакторинга может быть болезненным. Вы можете заметить, что его сложность будет увеличиваться экспоненциально по мере добавления приложений и сервисов в проект. Еще хуже то, что вам, возможно, придется поддерживать несколько методов аутентификации, таких как вход без пароля, социальный вход, SAML и т.д.

Вот почему стоит внедрить поставщика идентификации в самом начале, если у вас есть планы масштабировать проект.

Лучшие практики интеграции OIDC-сервера

Найти поставщика OIDC

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

Что означают "субъект", "клиент" и "аудитория" в OIDC?

Чтобы упростить концепцию, можно считать, что субъект — это сущность, запрашивающая доступ к аудитории через клиента.

Рассмотрим некоторые типичные сценарии:

1. Пользователь нажимает кнопку входа на веб-приложении

В традиционном веб-приложении с серверным рендерингом фронтенд и бэкенд связаны. Предположим, что веб-приложение обслуживает как фронтенд, так и бэкенд:

  • Субъект: Пользователь
  • Аудитория: OIDC-сервер
  • Клиент: Веб-приложение

Может показаться, что аудитория является OIDC-сервером. В действительности, это ключ к реализации опыта SSO (Single Sign-On) для конечных пользователей. Рассмотрим упрощенную диаграмму последовательности для кодового потока авторизации:

код — это одноразовый код, который может быть обменен на различные токены, такие как токен доступа, ID-токен и обновляющий токен. Ничего страшного, если вы не понимаете все эти токены в данный момент. По мере продвижения вперед вы лучше поймете их.

В вышеописанном случае пользователю не нужно снова входить в систему, когда он переключается на другое приложение, потому что пользователь (субъект) уже аутентифицирован на OIDC-сервере (аудитория).

2. Пользователь использует одностраничное приложение

В одностраничном приложении (или мобильном приложении) фронтенд и бэкенд разделены. Предположим, что бэкенд представляет собой сервис API:

  • Субъект: Пользователь
  • Аудитория: Сервис API
  • Клиент: Одностраничное приложение (SPA)

Упрощенная диаграмма последовательности с потоком кодов авторизации:

Поскольку сервис API является неинтерактивным, SPA использует токен доступа, в котором сервис API указан как аудитория (значение aud в токене).

Почему OIDC-сервер все еще является аудиторией?

Технически вы можете исключить OIDC-сервер из списка аудиторий. Поскольку в большинстве случаев вам потребуется информация о пользователе от OIDC-сервера (это требует, чтобы OIDC-сервер был аудиторией), всегда лучше включать OIDC-сервер в список аудиторий, когда взаимодействие связано с пользователем.

Подождите, вы говорите, что в запросе авторизации возможно иметь несколько аудиторий?

Именно так! Помните, что OIDC построен поверх OAuth 2.0, и возможно использовать RFC 8707: Resource Indicators for OAuth 2.0 в запросе авторизации для указания нескольких аудиторий. Это требует поддержки как от гранта, так и от сервера OIDC. Logto поддерживает эту функцию нативно.

3. Взаимодействие "машина-машина"

Предположим, у вас есть сервис А, который должен вызвать сервис B:

  • Субъект: Сервис А
  • Аудитория: Сервис B
  • Клиент: Сервис А

Упрощенная диаграмма последовательности с использованием гранта клиентских полномочий:

Когда сервис B должен вызвать сервис A, роли просто меняются местами.

Итог

  • Субъект: Это может быть пользователь, сервис или любая сущность, которой необходимо доступ к аудитории.
  • Клиент: Это может быть веб-приложение, мобильное приложение или любая сущность, инициирующая запрос или действующая от имени субъекта.
  • Аудитория: Это может быть сервис, API или любая сущность, предоставляющая доступ субъекту.

Что такое токены доступа, токены идентификатора и обновляющие токены?

Существуют три типа токенов, с которыми вы можете столкнуться при работе с OIDC:

  • Токен доступа: Используется для доступа к аудитории. Это может быть JWT (JSON Web Token) или непрозрачный токен (обычно случайная строка).
  • Токен идентификатора: OIDC-специфичный токен, содержащий информацию о пользователе. Это всегда JWT. Клиент может декодировать токен, чтобы получить информацию о пользователе.
  • Обновляющий токен: Используется для получения нового набора токенов, когда токен доступа или ID-токен истекает.

Для подробного объяснения этих токенов вы можете обратиться к статье Понимание обновляющих токенов, токенов доступа и ID-токенов в протоколе OIDC.

В вышеописанных сценариях 1 и 2 термин запрос авторизации относится к запросу на получение набора токенов через определенный грант.

Когда все проходит гладко, набор токенов будет возвращен на шаге "Обмен токенами с использованием кода". Доступные токены в наборе зависят от множества факторов, особенно от параметра scope в запросе авторизации. Ради простоты мы предположим, что все токены возвращаются в наборе. Как только токен доступа истекает, клиент может использовать обновляющий токен для получения нового набора токенов без взаимодействия с пользователем.

Для сценария 3 это проще, потому что на основе клиентских полномочий возвращается только токен доступа.

Как обрабатывать несколько аудиторий в OIDC?

Вы можете заметить, что за один раз возвращается только один токен доступа. Как же обрабатывать случай, когда клиент должен получить доступ к нескольким аудиториям?

Существуют два общих решения:

Указать resource в запросе обмена кода

Когда клиент обменивает код на токены, он может указать параметр resource в запросе. OIDC-сервер вернет токен доступа для указанной аудитории, если это применимо.

Вот неформальный пример:

Затем OIDC-сервер вернет токен доступа для аудитории API_SERVICE, если это применимо.

Использовать обновляющий токен, чтобы получить новый токен доступа

С RFC 8707 клиент даже может указать несколько аудиторий, используя параметр resource несколько раз. Теперь, если у клиента есть доступ к обновляющим токенам, он может указать аудиторию в параметре resource, обновляя токен.

Вот неформальный пример:

Это оказывает тот же эффект, что и предыдущее решение. Между тем, другие предоставленные аудитории будут по-прежнему доступны в будущих запросах токенов.

Грант клиентских полномочий

Вы также можете использовать параметр resource в гранте клиентских полномочий, чтобы указать аудиторию. В этом гранте нет проблем с несколькими аудиториями, поскольку вы всегда можете запросить новый токен доступа для другой аудитории, просто отправив очередной запрос токена.

Защитите свой API-сервис

"API-сервис" в сценарии 2 и "Сервис B" в сценарии 3 имеют одно общее: они должны проверить токен доступа, чтобы определить, авторизован ли запрос. В зависимости от формата токена доступа процесс проверки может отличаться.

  • Непрозрачный токен: API-сервис должен обратиться к OIDC-серверу для проверки токена. OIDC-сервер обычно предоставляет точку доступа для проверки токенов для этой цели.
  • JWT: API-сервис может проверить токен локально, проверив подпись и утверждения в токене. OIDC-сервер обычно предоставляет точку доступа JSON Web Key Set (JWKS) (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, нашу инфраструктуру идентификации для разработчиков.