panel: OAuth not working with prefixed app or behind a reverse proxy

Tested with Panel 0.13.0 and some older versions, Bokeh 2.4.2.

I’ve been using the OAuth authentication feature provided by Panel with a custom provider for some time. It’s working very well and I appreciate how easy it is to set up.

Now, I’m currently working on a new production environment where the app is behind a reverse proxy (see recent topic on discourse). The server is launched with something like:

panel serve myapp/ --oauth-provider provider --oauth-key key --oauth-secret secret --cookie-secret cookie-secret --oauth-encryption-key encryption-key --oauth-redirect-uri http://host/myapp --allow-websocket-origin host

With a random main.py in myapp/:

import panel as pn

content = pn.Column('Hey')
content.servable()

While trying to make it work, I realized that the auth.py module has some limitations regarding the management of URLs and redirection. Namely, the process fails if the app is available at a specific path. This is typically the case in a reverse proxy setup, but also if you use a prefix.

First, if you look at the latest version of the file, line 752 there is a return statement that builds the wrong URL. Trying to access http://host/myapp, the URL will change to http://host/login?next=%2Fmyapp, i.e. the path is ignored. This yields a 404 Error.

I’ve found that this can be fixed with the following change to the login_url method:

def login_url(self):
    if config.oauth_redirect_uri is None:
        return '/login'
    else:
        return urlparse(config.oauth_redirect_uri).path + '/login'

This will get the user to the provider page. Then, the path is also ignored in the redirection (self.redirect method call line 269) so that after the user has been authorized, Tornado redirects to http://host/ instead of http://host/myapp. Passing urlparse(redirect_uri).path instead of "/" solves the issue.

Note that the same issue arises without reverse proxying if you use a prefix, although the fix I put in place does not seem to work for some reason. In other words, you won’t be able to set up authentication in this configuration:

panel serve myapp/ --oauth-provider provider --oauth-key key --oauth-secret secret --cookie-secret cookie-secret --oauth-encryption-key encryption-key --oauth-redirect-uri http://host:5006/prefix/myapp --prefix prefix 

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 1
  • Comments: 31 (21 by maintainers)

Most upvoted comments

Ok. I’ve contributed to the Apache section in the Bokeh docs so I’m willing to help if needed.

Yes there is! It’s the LimitRequestFieldSize option mentioned in the logs and setting it to 16 ko fixes it.

Indeed this should definitely be mentioned in the Bokeh docs. I may submit a PR to that end.

Thanks for the tip @philippjfr

I can confirm we are also observing this issue with Version: 1.3.8 Our setup uses Keycloak as the OAuth provider, running inside a Kubernetes cluster and an Nginx reverse proxy. How we fixed it:

nginx:

- host: "yourdomain.com"
        paths:
          - path: /panel-apps/

For the env vars:

Then serve as:

panel serve --oauth-provider=generic --prefix /panel-apps/ panel_app1.py panel_app2.py

NOTE: After trying several solutions, the actual trick was to serve the panel app with the correct --prefix parameter.

Sure, I can reach out to you on gitter or via e-mail, whichever suits you best.

Can you try urlparse.urlparse instead of urlparse?

Or “from urlparse import urlparse” instead of “import urlparse”.