Nginx auth_request и auth_basic

Вопрос или проблема

Я пытаюсь настроить nginx для выполнения аутентификации пользователей перед доступом к ресурсу. В настоящее время моя конфигурация выглядит следующим образом:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    location = /test {
        satisfy any;
        auth_basic "test";
        auth_basic_user_file "/usr/local/nginx/htpasswd";        
        auth_request /auth;
        proxy_pass http://localhost:9000/;
    }
    
    location = /auth {
        proxy_pass http://192.168.111.101:8080/auth;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
    }
}

Итак, я хочу, чтобы nginx запрашивал у пользователя пароль, используя процедуру “auth_basic”. (это не сработает, так как пользователь не находится в файле auth_basic_user_file)

Затем nginx должен попробовать “auth_request” и также предоставить имя пользователя/пароль, использованные в “auth_basic”. То же решение, что и здесь: https://stackoverflow.com/questions/23299623/nginx-authentication-with-auth-request-module, однако кажется, что nginx в некотором смысле отдает предпочтение “auth_request”, так что это выполняется первым, а “auth_basic” выполняется после.

Есть идеи, что я делаю не так?

Самое важное для загрузки файла через POST:

proxy_pass_request_body off;
proxy_set_header Content-Length "";

Если вы только получаете, то вышеуказанное не нужно добавлять.

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

Учитывая это, в nginx нет механизма для различения клиента, который еще не пытался выполнить базовую аутентификацию, и клиента, который был аутентифицирован через механизм auth_request.

Если вы просто хотите предоставить два разных метода входа, то вам нужно реализовать их обоих в поставщике аутентификации (или мультиплексировать через поставщика аутентификации), а не в nginx.

Тем не менее, если вы только хотите использовать базовую аутентификацию для неинтерактивного доступа, то вы можете использовать наличие заголовка “Authorization” в качестве индикатора для nginx.

Ответ или решение

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

Решение проблемы

  1. Основы конфигурации:

    Обратите внимание, что при использовании auth_request, Nginx не может различить, был ли клиент уже аутентифицирован при помощи auth_basic. Таким образом, если вы хотите использовать оба метода аутентификации, вам нужно управлять логикой аутентификации через вашу собственную аутентификационную систему (допустим, через API), которая должна поддерживать оба метода.

  2. Настройка конфигурации:

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

    server {
       listen 80 default_server;
       listen [::]:80 default_server;
    
       location = /test {
           satisfy any;
           auth_basic "Restricted Access";
           auth_basic_user_file "/usr/local/nginx/htpasswd";
           auth_request /auth;
    
           proxy_pass http://localhost:9000/;
           # Обратите внимание, что следующие настройки нужны для POST запросов
           proxy_pass_request_body off;
           proxy_set_header Content-Length "";
           proxy_set_header X-Original-URI $request_uri;
       }
    
       location = /auth {
           internal;  # Эта локация будет использоваться только внутренне
           proxy_pass http://192.168.111.101:8080/auth;
           proxy_pass_request_body off;
           proxy_set_header Content-Length "";
           proxy_set_header X-Original-URI $request_uri;
           # Перенименование или добавление заголовков авторизации (по желанию)
           proxy_set_header Authorization $http_authorization;
       }
    }
  3. Обработка заголовков авторизации:

    Важно убедиться, что заголовок Authorization передается в запросе к вашему auth серверу. Ваша конфигурация выше уже включает это с помощью proxy_set_header Authorization $http_authorization;. Это позволит вашему аутентификационному серверу понимать, какие учетные данные были переданы пользователем, и проверять их.

  4. Обработка состояния:

    Поскольку auth_request не сохраняет состояние сессии, вам может понадобиться подход на стороне вашего аутентификационного сервера, который сможет корректно обрабатывать запросы, пришедшие без аутентификации (auth_basic). Рекомендуется использовать сервер Auth, который проверяет наличие заголовка Authorization, и если он отсутствует, возвращает ошибку 401 (Unauthorized) или 403 (Forbidden), что заставит клиентское приложение предложить пользователю ввести свои учетные данные.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...