Open havok2063 opened 3 years ago
Hi Brian,
in https://github.com/voila-dashboards/voila/pull/414 we added some of the CGI and vars to the kernel, which are in https://datatracker.ietf.org/doc/html/rfc3875 . I don't see anything for cookies. I guess we should be able to pass the cookie information somehow to the kernel, but we'd have to dig into what standard we should use. The other option would be if the frontend can access the cookie (which might be less save), so we can pass the cookie information in the event handler outselves.
cheers,
Maarten
You can try out the updated PR (https://github.com/voila-dashboards/voila/pull/922) with:
conda create -y -n http_voila -c conda-forge jupyterlab nodejs
conda activate http_voila
pip install pip install git+https://github.com/mariobuikhuizen/voila.git@httpforward
Create a notebook test.ipynb:
import os
import pprint
from http import cookies
cookie = cookies.SimpleCookie()
cookie.load(os.environ.get('HTTP_COOKIE', 'Cookie env var not found'))
cookie_dict = {key: morsel.value for key, morsel in cookie.items()}
pp = pprint.PrettyPrinter()
pp.pprint(cookie_dict)
Start Voila:
voila --VoilaConfiguration.http_header_envs=Cookie test.ipynb
@mariobuikhuizen We're finally getting around to testing the implementation of this on our end. I was able to test that this works in your example. I'm now trying to get this to work within our voila-embed infrastructure. I'm using the most recent voila-embed
and voila
installed from pip install git+https://github.com/voila-dashboards/voila.git@main
.
My voila.json
config.
MappingKernelManager
.cull_idle_timeout = 120
.cull_interval = 60
Voila
.open_browser = False
.port = 8000
.tornado_settings = {'allow_origin': '*'}
VoilaConfiguration
.enable_nbextensions = True
.http_header_envs = ["['Cookie','User-Agent’]"]
.template = 'embed'
In my notebook I have a test cell to capture the cookie output into a debug window
@out.capture()
def check_cookie():
print('cookie', os.environ.get("HTTP_COOKIE"))
print('user agent', os.environ.get('HTTP_USER_AGENT'))
print('server', os.environ.get('SERVER_NAME'))
but when I load the page, I don't see any HTTP information
cookie None
user agent None
server madrox.stsci.edu
Do we need to change anything about what is sent to the notebook via the requestWidget
? Or anything with the jupyter-widget-embed
?
Ok, some progrees. I changed my voila command to voila --VoilaConfiguration.http_header_envs=Cookie --VoilaConfiguration.http_header_envs='User-Agent'
, which gives me the configuration syntax
VoilaConfiguration
.enable_nbextensions = True
.http_header_envs = ['Cookie', 'User-Agent']
.template = 'embed'
and now I at least get the User-Agent printed, but still no cookie.
cookie None
user agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36
server madrox.stsci.edu
I didn't test the cookie stuff with voila-embed :|. Looking a bit closer now, the voila server needs to be accessed from the same domain as the website, else the cookie from the website domain is not passed.
This works for me with the nginx web server:
server {
listen 80 default_server;
server_name website.com;
location /voila/ {
proxy_pass http://localhost:8000;
}
location /api/ {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Scheme $scheme;
proxy_buffering off;
}
location / {
proxy_pass http://localhost:5000;
}
}
And then use website.com
in the embed tag: <jupyter-widget-embed ... voila-url="http://website.com" ...>
Hmm ok. I'm running both servers locally, accessible on the same localhost
or madrox.stsci.edu
domain. But I'm not running voila via nginx. I can try that.
It also has to be the same port.
hmm, then that might be the problem. The voila and web servers aren't running on the same port locally. I can try to hack something locally for testing but I'm not sure about our production environments. I'd have to talk to some other folks.
I finally got it working on different ports (no need for proxying with nginx anymore), you'll need the following:
.tornado_settings = {'allow_origin': 'http://website.com:5000', 'allow_credentials': 'true'}
voila-embed.js
change line 141 to: const res = await fetch(`${voilaUrl}/voila/render/${notebook}`, {credentials: 'include'});
oh cool! ok, let me try that.
Huzzah, that seemed to work! I think in our production environment, everything is proxied with nginx. Does this solution work under that framework as well?
Yeah, should work the same. Only the websocket connection to Voila needs some special settings:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
Ok, I checked our production nginx config for serving Voila and we have those settings in there. So we might be ok.
Is the code change in voila-embed.js
something that should go into a new commit, and/or PR?
We're in the process of integration our web authentication for the jdaviz site with voila-embed. Basically we need to restrict access to certain data based on user's authorization. Do
ipyvuetify
events orvoila_embed
requests allow access to the web request header or session cookie? I'm thinking in the notebook event handler, we extract the user info from the session cookie and validate it against the requested input data using our auth code. If it checks out we load Jdaviz proper, otherwise we return an alert message. Or are there other ideas on folding in authentication with notebooks?