Спрут IAM 1.0.0 Help

7. Руководство по интеграции

Ниже на практическом примере рассмотрено как встроить Спрут IAM в веб-приложение. Демонстрационное приложение, на примере которого рассматривается интеграция, входит в комплект поставки Спрут IAM.

Основные способы интеграции

Спрут IAM предлагает три основных подхода к интеграции, от самого простого до наиболее гибкого:

Способ 0: Прокси без изменений в коде приложения

Самый простой способ защитить приложение, не требующий изменений в его коде:

ПользовательПользовательSprut IAM ProxySprut IAM ProxySprut IAMSprut IAMПриложениеПриложениеGET /app/editПроверка авторизацииalt[Пользователь не авторизован]Редирект на страницу логинаВвод логина/пароляВыдача токена/сессииGET /app/edit (авторизован)Возврат страницыСтраница /app/edit
  • Принцип работы: Спрут IAM размещает прокси-сервер перед вашим приложением, который проверяет наличие сессии пользователя

  • Доступ: Контролируется на уровне URL-адресов

  • Приложение: Не получает информации о пользователе

  • Подходит для: Быстрой защиты существующих приложений, когда нет возможности менять код

Способ 1: Прокси с проверкой разрешений в приложении

Немного более сложный, но гораздо более функциональный способ:

ПользовательПользовательSprut IAM ProxySprut IAM ProxyПриложениеПриложениеSprut IAMSprut IAMGET /app/editПроверка авторизацииalt[Не авторизован]Редирект на логинВвод логина/пароляВыдача oidc_session, user_infoPOST /proxy/newsessionСоздаём локальную сессиюGET /app/edit (session)checkPermissionВозвращаем страницу
  • Принцип работы: Прокси-сервер интегрируется с приложением через специальные API-вызовы

  • Доступ: Контролируется как на уровне URL, так и внутри приложения

  • Приложение: Получает информацию о пользователе и его разрешениях

  • Подходит для: Приложений, где требуется более детальный контроль доступа

Способ 2: Интеграция через OIDC/OAuth 2.0

Наиболее гибкий и стандартизированный подход:

ПользовательПользовательПриложение (Client)Приложение (Client)Sprut IAM (OIDC Server)Sprut IAM (OIDC Server)GET /app/editcheck local sessionalt[No local session]302 Redirect -> IAM /authorize?...Ввод логина/пароля302 Redirect -> App /oidc/callback?code=xyzGET /oidc/callback?code=xyzPOST /token {code=xyz, secret=???}{access_token, id_token, refresh_token}store tokens in sessioncheckPermission(...) using id_tokenСтраница /app/edit
  • Принцип работы: Прямая интеграция приложения со Спрут IAM через протоколы OIDC/OAuth 2.0

  • Доступ: Полностью контролируется приложением

  • Приложение: Самостоятельно управляет всем процессом аутентификации и авторизации

  • Подходит для: Современных приложений, особенно SPA, мобильных приложений и микросервисов

Способ 0: Прокси без изменений в коде приложения

Это самый простой способ защиты вашего приложения.

