Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

accessing input web request session inside the notebook event handler #23

Open
havok2063 opened this issue May 20, 2021 · 15 comments
Open

Comments

@havok2063
Copy link

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 or voila_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?

@maartenbreddels
Copy link
Collaborator

Hi Brian,

in voila-dashboards/voila#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

@maartenbreddels
Copy link
Collaborator

Related: voila-dashboards/voila#835

@mariobuikhuizen
Copy link
Owner

You can try out the updated PR (voila-dashboards/voila#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

@havok2063
Copy link
Author

@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?

@havok2063
Copy link
Author

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

@mariobuikhuizen
Copy link
Owner

mariobuikhuizen commented Sep 30, 2021

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" ...>

@havok2063
Copy link
Author

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.

@mariobuikhuizen
Copy link
Owner

It also has to be the same port.

@havok2063
Copy link
Author

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.

@mariobuikhuizen
Copy link
Owner

mariobuikhuizen commented Sep 30, 2021

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'}
  • In voila-embed.js change line 141 to: const res = await fetch(`${voilaUrl}/voila/render/${notebook}`, {credentials: 'include'});

@havok2063
Copy link
Author

oh cool! ok, let me try that.

@havok2063
Copy link
Author

havok2063 commented Sep 30, 2021

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?

@mariobuikhuizen
Copy link
Owner

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";

@havok2063
Copy link
Author

Ok, I checked our production nginx config for serving Voila and we have those settings in there. So we might be ok.

@havok2063
Copy link
Author

Is the code change in voila-embed.js something that should go into a new commit, and/or PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants