Adding authentication to a shiny server

December 5, 2014
By

(This article was first published on log Fold Change » r, and kindly contributed to R-bloggers)

Umph, that was a tough one. I spent ages figuring out how to do it correctly. I have a server running apache (on port 80) and shiny on port (say) 11111. Shiny has its own document root, and within this root, we have a shiny app, say, “example”. So to view this app you need to type http://server:1111/example/. So far, so good. What I wanted, though, was (i) some kind of password protection for the app, and (ii) calling the app from the URL http://server/example/. Turns out it can be done, but it was not trvial.

First, I modified configuration of the shiny server to listen only to the specified port and only to the localhost; this prevents anyone from any other machine to connect to shiny:

server {
  listen 11111 127.0.0.1;
  location / {
    site_dir /srv/shiny-server;
    log_dir /var/log/shiny-server;
    directory_index off;
  }
}

Now to apache. In the httpd.conf file, I have added The following:

         

            Redirect /example /example/
            ProxyPass /example/ http://127.0.0.1:11111/example/
            ProxyPassReverse /example/ http://127.0.0.1:11111/example/

            
                AuthType Basic
                AuthName "Enter your login name and password"
                AuthUserFile /etc/httpd/htpasswd.users
                Require valid-user
            

         

This makes apache work as a proxy to the shiny server; however, with the added benefit of a simple authentication for the shiny contents.

It took me quite some time to figure out that without the Redirect directive above, http://server/example/ works, but http://server/example (without the slash) doesn’t.

Finally, I created new users with htpasswd.

Update: Interestingly, shiny cannot handle HEAD requests. HEAD request is when a program asks whether a page is there rather than downloading the whole page. Apparently, this is how CRAN checks whether a site is available. In any case, just after the Virtualhosts directive, I have added the following:

    RewriteEngine on
    RewriteCond %{REQUEST_METHOD} ^HEAD
    RewriteRule ^/example(.*) /foo/index.html

This rewrites the requested URL to example only if the request method is HEAD, and instead asking the shiny server, it asks itself — and since the file /foo/index.html exists, we get 200 OK.

Update 2: I found why shiny is returning 404 to HEAD requests. In the file shiny/R/server.R, in line 177, you have the statement

  if (!identical(req$REQUEST_METHOD, 'GET'))
    return(NULL)

Obviously, any request other than “GET” gets turned down, as NULL results in a 404.

As a workaround, I have changed it to

  if(identical(req$REQUEST_METHOD, 'HEAD'))
    return(httpResponse(200, content="OK"))

  if (!identical(req$REQUEST_METHOD, 'GET'))
    return(NULL)

Of course, the down side is that it replies with “OK” even if the given resource does not exist. I am testing a proper way of handling these requests, but at the moment this will have to do.

To leave a comment for the author, please follow the link and comment on their blog: log Fold Change » r.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: Data science, Big Data, R jobs, visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...



If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.

Sponsors

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)