Добавление в Спрут IAM (без доработок)

  1. Войдите в административную консоль Спрут IAM (http://localhost:8090)

  2. Перейдите в раздел "Приложения"

  3. Нажмите "Добавить приложение"

  4. Заполните форму:

    • Название: Имя вашего приложения

    • Порт: Порт для доступа к приложению через прокси (например, 8216)

    • URL приложения: Внутренний адрес вашего приложения (например, http://demo-app:80)

    • Настройте маршруты и правила предоставления доступа к ним

    • Запомните Client ID и Client Secret

  5. Нажмите "Сохранить"

Проверка работы

  1. Откройте приложение через прокси: http://localhost:8091 (порт 8216 отображается в 8091)

  2. При попытке доступа к защищённым страницам вы будете перенаправлены на страницу входа

  3. После успешной аутентификации вы получите доступ к защищённым ресурсам

Преимущество этого подхода — вам не нужно менять код приложения вообще. Достаточно настроить прокси в консоли Спрут IAM.

Способ 1: Прокси с проверкой разрешений в приложении

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

Добавление в Спрут IAM (настройка прокси)

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

При этом необходимо реализовать эти два обязательных эндпоинта в приложении.

Эндпоинт /proxy/newsession

Этот эндпоинт вызывается Спрут IAM при успешной аутентификации пользователя. Приложение должно извлечь и запомнить сведения о пользователе и его разрешениях.

Информация о пользователе, передаваемая от Спрут IAM имеет следующую структуру:

{ "user_info": { "sub": "1234567890", "name": "Иван Петров", "email": "ivan@example.com", "permissions": [ "/:/auth", "/rooms/floor1:/book", "/rooms/floor2:/read" ] }, "oidc_session": "AHHps7zVREyKD6d2P8FqhwYMY9tWe1Bs" }

Вот пример реализации эндпоинта на языке Python:

@app.route('/proxy/newsession', methods=['POST']) def newsession(): # Получаем данные от Спрут IAM data = flask.request.get_json() # Извлекаем идентификатор сессии и информацию о пользователе session = data.get('oidc_session', 'no-session') user_info = data.get('user_info', {}) # Сохраняем информацию в сессии приложения # В реальном приложении следует использовать защищённое хранилище app.session_info[session] = user_info # Создаём ответ с флагом успеха response = flask.jsonify({"success": "true"}) # Устанавливаем cookie с идентификатором сессии response.set_cookie('session', session) return response

Эндпоинт /proxy/endsession

Этот эндпоинт вызывается при завершении сессии. Приложение должно сбросить сохраненные ранее данные о пользователе и его разрешениях.

@app.route('/proxy/endsession') def endsession(): # Получаем идентификатор текущей сессии session = flask.request.cookies.get('session', 'no-session') # Удаляем информацию о сессии app.session_info.pop(session, None) # Перенаправляем на страницу выхода Спрут IAM redirect_url = '/api/service/sprut-proxy/logout?redirect=true' return flask.redirect(redirect_url)

Проверка разрешений (прокси)

Теперь вы можете проверять разрешения пользователя в любой части кода. При этом рекомендуется использовать ранее сохраненные права доступа, либо каждый раз обращаться к Спрут IAM за актуальными данными пользователя.

def checkPermission(permission): # Получаем идентификатор сессии из cookie session = flask.request.cookies.get('session', 'no-session') # Получаем информацию о сессии session_info = app.session_info.get(session, {}) # Получаем список разрешений permissions = session_info.get('permissions', []) # Проверяем наличие требуемого разрешения return permission in permissions # Пример использования в обработчике запроса @app.route('/app/edit') def edit(): # Проверяем, авторизован ли пользователь if not checkPermission('/:/auth'): return "Доступ запрещен", 403 # Проверяем конкретное разрешение if not checkPermission('/rooms/floor1:/book'): return "Недостаточно прав для бронирования", 403 # Код обработки запроса... return "Редактирование разрешено"

Способ 2: Интеграция через OIDC/OAuth 2.0

Это самый гибкий способ интеграции, позволяющий полностью контролировать процесс аутентификации и авторизации.

Добавление в Спрут IAM (настройка OIDC)

Порядок действий аналогичен Способу 0, однако необходимо выбрать режим "Не использовать прокси".

На закладке Безопасность необходимо задать допустимый список Redirect URI, включив туда внешние URL приложения для обработки ответа после аутентификации (например, http://localhost:8081/oidc/callback)

Структура эндпоинтов сервера OIDC

Эндпоинты OIDС расположены по адресу /api/service/oidc

Например, интерфейс автообнаружения сервисов доступен на /api/service/oidc/.well-known/openid-configuration

# Адреса OIDC-сервера (внешний для перенаправления пользователя, внутренний для API-запросов) OIDC_SERVER_EXT=http://localhost:8090 OIDC_SERVER_INT=http://sprut-iam:8215 # Эндпоинты OIDC AUTH_ENDPOINT=${OIDC_SERVER_EXT}/login/oidc TOKEN_ENDPOINT=${OIDC_SERVER_INT}/api/service/oidc/token LOGOUT_ENDPOINT=${OIDC_SERVER_INT}/api/service/oidc/end-session SERVICE_ENDPOINT=${OIDC_SERVER_INT}/api/service/ext-apps USERINFO_ENDPOINT=${OIDC_SERVER_INT}/api/service/oidc/userinfo

Эндпоинт /oidc/login

Этот эндпоинт инициирует процесс аутентификации, перенаправляя пользователя на страницу входа Спрут IAM:

@app.route('/oidc/login') def login(): # Генерируем случайное значение state для защиты от CSRF state = f'{time.time()**2:.0f}' flask.session['state'] = state # Формируем URL для перенаправления на страницу аутентификации redirect_url = ( f'{ENV["AUTH_ENDPOINT"]}?' f'response_type=code&' f'client_id={ENV["CLIENT_ID"]}&' f'redirect_uri={ENV["CLIENT_REDIRECT"]}&' f'scope=openid profile permissions&' f'state={state}' ) # Перенаправляем пользователя return flask.redirect(redirect_url)

Эндпоинт /oidc/callback

Этот эндпоинт обрабатывает ответ от Спрут IAM после успешной аутентификации:

@app.route('/oidc/callback') def callback(): # Проверяем соответствие значения state для защиты от CSRF state = flask.session.get('state', 'no-state') check = flask.request.args.get('state', 'no-check') if state != check: return "Ошибка безопасности: несоответствие state", 400 # Получаем код авторизации code = flask.request.args.get('code', 'no-code') # Обмениваем код на токены tokens = fetchTokens('authorization_code', 'code', code) if not tokens: return "Не удалось получить токены", 400 # Декодируем и проверяем токены session_info = decodeTokens(tokens) if not session_info: return "Не удалось декодировать токены", 400 # Сохраняем информацию о сессии session = session_info['id_token']['sid'] saveSessionInfo(session, session_info) # Перенаправляем на главную страницу return flask.redirect(flask.url_for('root'))

Эндпоинт /oidc/logout

Этот эндпоинт завершает сессию пользователя:

@app.route('/oidc/logout') def logout(): # Получаем токен доступа access_token = getSessionInfo().get('access_token', None) # Вызываем эндпоинт завершения сессии в Спрут IAM http_request('GET', ENV['LOGOUT_ENDPOINT'], access_token=access_token) # Очищаем локальную сессию clearSessionInfo(getSessionId()) # Перенаправляем на главную страницу return flask.redirect(flask.url_for('root'))

Проверка разрешений (сервер)

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

Загрузка справочников в Спрут IAM

Если приложение работает с собственными объектами (например, комнаты, документы, проекты), можно загрузить их в Спрут IAM для назначения прав доступа в разрезе прикладных объектов. Можно загружать справочник организаций, объектов и действий.

Для загрузки справочников используется эндпоинт /api/service/ext-apps

# Определяем справочники dictionaries = { # Действия (например, чтение, запись, бронирование) 'actions': [ {'id': '/auth', 'title': 'Авторизация'}, {'id': '/book', 'title': 'Бронирование'}, {'id': '/read', 'title': 'Чтение'}, {'id': '/write', 'title': 'Запись'} ], # Объекты (например, комнаты, этажи) 'objects': [ {'id': '/floor1', 'title': 'Этаж #1'}, {'id': '/floor1/room101', 'title': 'Переговорная 1-01'}, {'id': '/floor1/room102', 'title': 'Переговорная 1-02'}, {'id': '/floor2', 'title': 'Этаж #2'}, {'id': '/floor2/room201', 'title': 'Переговорная 2-01'} ], # Организации 'organizations': [ {'id': '/org0001', 'title': 'Организация #1'}, {'id': '/org0002', 'title': 'Организация #2'} ] } # Отправляем справочники в Спрут IAM http_request('POST', ENV['SERVICE_ENDPOINT'], json={ 'client_id': ENV['CLIENT_ID'], 'client_secret': ENV['CLIENT_SECRET'], 'action': 'putDictionaries', 'data': { 'dictionaries': dictionaries } })

Идентификаторы объектов (поле id) имеют иерархическую структуру:

  • Должны начинаться с символа /

  • Вложенные объекты также указываются через /

  • Например: /floor1/room101 означает, что объект "room101" находится внутри объекта "floor1"

Рекомендации по интеграции

Выбор подходящего способа интеграции

  • Способ 0 (прокси без изменений) подходит, если:

    • У вас нет возможности изменять код приложения

    • Требуется быстрое внедрение защиты

    • Достаточно простого контроля доступа по URL

  • Способ 1 (прокси с проверкой разрешений) подходит, если:

    • Требуется более детальный контроль доступа внутри приложения

    • Нежелательно реализовывать полный протокол OIDC

    • Приложение уже имеет некоторую логику авторизации

  • Способ 2 (OIDC/OAuth) подходит, если:

    • Требуется максимальная гибкость

    • Приложение имеет клиентскую часть (SPA, мобильное приложение)

    • Используется микросервисная архитектура

Особенности реализации

  1. Не храните CLIENT_SECRET в клиентском коде (JavaScript, мобильные приложения)

  2. Всегда проверяйте параметр state при обработке OIDC-callback для защиты от CSRF

  3. Всегда валидируйте JWT-токены, проверяя подпись и срок действия

  4. Храните токены безопасно, используя защищённые хранилища (например, HttpOnly cookies, Redis, зашифрованные базы данных)

Производительность

  1. Кэшируйте результаты проверки разрешений для частых операций

  2. Используйте refresh_token для продления сессии без повторной аутентификации

  3. Минимизируйте запросы к Спрут IAM — не проверяйте разрешения при каждом действии пользователя

  4. Используйте готовые библиотеки для работы с OAuth 2.0, OIDC, JWT

Last modified: 12 марта 2025