0

I'm trying to use the auth_request module in conjunction with the more_set_input_headers to automatically login my users into web apps.

Basically, it works like this:

  1. Users have some session cookie that authenticates them.
  2. I have a PHP script (auth.php) that validates the cookie and returns their proper username as a response header.
  3. Nginx calls auth.php with auth_request, and sets the username in a variable.
  4. Nginx then calls the web app with a request header set to the correct username.
  5. The web app reads the header, and logs the user in.

This works, but strangely inconsistent. The issue is that when a user accesses the web app on /app/, it works, but when the app is accesssed on /app/index.php, it never receives the header from nginx.

I've created a mock configuration that reproduces the error.

Nginx site config:

server {
    server_name www.example.com
    index index.php index.html;

    # --- Internal auth
    location /auth {
        internal;
        root /var/www/sf;

        location /auth/auth.php {
            fastcgi_pass unix:/var/run/php5-fpm.sock;
            include includes/fastcgi_params;

            fastcgi_pass_request_body off;
            fastcgi_param CONTENT_LENGTH 0;
        }

        location /auth {
            deny all;
        }
    }

    location / {

        auth_request /auth/auth.php;

        auth_request_set $auth_header $upstream_http_x_auth_header;
        more_set_input_headers 'X-Test-Header: $auth_header';

        location /app {
            root /var/www/sf;

            # Allow these locations
            location = /app/ {
                allow all;
            }

            location /app/index.php {
                fastcgi_pass unix:/var/run/php5-fpm.sock;
                include includes/fastcgi_params;
            }

            # Deny everything else
            location /app/ {
                deny all;
            }
        }

    }
}

/var/www/sf/auth/auth.php:

<?php

// Mock precondition checker
function is_allowed() {
    return true;
}

// Set the default response code
http_response_code(403);

if(!is_allowed())
    exit();

// Return our header and the OK response code
header("X-Auth-Header: myusername");
http_response_code(200);

/var/www/sf/app/index.php:

<?php

if(empty($_SERVER["HTTP_X_TEST_HEADER"]))
    exit("No header was supplied by nginx.");

exit("Nginx supplied header value: ". $_SERVER["HTTP_X_TEST_HEADER"]);

Response when doing a GET request to /app/:

Nginx supplied header value: myusername

Response when doing a GET request to /app/index.php:

No header was supplied by nginx.

Would anyone have an idea as to what is going on here?

I'm using Debian Wheezy with the nginx-extras package from DotDeb (1.6.0-1~dotdeb.1).

(a small note: when you replace 'more_set_input_headers 'X-Test-Header: $auth_header';' with 'more_set_input_headers 'X-Test-Header: foobar';', the web app always receives a header)

1

This behaviour is likely due to the fact that more_set_input_headers handler is executed before access phase (where auth_request works), and hence only changes a request if it's internally redirected.

Solution to the problem is to stop using more_set_input_headers (it's anyway very wrong, request headers shouldn't be changed) and use native fastcgi_param instead:

fastcgi_param HTTP_X_TEST_HEADER $auth_header;

Copied from http://mailman.nginx.org/pipermail/nginx/2014-June/044281.html.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.