OIDC интеграция
В этом разделе описана пошаговая интеграция внешних приложений с IDENTYX через протокол OpenID Connect. Руководство содержит практические примеры реализации и детальное описание всех этапов интеграции.
Обзор процесса интеграции
Интеграция приложения с IDENTYX через OIDC состоит из следующих этапов:
- Регистрация приложения в IDENTYX
- Получение конфигурации OIDC сервера
- Реализация Authorization Code Flow
- Обработка токенов и получение информации о пользователе
- Обновление токенов (Refresh Token)
- Завершение сессии
Шаг 1: Регистрация приложения
Перед началом интеграции необходимо зарегистрировать ваше приложение в IDENTYX:
- Перейдите в раздел OIDC приложения
- Нажмите кнопку Создать приложение
- Заполните обязательные поля:
- Название приложения — понятное имя для пользователей
- Client ID — уникальный идентификатор приложения
- Client Secret — секретный ключ для аутентификации
- URL приложения — адрес вашего приложения (если не используется IDENTYX Proxy)
- Укажите разрешенные URL для перенаправления (Redirect URIs)
- Сохраните приложение
Сохраните значения client_id и client_secret — они понадобятся для настройки вашего приложения. Client Secret должен храниться в безопасности и никогда не передаваться на клиентскую сторону.
Шаг 2: Получение конфигурации OIDC
IDENTYX предоставляет эндпоинт автоматической конфигурации (Discovery), который содержит все необходимые URL для интеграции.
Well-Known Configuration Endpoint
Обратитесь к эндпоинту конфигурации:
GET https://ваш-identyx-сервер/.well-known/openid-configuration
Пример ответа:
{
"issuer": "https://ваш-identyx-сервер",
"authorization_endpoint": "https://ваш-identyx-сервер/login/oidc",
"token_endpoint": "https://ваш-identyx-сервер/api/service/oidc/token",
"userinfo_endpoint": "https://ваш-identyx-сервер/api/service/oidc/userinfo",
"end_session_endpoint": "https://ваш-identyx-сервер/api/service/oidc/end-session",
"scopes_supported": ["openid", "profile", "email", "permissions"],
"claims_supported": ["name", "phone", "phone_verified", "email", "email_verified", "permissions"],
"grant_types_supported": ["authorization_code"],
"response_types_supported": ["code"],
"response_modes_supported": ["query"],
"token_endpoint_auth_methods_supported": ["client_secret_post"]
}
Большинство OIDC-библиотек автоматически используют этот эндпоинт для получения конфигурации. Вам достаточно указать базовый URL вашего IDENTYX сервера.
Основные эндпоинты
| Эндпоинт | URL | Назначение |
|---|---|---|
| Authorization | /login/oidc |
Страница входа и получение кода авторизации |
| Token | /api/service/oidc/token |
Обмен кода на токены и обновление токенов |
| UserInfo | /api/service/oidc/userinfo |
Получение информации о пользователе |
| End Session | /api/service/oidc/end-session |
Завершение сессии пользователя |
Шаг 3: Authorization Code Flow
IDENTYX использует Authorization Code Flow — наиболее безопасный способ аутентификации для веб-приложений.
3.1 Перенаправление на страницу входа
Когда пользователь хочет войти в ваше приложение, перенаправьте его на Authorization Endpoint IDENTYX:
GET https://ваш-identyx-сервер/login/oidc?
response_type=code&
client_id=ваш_client_id&
redirect_uri=https://ваше-приложение/callback&
scope=openid profile email permissions&
state=случайная_строка&
nonce=случайная_строка
Параметры запроса:
| Параметр | Обязательный | Описание |
|---|---|---|
response_type |
Да | Всегда code |
client_id |
Да | Идентификатор вашего приложения из IDENTYX |
redirect_uri |
Да | URL для возврата после входа (должен быть зарегистрирован в IDENTYX) |
scope |
Да | Запрашиваемые разрешения (через пробел): openid, profile, email, permissions |
state |
Да | Случайная строка для защиты от CSRF атак |
nonce |
Рекомендуется | Случайная строка для защиты от replay атак |
Обязательно генерируйте уникальный state для каждого запроса и проверяйте его при получении ответа. Это защищает от CSRF атак. Сохраните значение state в сессии вашего приложения.
Описание Scopes
- openid (обязательный) — базовый scope для OIDC, возвращает идентификатор пользователя
sub - profile — доступ к отображаемому имени (
name) и телефону (phone) пользователя - email — доступ к email адресу пользователя
- permissions — доступ к правам пользователя в вашем приложении
3.2 Пользователь проходит аутентификацию
IDENTYX отобразит страницу входа, где пользователь:
- Выберет метод аутентификации (локальная, LDAP, внешние провайдеры, и т.д.)
- Введет свои учетные данные
- При необходимости пройдет двухфакторную аутентификацию
- Примет условия использования приложения (если настроена оферта)
3.3 Получение кода авторизации
После успешной аутентификации IDENTYX перенаправит пользователя обратно на ваш redirect_uri с параметрами:
GET https://ваше-приложение/callback?
code=полученный_код_авторизации&
state=та_же_случайная_строка
Что нужно сделать:
- Проверьте, что значение
stateсовпадает с тем, что вы отправили - Извлеките значение
code— это код авторизации - Используйте код для получения токенов (следующий шаг)
Код авторизации действителен очень короткое время (несколько минут) и может быть использован только один раз. Немедленно обменяйте его на токены.
Шаг 4: Обмен кода на токены
Теперь нужно обменять полученный код авторизации на токены доступа. Этот запрос выполняется с серверной стороны вашего приложения.
Запрос токенов
POST https://ваш-identyx-сервер/api/service/oidc/token
Content-Type: application/json
{
"grant_type": "authorization_code",
"client_id": "ваш_client_id",
"client_secret": "ваш_client_secret",
"code": "полученный_код_авторизации",
"redirect_uri": "https://ваше-приложение/callback"
}
Параметры запроса:
| Параметр | Описание |
|---|---|
grant_type |
Всегда authorization_code |
client_id |
Идентификатор вашего приложения |
client_secret |
Секретный ключ вашего приложения |
code |
Код авторизации, полученный на предыдущем шаге |
redirect_uri |
Тот же redirect_uri, что использовался при запросе кода |
Ответ с токенами
Успешный ответ:
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "def50200a1b2c3d4e5f6...",
"scope": "openid profile email permissions",
"id_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9..."
}
Описание полей:
| Поле | Описание |
|---|---|
access_token |
Токен для доступа к защищенным ресурсам (UserInfo endpoint) |
refresh_token |
Токен для обновления access_token после его истечения |
id_token |
JWT токен с информацией о пользователе и аутентификации |
token_type |
Тип токена, всегда Bearer |
expires_in |
Время жизни access_token в секундах |
scope |
Предоставленные разрешения |
Храните токены в безопасном месте на сервере (например, в зашифрованных cookie или в серверной сессии). Никогда не передавайте refresh_token на клиентскую сторону.
Проверка ID Token
ID Token — это JWT (JSON Web Token), содержащий информацию о пользователе. Он должен быть проверен перед использованием.
Структура ID Token:
{
"iss": "https://ваш-identyx-сервер",
"sub": "user123",
"aud": "ваш_client_id",
"exp": 1640995200,
"iat": 1640991600,
"auth_time": 1640991600,
"nonce": "ваш_nonce",
"sid": "session_id",
"name": "Иван Иванов",
"email": "ivan@example.com",
"email_verified": false,
"permissions": ["/app1:/read", "/app1:/write"]
}
Важные поля:
iss— издатель токена (ваш IDENTYX сервер)sub— уникальный идентификатор пользователяaud— для кого предназначен токен (должен быть ваш client_id)exp— время истечения токена (Unix timestamp)iat— время создания токенаnonce— должен совпадать с отправленным вами noncesid— идентификатор OIDC сессии
Проверки, которые необходимо выполнить:
- Проверьте подпись токена (используя
client_secretи алгоритм HS512) - Убедитесь, что
issсоответствует вашему IDENTYX серверу - Убедитесь, что
audсоответствует вашемуclient_id - Проверьте, что токен не истек (
exp > current_time) - Убедитесь, что
nonceсовпадает с отправленным
Используйте проверенные OIDC библиотеки для вашего языка программирования — они автоматически выполнят все необходимые проверки токена.
Шаг 5: Получение информации о пользователе
После получения токенов вы можете запросить дополнительную информацию о пользователе через UserInfo endpoint.
Запрос UserInfo
GET https://ваш-identyx-сервер/api/service/oidc/userinfo
Authorization: Bearer ваш_access_token
Или отправьте POST запрос с access_token в теле:
POST https://ваш-identyx-сервер/api/service/oidc/userinfo
Content-Type: application/json
{
"access_token": "ваш_access_token"
}
Ответ UserInfo
Пример ответа:
{
"sub": "user123",
"name": "Иван Иванов",
"email": "ivan@example.com",
"email_verified": false,
"phone": "+79001234567",
"phone_verified": false,
"permissions": [
"/ваше-приложение:/read",
"/ваше-приложение:/write",
"/ваше-приложение:/admin"
]
}
Возвращаемые поля зависят от запрошенных scopes:
| Scope | Возвращаемые поля |
|---|---|
openid |
sub (идентификатор пользователя) |
profile |
name, phone, phone_verified |
email |
email, email_verified |
permissions |
permissions (массив прав доступа) |
Использование прав доступа (permissions)
Если вы запросили scope permissions, в ответе будет массив прав доступа пользователя в вашем приложении.
Формат прав:
/объект:/действие
Примеры:
/myapp:/read— право на чтение в приложении myapp/myapp:/write— право на запись/myapp:/admin— право администратора/myapp/documents:/read— право на чтение документов
Используйте эти права для контроля доступа в вашем приложении.
Шаг 6: Обновление токенов
Access Token имеет ограниченный срок действия. Когда он истекает, используйте Refresh Token для получения нового Access Token без повторного входа пользователя.
Запрос обновления токена
POST https://ваш-identyx-сервер/api/service/oidc/token
Content-Type: application/json
{
"grant_type": "refresh_token",
"client_id": "ваш_client_id",
"client_secret": "ваш_client_secret",
"refresh_token": "ваш_refresh_token"
}
Ответ при обновлении
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "новый_access_token",
"refresh_token": "новый_refresh_token"
}
При обновлении токенов вы получаете новый access_token И новый refresh_token. Старый refresh_token становится недействительным. Обязательно сохраните оба новых токена.
Обработка истечения токенов
Рекомендуемая стратегия:
- Отслеживайте поле
expires_inпри получении токенов - Обновляйте токен за несколько минут до истечения (например, за 5 минут)
- Если запрос с access_token вернул ошибку 401, попробуйте обновить токен
- Если обновление не удалось, перенаправьте пользователя на страницу входа
Шаг 7: Завершение сессии
Когда пользователь выходит из вашего приложения, важно завершить его сессию в IDENTYX.
Завершение по ID Token
POST https://ваш-identyx-сервер/api/service/oidc/end-session
Content-Type: application/x-www-form-urlencoded
id_token_hint=ваш_id_token
Завершение по Access Token
POST https://ваш-identyx-сервер/api/service/oidc/end-session
Authorization: Bearer ваш_access_token
Что происходит при завершении сессии
- OIDC сессия в IDENTYX помечается как завершенная
- Токены становятся недействительными
- Все IAM сессии пользователя закрываются (опционально)
- Отправляется Backchannel Logout запрос в ваше приложение (если настроено)
После завершения сессии в IDENTYX обязательно завершите сессию пользователя в вашем приложении (удалите токены, очистите cookie, и т.д.)
Backchannel Logout
Backchannel Logout позволяет IDENTYX уведомить ваше приложение о завершении сессии (например, когда пользователь вышел из другого приложения или администратор принудительно завершил сессию).
Настройка Backchannel Logout
При использовании IDENTYX Proxy функциональность Backchannel Logout работает автоматически. Proxy получает уведомления от IDENTYX и завершает сессии приложений.
Если вы не используете Proxy, вам нужно реализовать обработку Backchannel Logout в вашем приложении:
- Создайте эндпоинт для приема уведомлений (например,
/backchannel-logout) - Обрабатывайте POST запросы с параметром
logout_token - Проверьте подпись JWT токена
- Извлеките
sid(session ID) из токена - Завершите соответствующую сессию в вашем приложении
Пример Logout Token:
{
"iss": "https://ваш-identyx-сервер",
"sub": "user123",
"aud": "ваш_client_id",
"iat": 1640991600,
"exp": 1640991780,
"jti": "unique_id",
"sid": "session_id",
"events": {
"http://schemas.openid.net/event/backchannel-logout": {}
}
}
Примеры реализации
Пример на PHP
1. Перенаправление на страницу входа:
<?php
session_start();
$client_id = 'ваш_client_id';
$redirect_uri = 'https://ваше-приложение/callback';
$identyx_url = 'https://ваш-identyx-сервер';
// Генерируем и сохраняем state
$state = bin2hex(random_bytes(16));
$_SESSION['oauth_state'] = $state;
// Генерируем nonce
$nonce = bin2hex(random_bytes(16));
$_SESSION['oauth_nonce'] = $nonce;
// Формируем URL для авторизации
$auth_url = $identyx_url . '/login/oidc?' . http_build_query([
'response_type' => 'code',
'client_id' => $client_id,
'redirect_uri' => $redirect_uri,
'scope' => 'openid profile email permissions',
'state' => $state,
'nonce' => $nonce
]);
// Перенаправляем пользователя
header('Location: ' . $auth_url);
exit;
?>
2. Обработка callback и получение токенов:
<?php
session_start();
$client_id = 'ваш_client_id';
$client_secret = 'ваш_client_secret';
$redirect_uri = 'https://ваше-приложение/callback';
$identyx_url = 'https://ваш-identyx-сервер';
// Проверяем state
if (!isset($_GET['state']) || $_GET['state'] !== $_SESSION['oauth_state']) {
die('Invalid state');
}
// Получаем код авторизации
$code = $_GET['code'] ?? null;
if (!$code) {
die('No code provided');
}
// Обмениваем код на токены
$token_url = $identyx_url . '/api/service/oidc/token';
$post_data = [
'grant_type' => 'authorization_code',
'client_id' => $client_id,
'client_secret' => $client_secret,
'code' => $code,
'redirect_uri' => $redirect_uri
];
$ch = curl_init($token_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
$tokens = json_decode($response, true);
if (isset($tokens['access_token'])) {
// Сохраняем токены в сессии
$_SESSION['access_token'] = $tokens['access_token'];
$_SESSION['refresh_token'] = $tokens['refresh_token'];
$_SESSION['id_token'] = $tokens['id_token'];
// Получаем информацию о пользователе
$userinfo_url = $identyx_url . '/api/service/oidc/userinfo';
$ch = curl_init($userinfo_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $tokens['access_token']
]);
$userinfo_response = curl_exec($ch);
curl_close($ch);
$userinfo = json_decode($userinfo_response, true);
$_SESSION['user'] = $userinfo;
// Перенаправляем на главную страницу
header('Location: /');
exit;
} else {
die('Failed to get tokens');
}
?>
3. Обновление токена:
<?php
function refreshAccessToken($refresh_token) {
$client_id = 'ваш_client_id';
$client_secret = 'ваш_client_secret';
$identyx_url = 'https://ваш-identyx-сервер';
$token_url = $identyx_url . '/api/service/oidc/token';
$post_data = [
'grant_type' => 'refresh_token',
'client_id' => $client_id,
'client_secret' => $client_secret,
'refresh_token' => $refresh_token
];
$ch = curl_init($token_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
// Использование
session_start();
$tokens = refreshAccessToken($_SESSION['refresh_token']);
if (isset($tokens['access_token'])) {
$_SESSION['access_token'] = $tokens['access_token'];
$_SESSION['refresh_token'] = $tokens['refresh_token'];
}
?>
Пример на Node.js (Express)
Установка зависимостей:
npm install express express-session openid-client
Базовая интеграция:
const express = require('express');
const session = require('express-session');
const { Issuer } = require('openid-client');
const app = express();
app.use(session({
secret: 'ваш_секретный_ключ',
resave: false,
saveUninitialized: false
}));
const IDENTYX_URL = 'https://ваш-identyx-сервер';
const CLIENT_ID = 'ваш_client_id';
const CLIENT_SECRET = 'ваш_client_secret';
const REDIRECT_URI = 'https://ваше-приложение/callback';
let client;
// Инициализация OIDC клиента
Issuer.discover(IDENTYX_URL).then(identyxIssuer => {
client = new identyxIssuer.Client({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
redirect_uris: [REDIRECT_URI],
response_types: ['code']
});
});
// Маршрут для входа
app.get('/login', (req, res) => {
const authUrl = client.authorizationUrl({
scope: 'openid profile email permissions',
state: generateRandomString(),
nonce: generateRandomString()
});
res.redirect(authUrl);
});
// Callback маршрут
app.get('/callback', async (req, res) => {
try {
const params = client.callbackParams(req);
const tokenSet = await client.callback(REDIRECT_URI, params);
// Сохраняем токены в сессии
req.session.tokens = {
access_token: tokenSet.access_token,
refresh_token: tokenSet.refresh_token,
id_token: tokenSet.id_token
};
// Получаем информацию о пользователе
const userinfo = await client.userinfo(tokenSet.access_token);
req.session.user = userinfo;
res.redirect('/');
} catch (err) {
console.error(err);
res.status(500).send('Authentication failed');
}
});
// Защищенный маршрут
app.get('/', (req, res) => {
if (!req.session.user) {
return res.redirect('/login');
}
res.send(`Добро пожаловать, ${req.session.user.name}!`);
});
// Выход
app.get('/logout', async (req, res) => {
if (req.session.tokens) {
try {
await client.revoke(req.session.tokens.access_token);
} catch (err) {
console.error('Logout error:', err);
}
}
req.session.destroy();
res.redirect('/login');
});
function generateRandomString() {
return require('crypto').randomBytes(16).toString('hex');
}
app.listen(3000, () => {
console.log('App running on http://localhost:3000');
});
Лучшие практики
- Храните
client_secretв безопасности, никогда не передавайте его на клиент - Всегда проверяйте параметр
stateдля защиты от CSRF - Используйте HTTPS для всех запросов
- Проверяйте подпись и срок действия ID Token
- Храните токены в безопасном месте (httpOnly cookies, серверная сессия)
- Кешируйте well-known конфигурацию
- Обновляйте токены заранее, не дожидаясь истечения
- Используйте connection pooling для HTTP запросов
- Не запрашивайте UserInfo на каждый запрос, кешируйте данные
- Обрабатывайте ошибки при получении и обновлении токенов
- Реализуйте механизм retry при временных сбоях
- Логируйте все важные события аутентификации
- Корректно обрабатывайте Backchannel Logout
- Используйте проверенные OIDC библиотеки для вашего языка
- Тестируйте интеграцию в staging окружении
- Документируйте процесс интеграции для вашей команды
- Следите за обновлениями OIDC стандартов
Устранение проблем
Частые ошибки
| Ошибка | Причина | Решение |
|---|---|---|
invalid_request |
Неверные параметры запроса | Проверьте правильность всех обязательных параметров |
invalid_client |
Неверный client_id или client_secret | Убедитесь, что используете правильные учетные данные из IDENTYX |
invalid_grant |
Код авторизации истек или уже использован | Используйте код немедленно после получения, каждый код можно использовать только один раз |
redirect_uri_mismatch |
Redirect URI не совпадает с зарегистрированным | Убедитесь, что redirect_uri точно совпадает с указанным в настройках приложения |
Unauthorized (401) |
Access token истек или недействителен | Обновите токен используя refresh_token |
Советы по отладке
- Проверьте, что все URL правильные и доступные
- Убедитесь, что используете правильные client_id и client_secret
- Проверьте, что redirect_uri зарегистрирован в IDENTYX
- Включите подробное логирование HTTP запросов
- Используйте инструменты разработчика браузера для отслеживания redirects
- Проверьте журнал событий в IDENTYX для диагностики проблем
Тестирование интеграции
Перед запуском в production убедитесь, что протестировали следующие сценарии:
- Первичный вход — пользователь входит в приложение впервые
- Повторный вход — пользователь входит повторно (должен быть авторизован автоматически если есть активная сессия)
- Выход — пользователь выходит из приложения
- Истечение токена — обновление access_token через refresh_token
- Истечение сессии — что происходит когда истекает refresh_token
- Разные методы входа — локальная аутентификация, LDAP, внешние провайдеры
- 2FA — вход с двухфакторной аутентификацией
- Согласие с офертой — если настроено для вашего приложения
- Права доступа — проверка прав пользователя из scope permissions
- Принудительное завершение сессии — администратор завершает сессию пользователя
Полезные библиотеки
Для упрощения интеграции рекомендуем использовать проверенные OIDC библиотеки:
| Язык | Библиотека | Описание |
|---|---|---|
| PHP | jumbojett/openid-connect-php | Легкая библиотека для OIDC |
| Node.js | openid-client | Сертифицированная OIDC библиотека |
| Python | authlib | Универсальная библиотека для OAuth и OIDC |
| Java | Spring Security OAuth | Интеграция с Spring Framework |
| .NET | IdentityModel.OidcClient | OIDC клиент для .NET |
| Go | coreos/go-oidc | OIDC клиент для Go |
Связанные разделы
- 31. Обзор OIDC — общее описание протокола OIDC в IDENTYX
- 32. Создание OIDC приложения — регистрация и настройка приложений
- 33. IDENTYX Proxy — использование встроенного прокси вместо прямой интеграции
- 55. Proxy интеграция — интеграция через IDENTYX Proxy
- 37. IAM сессии — управление сессиями пользователей
- 38. OIDC сессии — просмотр и управление OIDC сессиями
После интеграции вашего приложения через OIDC, изучите раздел 55. Proxy интеграция для упрощенного способа подключения приложений через IDENTYX Proxy.