NGINX stuck in endless redirect loop when trying to use auth_request

authenticationnginxproxypassreverse-proxy

nginx version: 1.14.2

Im trying to use nginx auth_request to authenticate users for accessing a subdomain on which a page is served that i cant otherwise influence.

I have a python + flask based login page which returns 200 if the user is logged in, and returns 401 if the user is not logged in.

I have configured a proxy_pass subdomain in nginx like this:

server {
    listen 80;
    server_name sub.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name sub.example.com;

    location / {
        auth_request /myauth;
        auth_request_set $auth_status $upstream_status;

        proxy_pass http://localhost:8001;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    location = /myauth {
        proxy_pass https://login.example.com/;
        proxy_pass_request_body off; 

        proxy_set_header Content-Length "";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    error_page 401 = @error401;
    location @error401 {
        return 302 https://login.example.com/login/?next=https://$http_host$request_uri ;
    }
}

The nginx config for the login page looks like this:

server {
    listen                    80;
    server_name               login.example.com;
    return                    301 https://$server_name$request_uri;
}

server {
    listen                    443 ssl http2;
    server_name               login.example.com;
    client_max_body_size      128M;

    location / {
        include                  uwsgi_params;
        uwsgi_pass               unix:/srv/loginpage/loginpage.sock;
    }
}

This is what my access log looks like:

[24/Dec/2019:04:17:28 +0100] "login.example.com" "GET /login/?next=https://sub.example.com/ HTTP/2.0" 302 263
[24/Dec/2019:04:17:28 +0100] "login.example.com" "GET / HTTP/1.0" 401 10
[24/Dec/2019:04:17:28 +0100] "sub.example.com" "GET / HTTP/2.0" 302 161
[24/Dec/2019:04:17:28 +0100] "login.example.com" "GET /login/?next=https://sub.example.com/ HTTP/2.0" 302 263
[24/Dec/2019:04:17:28 +0100] "login.example.com" "GET / HTTP/1.0" 401 10
[24/Dec/2019:04:17:28 +0100] "sub.example.com" "GET / HTTP/2.0" 302 161
[24/Dec/2019:04:17:28 +0100] "login.example.com" "GET /login/?next=https://sub.example.com/ HTTP/2.0" 302 263
[24/Dec/2019:04:17:28 +0100] "login.example.com" "GET / HTTP/1.0" 401 10
[24/Dec/2019:04:17:28 +0100] "sub.example.com" "GET / HTTP/2.0" 302 161

The debug log can be found here: https://gist.github.com/laundmo/c23345061940bbef59703d43e93a9ba0

The login system works, i can login and get a 200 response on https://login.example.com/, if im logged out i get redirected to the login page, even when accessing sub.example.com while logged out. The ridirect back also seems to work. Just for some reason once i get redirected back to sub.example.com i get redirected to login.example.com whihc redirects me to sub.example.com and so on…

edit: if this belongs on another stackexchange page, please tell me and i will delete this and move it there

Best Answer

in the end it was so simple

the flask app i was trying to use as a authenticator, didnt store the session across subdomains

if anyone else attempts this, make sure to include app.config["SESSION_COOKIE_DOMAIN"] = ".example.com" so that flask knows to store the session across subdomains