OIDC#

Модуль добавляет аутентификацию по протоколу OpenID Connect (OIDC). Когда неаутентифицированный пользователь запрашивает защищенную страницу, Angie перенаправляет его на страницу входа провайдера OIDC, например Google, Azure AD или Keycloak; после успешного входа пользователь возвращается на исходную страницу. Данные пользователя Angie передает бэкенду в переменных, поэтому самому бэкенду не нужен собственный код аутентификации.

Другой способ настроить аутентификацию OIDC в Angie, на скриптах Lua, описан в руководстве Настройка аутентификации OIDC.

Установка#

Для установки модуля используйте один из следующих пакетов:

  • Angie: angie-module-oidc;

  • Angie PRO: angie-pro-module-oidc.

Директивы#

Основные директивы модуля:

  • oidc_provider — определяет провайдера: его issuer, учетные данные клиента, путь обратного вызова redirect_uri, время жизни сессии (session_timeout, по умолчанию 8 часов) и другие настройки;

  • oidc_session_store — определяет именованное хранилище сессий в памяти (type memory) или в Redis (type redis), которое провайдер использует, только если оно указано в его параметре session_store; провайдер без session_store хранит сессии в хранилище в памяти по умолчанию;

  • auth_oidc — включает аутентификацию через указанного провайдера; off отключает ее;

  • auth_oidc_mode — задает обработку неаутентифицированных запросов: require (по умолчанию) перенаправляет их к провайдеру, а verify пропускает дальше, устанавливая $oidc_authenticated в 0;

  • auth_oidc_bearer — дополнительно принимает токен доступа в заголовке Authorization: Bearer: запрос с таким токеном аутентифицируется только по нему и при неудачной проверке токена получает ответ 401; остальные запросы аутентифицируются по сессионной cookie;

  • oidc_base_url — задает базовый URL обратного вызова (схему, хост и, при необходимости, порт) вместо взятого из запроса.

Данные аутентификации модуль передает в переменных: $oidc_claim_name содержит утверждение (claim) из ID-токена пользователя, например $oidc_claim_sub или $oidc_claim_email (значения-массивы объединяются через запятую); $oidc_id_token и $oidc_access_token содержат сами токены; $oidc_authenticated равна 1 для аутентифицированного запроса и 0 в остальных случаях. Для запроса, аутентифицированного по токену Bearer, задаются только переменные с утверждениями и $oidc_authenticated.

Все директивы, параметры провайдера и хранилища, а также переменные описаны в документации модуля.

Загрузка модуля#

Для работы с модулем необходимо загрузить его в контексте main{}:

load_module modules/ngx_http_oidc_module.so;

Пример конфигурации#

http {
    oidc_provider google {
        issuer "https://accounts.google.com";
        client_id "your-client-id.apps.googleusercontent.com";
        client_secret "your-client-secret";
        redirect_uri "/oauth2/callback";
    }

    server {
        listen 80;
        server_name myapp.example.com;

        # Аутентификация для всего сервера
        auth_oidc google;

        location / {
            proxy_pass http://127.0.0.1:9090;
            proxy_set_header X-User-ID $oidc_claim_sub;
        }

        location /_oidc_http_fetch {
            internal;
            auth_oidc off;

            proxy_pass $oidc_fetch_url;
            proxy_method $oidc_fetch_method;
            proxy_set_header Content-Type $oidc_fetch_content_type;
            proxy_set_header Content-Length $oidc_fetch_content_length;
            proxy_set_header Authorization $oidc_fetch_bearer;

            proxy_set_header Host $proxy_host;
            proxy_set_header Accept-Encoding "";
            proxy_pass_request_body on;
            proxy_max_temp_file_size 0;
            subrequest_output_buffer_size 200k;

            proxy_http_version 1.1;
            proxy_set_header Connection "";

            proxy_ssl_verify on;
            proxy_ssl_verify_depth 2;
            proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
            proxy_ssl_server_name on;
            proxy_ssl_name $proxy_host;

            proxy_connect_timeout 30s;
            proxy_send_timeout 30s;
            proxy_read_timeout 30s;
        }
    }
}

Значения client_id и client_secret выдает провайдер при регистрации приложения. Там же нужно зарегистрировать полный URL обратного вызова, в этом примере http://myapp.example.com/oauth2/callback: модуль составляет его из схемы, имени хоста из запроса и порта, на котором Angie принял соединение (порт указывается, если он отличается от 80 для HTTP и 443 для HTTPS), а затем добавляет путь redirect_uri.

В рабочей среде сайт следует обслуживать по HTTPS: атрибут Secure модуль добавляет к своим cookie, только если клиент подключается к Angie по TLS. Если TLS завершается на прокси перед Angie, задайте в oidc_base_url внешний URL со схемой https, чтобы URL обратного вызова совпадал с зарегистрированным.

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

Собственные запросы к провайдеру, например получение документа обнаружения (discovery) и ключей провайдера или обмен кода авторизации на токены, модуль выполняет через location /_oidc_http_fetch. Имя этого location фиксировано; если его нет, проверка конфигурации завершается ошибкой. В этом location:

  • proxy_pass $oidc_fetch_url и proxy_set_header Content-Type $oidc_fetch_content_type обязательны: без заголовка Content-Type провайдер может отклонить запрос токена, и вход не состоится.

  • proxy_set_header Authorization $oidc_fetch_bearer нужна, только если в блоке провайдера включен userinfo.

  • subrequest_output_buffer_size должна вмещать самый большой ответ провайдера: если документ обнаружения или набор ключей не помещается в буфер, подзапрос завершается ошибкой, и браузер получает пустой ответ.

  • Директивы proxy_ssl_* нужны для провайдера с URL https в issuer, как у Google: они проверяют сертификат провайдера по доверенным сертификатам ЦС и передают имя провайдера в SNI.

  • internal делает location недоступным извне, а auth_oidc off исключает его из аутентификации.

Остальные строки этого location — настройки, рекомендованные авторами модуля.

Имя хоста провайдера Angie разрешает собственным резолвером; по умолчанию он обращается к DNS-серверам, перечисленным в /etc/resolv.conf. Добавляйте директиву resolver в этот location, только если настройки по умолчанию не подходят.

Модуль проверяет аутентификацию на этапе доступа, поэтому директива return в защищенном location отвечает раньше этой проверки; защищенное содержимое отдавайте через proxy_pass или из файлов.

Порядок аутентификации#

С приведенной выше конфигурацией пользователь получает доступ так:

  1. Браузер запрашивает страницу без сессионной cookie. Angie перенаправляет браузер на конечную точку авторизации провайдера, добавляя в URL параметры state, nonce и параметры PKCE.

  2. Пользователь выполняет вход на странице провайдера, и провайдер перенаправляет браузер на /oauth2/callback с кодом авторизации.

  3. Angie обменивает код на токены через /_oidc_http_fetch, проверяет ID-токен, устанавливает сессионную cookie NGX_OIDC_SESSION и перенаправляет браузер на исходную страницу.

  4. Запросы с сессионной cookie доходят до бэкенда без перенаправлений; бэкенд получает идентификатор пользователя, утверждение sub, в заголовке X-User-ID.

Дополнительная информация#

Версия: 0.8.0

Подробная документация и исходный код доступны по ссылке: kjdev/nginx-oidc