5

I've successfully implemented an nginx reverse proxy for my shiny-server in order to have SSL and user authentication. However, there is still a gap that I can't figure out. Is there a way for my shiny app to determine which user is actually logged in?

Here's my /etc/nginx/sites-available/default

server {
listen 80;
return 301 https://$host$request_uri;
}

server {

listen 443;
server_name myserver.com;

ssl_certificate           /etc/nginx/cert.crt;
ssl_certificate_key       /etc/nginx/cert.key;

ssl on;
ssl_session_cache  builtin:1000  shared:SSL:10m;
ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;

access_log            /var/log/nginx/shiny.log;

location / {

  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;

  # Fix the “It appears that your reverse proxy set up is broken" error.
  proxy_pass          http://localhost:3838;
  proxy_read_timeout  90;

  proxy_redirect      http://localhost:3838 https://myserver.com;
  auth_basic "Restricted";
  auth_basic_user_file /etc/nginx/.htpasswd;
  proxy_set_header Authorization $http_authorization;
  proxy_pass_header  Authorization;
}
  }

With the last two lines of my location I expect to have a header with the user name. I found that tip here. I found this which allows me to see my header information but none of the headers I see are my user name.

Edit:

With Bert Neef's citation, I see why the above didn't work. However, the server does have access to the HTTP_SEC_WEBSOCKET_KEY header which is unique across sessions. It seems that if we can get Nginx to log that value then the server can look at that code to match up the header to an actual user. That being said, I don't know if that is feasible and I don't know how to get Nginx to log that value.

Community
  • 1
  • 1
Dean MacGregor
  • 11,847
  • 9
  • 34
  • 72

1 Answers1

3

Based on the Shiny Docs this a Shiny Server Professional feature only and you need to use the whitelist_headers directive to get those headers:

4.9 Proxied Headers Typically, HTTP headers sent to Shiny Server will not be forwarded to the underlying Shiny application. However, Shiny Server Professional is able to forward specified headers into the Shiny application using the whitelist_headers configuration directive, which can be set globally or for a particular server or location.

Update: just tested the whitelist-headers option in a non-pro shiny server install, and I can't get the custom headers to show. I did verify the headers were send on by nginx by using netcat to show me the incoming data (nc -l 8080 and a quick change to proxy_pass in the nginx.conf file).

Update 2: can't get NGINX to log the HTTP_SEC_WEBSOCKET_KEY header (the authorization header is logged after specifying it in the log specification) and I can't see it in the traffic between nginx and Shiny Server, I think it either boils down to getting Shiny Server Professional or to modifying the shiny source code to pass the authorization header to the application.

Bert Neef
  • 743
  • 1
  • 7
  • 14
  • Sorry if this seems harsh but I'm not going to award the bounty for what amounts to "you have to buy the pro edition". Shiny server accepts at least some headers and even the snippet you quoted is qualified with "Typically" so there's got to be a way. – Dean MacGregor Nov 04 '15 at 19:04
  • that's entirely up to you. I hope someone else can provide the way. – Bert Neef Nov 04 '15 at 19:18
  • 1
    It seems like the way to do this is to use the HTTP_SEC_WEBSOCKET_KEY header. It is available to shiny and it seems to be unique for each login so if we can have nginx log what each user has for that header then shiny can look at that log and match up the websocket_key header to an actual user. I don't know if that is doable nor do I know how to do the logging on the nginx side. – Dean MacGregor Nov 04 '15 at 19:37
  • I tried to get a bit of logging going with nginx to its access.log, I can simply log the authentication header, it's base64 encoded but getting the username from that is easy, the HTTP_SEC_WEBSOCKET_KEY does not seem to be present, when I tell nginx to log it nothing shows up in the log, and when I try the netcat trick I don't see it as well. Maybe its internal to shiny server, I don't have tcpdump installed at the moment. Will see if I can get some more info by doing a packet capture. Do keep in mind this is not a very secure approach to user handling, even if it would work. – Bert Neef Nov 05 '15 at 08:56
  • Doing that stuff wouldn't make it any easier to get past the NginX authentication and I'm not worried about any of the users spoofing one another. – Dean MacGregor Nov 05 '15 at 14:16
  • I don't think I can get this to work, the WEBSOCKET_KEY is not showing up in any place I can log as far as I can tell, for example I tried ngrep as ngrep -d lo -W byline | grep -ie "WEBSOCKET" -e "Authorization", I do get the Authorization headers out of the traffic but no websocket headers. – Bert Neef Nov 05 '15 at 17:21