Настройка аутентификации OIDC#
В этом руководстве описано, как настроить аутентификацию OpenID Connect (OIDC), используя Google в качестве провайдера идентификации и веб-сервер Angie со скриптами на Lua.
Эта реализация защищает внутренние конечные точки с помощью аутентификации OAuth2/OIDC и демонстрирует один из способов ограничить доступ по доменам электронной почты. Это лишь один из возможных подходов; вы можете реализовать контроль доступа любым удобным вам способом — например, поддерживать списки разрешённых пользователей, проверять принадлежность к домену или группам в ответе провайдера или использовать произвольные claims вашего внутреннего IAM.
Совет
Эта реализация OIDC предоставляет базовый фундамент для аутентификации, но должна быть адаптирована для продакшена с учётом мер безопасности, мониторинга и требований политики безопасности вашей организации.
Архитектура#
Предлагаемая конфигурация OIDC включает:
Angie — с поддержкой Lua-модуля для обработки OIDC
lua-resty-openidc — Lua-библиотека OpenResty для аутентификации через OIDC
Google OAuth2 — провайдер идентификации
Docker Compose — используется в примере только для быстрого запуска; в продакшене используйте подходящий вариант развертывания
Требования#
Перед настройкой OIDC убедитесь, что у вас есть:
Веб-сервер Angie с поддержкой Lua-модуля
Docker и Docker Compose (для развертывания)
Проект в Google Cloud Console
OAuth2-учётные данные от Google
Настройка Google OAuth2#
Чтобы настроить Google как OIDC-провайдера:
Перейдите в Google Cloud Console
Создайте новый проект или выберите существующий
Настройте экран согласия OAuth (External или Internal) и опубликуйте его
Создайте OAuth2-учётные данные:
Тип приложения: Web application
Разрешённые URI для редиректа:
http://localhost/auth/callback
Сохраните свои
client_idиclient_secret
Примечание
Стандартные Google Identity Services уже поддерживают OIDC; устаревший Google+ API не требуется. Включайте дополнительные Google API только при необходимости.
Настройка конфигурации#
Начнём с необходимых конфигурационных файлов. Развёртывание через Docker использует следующий конфиг: Эта конфигурация: Использует templated-образ Angie с поддержкой Lua Загружает Lua-модуль для OIDC Пробрасывает порт 80 Монтирует локальные конфигурационные файлы Для запуска «из коробки» скачайте
Создайте скрипт OIDC,
который обрабатывает логику аутентификации с использованием библиотеки
Параметры конфигурации: Настройте Angie с необходимыми блоками location
для аутентификации OIDC. Чтобы защитить ресурсы: Здесь: Путь Запросы проксируются к внутреннему API на Настройка OAuth2-эндпоинтов: Назначение маршрутов: Настройте ограниченный доступ к API: Это обеспечивает: Доступ к status API Angie Доступ только с localhost OIDC-защиту при доступе через Конфигурация Docker Compose#
services:
angie:
image: docker.angie.software/angie:templated
environment:
ANGIE_LOAD_MODULES: "lua"
ports:
- 80:80
volumes:
- ./files/etc/angie/http.d:/etc/angie/http.d
OIDC quick-start bundle,
установите client_id и client_secret в
files/etc/angie/http.d/oidc.lua,
и всё сразу заработает.Скрипт аутентификации OIDC#
lua-resty-openidc:access_by_lua_block {
local res, err = require("resty.openidc").authenticate({
redirect_uri = "http://localhost/auth/callback",
discovery = "https://accounts.google.com/.well-known/openid-configuration",
logout_path = "/auth/logout",
redirect_after_logout_uri = "/auth/logged-out",
revoke_tokens_on_logout = true,
client_id = "YOUR_CLIENT_ID",
client_secret = "YOUR_CLIENT_SECRET"
})
}
redirect_uri: URL-адрес обратного вызова после успешной аутентификацииdiscovery: discovery-endpoint Google OIDClogout_path: путь выхода пользователяredirect_after_logout_uri: куда перенаправлять после выходаrevoke_tokens_on_logout: отзывать токены при logoutclient_id и client_secret: учётные данные OAuth2Конфигурация Angie#
Защищённые ресурсы#
location /internal/ {
include /etc/angie/http.d/oidc.lua;
proxy_pass http://127.0.0.1/status/;
}
/internal/ защищён OIDC/status/Конечные точки аутентификации#
location /auth/callback {
include /etc/angie/http.d/oidc.lua;
}
location /auth/logout {
include /etc/angie/http.d/oidc.lua;
}
location /auth/logged-out {
default_type text/plain;
return 200 "You have been logged out. Bye!";
}
/auth/callback: обработка callback от Google/auth/logout: инициирует выход/auth/logged-out: страница после выходаДоступ к внутреннему API#
location /status/ {
api /status/;
allow 127.0.0.1;
deny all;
}
/internal/
Этапы развертывания#
Обновление конфигурации#
Обновите учетные данные OAuth2 в файле Lua:
Замените значения в
oidc.lua:client_idна ваш Google OAuth2 Client IDclient_secretна ваш Client Secret
Запуск сервисов#
Запустите Docker-сервисы:
$ docker-compose up -d
Проверьте работу:
Откройте
http://localhost/internal/Должна появиться переадресация на Google
После логина вы попадёте в защищённый раздел
Настройки безопасности#
Ограничение по домену e-mail#
Реализуйте проверку домена:
if not string.match(res.user.email, "gmail.com$") then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
В продакшене:
замените
gmail.comна домен вашей компаниииспользуйте whitelist пользователей
добавьте контроль ролей
Управление токенами#
В реализации OIDC предусмотрено:
автоматический отзыв токенов при logout (
revoke_tokens_on_logout = true)безопасное управление сессией в lua-resty-openidc
следование лучшим практикам OAuth2/OIDC
Предупреждение
Для продакшена:
Всегда используйте HTTPS для callback-адресов
Храните client secrets безопасно, не в репозитории
Настройте корректные таймауты и обновление сессий
Мониторьте логи аутентификации
Поток аутентификации#
Стандартный поток OIDC выглядит так:
Пользователь запрашивает защищённый URL (например
http://localhost/internal/)При отсутствии сессии — перенаправление на Google OAuth2
Пользователь входит в аккаунт Google
Google возвращает код авторизации на
/auth/callbackСервер запрашивает access token и ID token
Проверяет данные пользователя (включая домен e-mail)
Предоставляет доступ к ресурсу
Процесс logout:
Пользователь переходит по
http://localhost/auth/logoutТокены отзываются у Google
Локальная сессия очищается
Переход на
/auth/logged-out
Расширенная конфигурация#
Ограничить доступ одним доменом:
if not string.match(res.user.email, "yourcompany.com$") then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
Несколько разрешённых доменов:
local allowed_domains = {"company1.com", "company2.com", "gmail.com"}
local email_valid = false
for _, domain in ipairs(allowed_domains) do
if string.match(res.user.email, domain .. "$") then
email_valid = true
break
end
end
if not email_valid then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
Доступ к данным пользователя#
Получить дополнительные claims:
-- Доступ к данным из ID token
local user_name = res.user.name
local user_picture = res.user.picture
local user_locale = res.user.locale
local user_email = res.user.email
Эти данные можно использовать для логирования, персонализации или дополнительных решений по контролю доступа.