Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
31c0179
Auth using before_request decorator
RenaudLN Jul 2, 2023
2086b7a
Updated CHANGELOG
RenaudLN Jul 2, 2023
a7e5236
linting
RenaudLN Jul 2, 2023
d66f6a3
Added flask to dependencies as it is explicitely imported
RenaudLN Jul 2, 2023
7cb4203
Change to PUBLIC_ROUTES and use werkzeug routing
RenaudLN Jul 2, 2023
9675eb3
add route whitelisting test
RenaudLN Jul 2, 2023
dc5b3a0
Updated Changelog
RenaudLN Jul 2, 2023
d310e87
lint
RenaudLN Jul 3, 2023
28721a4
update test
RenaudLN Jul 3, 2023
fdf6708
fix typo
RenaudLN Jul 3, 2023
b3d7101
Add add_public_routes util
RenaudLN Jul 7, 2023
397e2da
remove modern typing
RenaudLN Jul 7, 2023
cc3967a
Updated CHANGELOG and docstring
RenaudLN Jul 7, 2023
8cdbbd8
Simplify by setting a default PUBLIC_ROUTES config
RenaudLN Jul 3, 2023
efaa88b
Mark arguments as deprecated.
RenaudLN Jul 13, 2023
8f814a8
fix add_public_routes call
RenaudLN Jul 13, 2023
6f512d3
Working public routes and public callbacks
RenaudLN Jul 15, 2023
1be6060
update test as /_dash-layout is whitelisted
RenaudLN Jul 15, 2023
01b5402
Move import to top of file
RenaudLN Jul 15, 2023
db547a8
Only add default public routes on the first call of add_public_routes
RenaudLN Jul 17, 2023
ecda821
simplified
RenaudLN Jul 17, 2023
d89f069
Rollback to only use before request
RenaudLN Aug 9, 2023
88326e6
update changelog, readme, deps
RenaudLN Aug 9, 2023
afcef97
rm remaining public routes bits
RenaudLN Aug 9, 2023
c26d714
rm unused import
RenaudLN Aug 9, 2023
d835ede
updated browser-tools orb
RenaudLN Aug 11, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: 2.1

orbs:
browser-tools: circleci/browser-tools@1.4.1
browser-tools: circleci/browser-tools@1.4.3

jobs:
python-36: &test-template
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Changed
- Uses flask `before_request` to protect all endpoints rather than protecting routes present at instantiation time

## [2.0.0] - 2023-03-10
### Removed
Removed obsolete `PlotlyAuth`. `dash-auth` is now just responsible for `BasicAuth`.
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,21 @@ python -k ba001
```

Note that Python 3.6 or greater is required.

## Usage

### Basic Authentication

To add basic authentication, add the following to your Dash app:

```python
from dash import Dash
from dash_auth import BasicAuth

app = Dash(__name__)
USER_PWD = {
"username": "password",
"user2": "useSomethingMoreSecurePlease",
}
BasicAuth(app, USER_PWD)
```
7 changes: 5 additions & 2 deletions dash_auth/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
from .basic_auth import BasicAuth # noqa: F401
from .version import __version__ # noqa: F401
from .basic_auth import BasicAuth
from .version import __version__


__all__ = ["BasicAuth", "__version__"]
54 changes: 34 additions & 20 deletions dash_auth/auth.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,43 @@
from __future__ import absolute_import
from abc import ABC, abstractmethod

from dash import Dash


class Auth(ABC):
def __init__(self, app, authorization_hook=None, _overwrite_index=True):
def __init__(self, app: Dash, **obsolete):
"""Auth base class for authentication in Dash.

:param app: Dash app
"""

# Deprecated arguments
if obsolete:
raise TypeError(
f"Auth got unexpected keyword arguments: {list(obsolete)}"
)

self.app = app
self._index_view_name = app.config['routes_pathname_prefix']
if _overwrite_index:
self._overwrite_index()
self._protect_views()
self._index_view_name = app.config['routes_pathname_prefix']
self._auth_hooks = [authorization_hook] if authorization_hook else []

def _overwrite_index(self):
original_index = self.app.server.view_functions[self._index_view_name]

self.app.server.view_functions[self._index_view_name] = \
self.index_auth_wrapper(original_index)

def _protect_views(self):
# TODO - allow users to white list in case they add their own views
for view_name, view_method in self.app.server.view_functions.items():
if view_name != self._index_view_name:
self.app.server.view_functions[view_name] = \
self.auth_wrapper(view_method)
self._protect()

def _protect(self):
"""Add a before_request authentication check on all routes.

The authentication check will pass if the request
is authorised by `Auth.is_authorised`
"""

server = self.app.server

@server.before_request
def before_request_auth():

# Check whether the request is authorised
if self.is_authorized():
return None

# Otherwise, ask the user to log in
return self.login_request()

def is_authorized_hook(self, func):
self._auth_hooks.append(func)
Expand Down
17 changes: 15 additions & 2 deletions dash_auth/basic_auth.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
from .auth import Auth
import base64
from typing import Union
import flask
from dash import Dash

from .auth import Auth


class BasicAuth(Auth):
def __init__(self, app, username_password_list):
def __init__(
self,
app: Dash,
username_password_list: Union[list, dict],
):
"""Add basic authentication to Dash.

:param app: Dash app
:param username_password_list: username:password list, either as a
list of tuples or a dict
"""
Auth.__init__(self, app)
self._users = (
username_password_list
Expand Down
1 change: 1 addition & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dash[testing]>=2
requests[security]
flake8
flask
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
description='Dash Authorization Package.',
long_description=long_description,
install_requires=[
'dash>=1.1.1'
'dash>=1.1.1',
"flask",
],
python_requires=">=3.6",
include_package_data=True,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_basic_auth_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def update_output(new_value):

def test_failed_views(url):
assert requests.get(url).status_code == 401
assert requests.get(url.strip("/") + "/_dash-layout").status_code == 403
assert requests.get(url.strip("/") + "/_dash-layout").status_code == 401

test_failed_views(base_url)

Expand Down