Looking for help using sessions and nginx as a proxy

I'm using prodigy v1.11.4 but I don't see anything in more recent changelogs that would affect this.

server {
  listen 80;

  # general proxy with password protection
  location / {
    auth_basic "Password Required";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://0.0.0.0:8080;
  }

  # root page requires specifying a session name (username)
  location = / {
    auth_basic "Password Required";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://0.0.0.0:8080?session=$remote_user;
  }

  # project page also requires specifying a session name (username)
  location /project {
    auth_basic "Password Required";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://0.0.0.0:8080/project/$remote_user;
  }
}

I've also set the PRODIGY_ALLOWED_SESSIONS=user1 to include the desired user.

From the logs:

✨  Starting the web server at http://0.0.0.0:8080 ...
Open the app in your browser and start annotating!

INFO:     Started server process [11]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
INFO:     127.0.0.1:50146 - "GET /?session=user1 HTTP/1.0" 200 OK
INFO:     127.0.0.1:50148 - "GET /bundle.js HTTP/1.0" 200 OK
INFO:     127.0.0.1:50150 - "GET /project/user1 HTTP/1.0" 200 OK
19:27:25: POST: /get_session_questions
19:27:25: CONTROLLER: Getting batch of questions for session: None
19:27:25: FEED: Finding next batch of questions in stream
19:27:25: FEED: re-adding open tasks to stream
19:27:25: FEED: Stream is empty
19:27:25: FEED: adding tasks from other sessions to None queue.
19:27:25: FEED: batch of questions requested for session None: 4
19:27:25: RESPONSE: /get_session_questions (4 examples)

Note how the GETs are all correct, but the CONTROLLER and FEED lines all report the session as None. It works fine if I drop the proxy and add the user_id manually to the URL. What other magic is needed beyond adding it to the URL of the root page and project URI?

The same result (and log) comes from using a rewrite:

server {
  listen 80;

  # general proxy with password protection
  location / {
    rewrite ^(/)$ $1?session=$remote_user break;
    rewrite ^(/project)$ $1/$remote_user break;
    auth_basic "Password Required";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://0.0.0.0:8080;
  }
}

Using nginx and the proxy works fine. And if I don't do any rewrite, but add the session_name on the url manually, it works fine through the proxy. There is likely something small. Someone has to have gotten this to work. Any help?I suspect that the project modification isn't necessary if the original query variable ended up working correctly.

For the record, I do need to authenticate more than one user.

Ok, this almost seems to be the answer:

server {
  listen 80;

  if ($request_uri = "/") {
    return 302 /?session=$remote_user;
  }

  location / {
    auth_basic "Password Required";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://0.0.0.0:8080;
  }
}

$request_uri contains both the URI and the arguments. This checks if no session argument is present and does a redirect. Digging into the bundle.js code, it seems the page looks to the window.location variable for the session query string. Since the proxy was only adding the session information on the way from the page to the server, the page still thought it was http://localhost not http://localhost?session=user1. As such, the page was never aware of the session in the original code. A redirect is required because it tells the browser to go to a different URL (one with the session information).

The problem is that it remembers the redirect with an empty remote_user string even after you go through the login. You then need to refresh it by manually going back to http://localhost and it will pick up the login name. The solution? Ain't pretty since nginx doesn't allow boolean concatenation of if conditions.

server {
  listen 80;

  # see if both conditions exist to trigger a redirect
  set $redirect_ready 0;
  if ($remote_user != '') { # a user name exists
    set $redirect_ready 1;
  }
  if ($request_uri = "/") { # the base path is given without a session name
    set $redirect_ready 1$redirect_ready;
  }
  if ($redirect_ready = 11) {
    return 302 /?session=$remote_user;
  }

  location / {
    auth_basic "Password Required";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://0.0.0.0:8080;
  }
}
1 Like