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

Add ability to declare OAuth provider #820

Merged
merged 11 commits into from
Jul 6, 2020
Merged

Conversation

philippjfr
Copy link
Member

@philippjfr philippjfr commented Nov 27, 2019

Adds a number of inbuilt OAuth providers to Panel which you can activate via the config and eventually by supplying options to panel serve.

  • Add GitHub OAuth Provider
  • Add AzureAd OAuth Provider
  • Add Bitbucket OAuth Provider
  • Add Google OAuth Provider
  • Add GitLab OAuth Provider
  • Add ability to declare OAuth provider in config and via env variables
  • Ensure the OAuth providers can be declared using panel serve
  • Expose the current user info in a convenient way
  • Make AuthProviders pluggable
  • Add docs
  • Add ability to logout
  • Add examples

e.g. given an app like this:

import hvplot.pandas
import panel as pn
import holoviews as hv

from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature

bins = pn.widgets.IntSlider(name='Number of bins', start=5, end=25, step=5, value=10)
kde = pn.widgets.Checkbox(name='Show density estimate')
observations = pn.widgets.Checkbox(name='Show individual observations')
bandwidth = pn.widgets.FloatSlider(name='KDE Bandwidth', start=0.1, end=1)

@pn.depends(bins, kde, observations, bandwidth)
def get_plot(bins, kde, obs, bw):
    plot = sea_surface_temperature.hvplot.hist(bins=bins, normed=True, xlabel='Temperature (C)', padding=0.1)
    if kde:
        plot *= sea_surface_temperature.hvplot.kde().opts(bandwidth=bw)
    if obs:
        plot *= hv.Spikes(sea_surface_temperature, 'temperature').opts(
            line_width=0.1, alpha=0.1, spike_length=-0.01)
    return plot

widgets = pn.WidgetBox('## Sea surface temperatures', bins, observations, kde, logout)

def add_bandwidth(event):
    if event.new:
        widgets.append(bandwidth)
    else:
        widgets.remove(bandwidth)

kde.param.watch(add_bandwidth, 'value')

pn.Row(widgets, get_plot).show()

You can run it with:

PANEL_OAUTH_PROVIDER='github' PANEL_OAUTH_KEY=... PANEL_OAUTH_SECRET=... python app.py

or:

panel serve test_oauth.py --oauth-provider="github" --oauth-key="..." --oauth-secret="..."

and get something like:

Screen Shot 2019-11-27 at 4 26 42 PM

Cc: @ceball @sdc50 @jbednar

@philippjfr
Copy link
Member Author

I'd particularly value any opinions on how best to make AuthProviders pluggable. Bokeh allows defining a module alongside the app which provides the auth provider but I'd prefer a cleaner way of providing one.

@jbednar
Copy link
Member

jbednar commented Nov 28, 2019

Cool. I don't have an immediate ideas about making it pluggable.

@sdc50
Copy link
Contributor

sdc50 commented Dec 17, 2019

I'd particularly value any opinions on how best to make AuthProviders pluggable.

Would it work to use namespace plugins, similar to what Intake does (https://github.com/intake/intake/blob/master/intake/source/discovery.py#L271)?

Something like this might work:

panel_oauth_login_handlers = dict('github': GithubLoginHandler)

import panel_oauth
for _, modname, ispkg in pkgutil.iter_modules(panel_oauth.__path__):
    plugin_path = f'panel_oauth.{modname}'
    plugin_module = importlib.import_module(plugin_path)
    for name, cls in inspect.getmembers(plugin_module, inspect.isclass):
        if issubclass(cls, tornado.web.RequestHandler):
            panel_oauth_login_handlers[modname] = cls




class OAuthProvider(AuthProvider):

    ...

    @property
    def login_handler(self):
        return panel_oauth_login_handlers.get(config.oauth_provider)

This would require that the AuthProvider plugins would need to be packaged and installed, which is maybe not as simple as you were hoping for.

@MarcSkovMadsen
Copy link
Collaborator

FYI I'm not very knowledgable in this. But one of the next steps for me would be to find out how to have users securely sign on via LDAP, Azure AD or SSO. I'm able to do LDAP with django applications. The other methods I've not tried yet.

Hope the methods are or can be supported. Would be great if there was some kind of docs, examples or tutorials on this.

@MarcSkovMadsen
Copy link
Collaborator

And in the end I would like to be able to build a single page application. But with different "pages" in (like awesome-panel.org has a gallery of apps). Some of these pages everybody can have access to. And others are restricted by AD Groups. I.e. there could be multiple AD groups giving access to different "pages" and data in the application.

@philippjfr philippjfr modified the milestones: v1.0.0, v0.10.0 Jul 6, 2020
@MarcSkovMadsen
Copy link
Collaborator

MarcSkovMadsen commented Jul 6, 2020

I am so much looking forward to this.

And it’s a unique feature. No other Python Analytics web framework provides this in the free, open source version I believe.

@codecov
Copy link

codecov bot commented Jul 6, 2020

Codecov Report

Merging #820 into master will decrease coverage by 1.20%.
The diff coverage is 35.30%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #820      +/-   ##
==========================================
- Coverage   87.78%   86.57%   -1.21%     
==========================================
  Files         135      138       +3     
  Lines       14930    15711     +781     
==========================================
+ Hits        13106    13602     +496     
- Misses       1824     2109     +285     
Impacted Files Coverage Δ
panel/command/serve.py 18.75% <11.36%> (-16.25%) ⬇️
panel/io/state.py 56.88% <21.21%> (-15.49%) ⬇️
panel/util.py 81.81% <23.07%> (-4.13%) ⬇️
panel/command/__init__.py 35.80% <25.00%> (-0.57%) ⬇️
panel/auth.py 38.61% <38.61%> (ø)
panel/config.py 45.59% <46.15%> (+0.13%) ⬆️
panel/io/server.py 62.06% <50.00%> (-0.57%) ⬇️
panel/command/oauth_secret.py 66.66% <66.66%> (ø)
panel/template/__init__.py 100.00% <0.00%> (ø)
panel/template/material/__init__.py 100.00% <0.00%> (ø)
... and 8 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a2f8c79...78b6ac1. Read the comment docs.

@philippjfr
Copy link
Member Author

@MarcSkovMadsen If you get a chance it would be fabulous if you could go through the new docs I've added here and do some testing. I'm going to merge this PR due to shorter term deadlines but this definitely needs some Q&A and actual unit tests before release.

@philippjfr philippjfr merged commit 0224639 into master Jul 6, 2020
@philippjfr philippjfr deleted the add_oauth_providers branch July 6, 2020 16:28
philippjfr added a commit that referenced this pull request Sep 17, 2020
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

Successfully merging this pull request may close these issues.

None yet

4 participants