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

auth checks #5503

Closed
ndmlny-qs opened this issue Sep 12, 2023 · 0 comments · Fixed by #5504
Closed

auth checks #5503

ndmlny-qs opened this issue Sep 12, 2023 · 0 comments · Fixed by #5504

Comments

@ndmlny-qs
Copy link
Contributor

ALL software version info

  • panel main
  • bokeh 3.2.2
  • python 3.9.17
  • juptyerlab 3.6.5
  • linux

Description of expected behavior and the observed behavior

Expected behavior

#5386 adds the ability to authenticate user names and optionally user paths in a Panel app. If a user does not create an authorize_callback method that takes two parameters, then the new optional user path checks for authentication should be ignored.

Observed behavior

A follow up comment #5386 (comment) from @el-abcd indicates that the feature errors when an authorize_callback object only has one parameter. @maximlt also confirmed the bug in the conversation.

Complete, minimal, self-contained example code that reproduces the issue

# app1.py
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
import panel as pn
import param
from auth import check_user_authorization

pn.extension()
pn.config.authorize_callback = check_user_authorization

class App1(param.Parameterized):
    a = param.Integer(default=2, bounds=(0, 10))
    b = param.Integer(default=3, bounds=(0, 10))

    def view(self):
        return pn.pane.HTML(f"<p>a={self.a} b={self.b}</p>")

    def panel(self):
        return pn.Row(self.param, self.view).servable()

app1 = App1()
app1.panel()
# app2.py
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
import panel as pn
import param
from auth import check_user_authorization

pn.extension()
pn.config.authorize_callback = check_user_authorization

class App2(param.Parameterized):
    c = param.Integer(default=6, bounds=(0, None))
    exp = param.Number(default=0.1, bounds=(0, 3))

    def view(self):
        out = self.c**self.exp
        return pn.Column(out)

    def panel(self):
        return pn.Row(self.param, self.view).servable()

app2 = App2()
app2.panel()
# auth.py
from typing import Any

authorized_users = {"admin", "user"}

def check_user_authorization(user_info: dict[str, Any]) -> bool:
    authenticated = False
    current_user = user_info["user"]
    if current_user in authorized_users:
        authenticated = True
    return authenticated
// credentials.json
{
  "user": "user",
  "admin": "admin"
}

Run the apps via the command line

panel serve app1.py app2.py --basic-auth credentials.json --cookie-secret my_super_safe_cookie_secret

Stack traceback and/or browser JavaScript console output

$ panel serve app1.py app2.py --basic-auth credentials.json --cookie-secret my_super_safe_cookie_secret
2023-09-12 10:27:49,876 Starting Bokeh server version 3.2.2 (running on Tornado 6.3.2)
2023-09-12 10:27:49,877 User authentication hooks provided (no default user)
2023-09-12 10:27:49,880 Bokeh app running at: http://localhost:5006/app1
2023-09-12 10:27:49,880 Bokeh app running at: http://localhost:5006/app2
2023-09-12 10:27:49,880 Starting Bokeh server with process id: 3589592
2023-09-12 10:28:00,772 404 GET /thumbnails/app1.png (127.0.0.1) 1.09ms
2023-09-12 10:28:00,774 404 GET /thumbnails/app2.png (127.0.0.1) 1.25ms
2023-09-12 10:28:18,725 404 GET /thumbnails/app1.png (127.0.0.1) 1.46ms
2023-09-12 10:28:18,727 404 GET /thumbnails/app2.png (127.0.0.1) 1.07ms
2023-09-12 10:28:22,158 Uncaught exception GET /app1 (127.0.0.1)
HTTPServerRequest(protocol='http', host='localhost:5006', method='GET', uri='/app1', version='HTTP/1.1', remote_ip='127.0.0.1')
Traceback (most recent call last):
  File "$HOME/mambaforge/envs/panel-dev/lib/python3.9/site-packages/tornado/web.py", line 1786, in _execute
    result = await result
  File "PATH/TO/PANEL-INSTALL/panel/panel/io/server.py", line 517, in get
    raise RuntimeError(
RuntimeError: Authorization callback must accept either one or two arguments.
2023-09-12 10:28:22,159 500 GET /app1 (127.0.0.1) 305.37ms

Screenshots or screencasts of the bug in action

image

ndmlny-qs added a commit to ndmlny-qs/panel that referenced this issue Sep 12, 2023
This commit adds some extra logic, and error messages around user
authentication with a user supplied `authorize_callback` method.

- Adds more messaging around the `RuntimeError` when an error occurs
  during authorization checks.
- Adds messaging to a user attempting access a path they do not have
  access to.
- Adds logic to ensure if an `authorize_callback` has only 1 parameter,
  it does not cause a `RuntimeError`.

Resolves holoviz#5503
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 a pull request may close this issue.

1 participant