From ee2481daf1f9299e9880033bc763d766034d8421 Mon Sep 17 00:00:00 2001 From: Jonathan Longe Date: Fri, 15 Dec 2023 14:41:28 -0800 Subject: [PATCH 1/3] permit flask-application-factory pattern too --- .gitignore | 3 +- README.md | 39 ++++++++++++++++++++++++ src/flask_oauth2_validation/decorator.py | 19 +++++++----- tests/functional/test_config.py | 8 +++++ 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index dec703e..c3ad34b 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ dist/ .coverage htmlcov/ coverage.xml -lcov.info \ No newline at end of file +lcov.info +.idea/ diff --git a/README.md b/README.md index 5f3c337..67d0825 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,45 @@ def protected(): pass ``` +If you're using the **Flask Application Factory**, set up using `init_app()` like: + +```python +# __init__.py + +oauth2 = OAuth2Decorator() + + +def create_app(config_class=Config): + application = Flask(__name__) + application.config.from_object(config_class) + + # ... register blueprints etc + + with application.app_context(): + oauth2.init_app(application) # <-- call init_app() + return application +``` + +```python +# some-blueprint-file.py + +from api import oauth2 # <-- from __init__.py + +bp = Blueprint('users', __name__, url_prefix=Config.ROOT_URL+ '/api/v1') + + +@oauth2.requires_token() +@bp.route('/users', methods=['GET']) +def index(): + """ + Get all users + """ + users = User.query.all() + return users_schema.dump(users) + +``` + + # License MIT License diff --git a/src/flask_oauth2_validation/decorator.py b/src/flask_oauth2_validation/decorator.py index e1bcf41..ed4d957 100644 --- a/src/flask_oauth2_validation/decorator.py +++ b/src/flask_oauth2_validation/decorator.py @@ -49,7 +49,7 @@ class OAuth2Decorator(): """ - def __init__(self, app: Flask): + def __init__(self, app=None): """ Reads the app configuration and requests the Authorization Server Metadata as well as the authorization servers public keys. @@ -68,12 +68,6 @@ def __init__(self, app: Flask): self._logger = logging.getLogger(__name__) - app.config.setdefault('OAUTH2_ISSUER', None) - app.config.setdefault('OAUTH2_AUDIENCE', None) - app.config.setdefault('OAUTH2_JWKS_UPDATE_INTERVAL', None) - app.config.setdefault('OAUTH2_CLIENT_ID', None) - app.config.setdefault('OAUTH2_CLIENT_SECRET', None) - # Holds the current requests token in case # the verification steps where all successful. self.token = None @@ -97,6 +91,17 @@ def __init__(self, app: Flask): # that's why we cache its response, here. self._cached_metadata = None + if app is not None: + self.init_app(app) + + def init_app(self, app: Flask): + + app.config.setdefault('OAUTH2_ISSUER', None) + app.config.setdefault('OAUTH2_AUDIENCE', None) + app.config.setdefault('OAUTH2_JWKS_UPDATE_INTERVAL', None) + app.config.setdefault('OAUTH2_CLIENT_ID', None) + app.config.setdefault('OAUTH2_CLIENT_SECRET', None) + # The only mandatory value is the issuer URI. # In case it is the only value we expect it to offer # Authorization Server Metadata support (RFC-8414). diff --git a/tests/functional/test_config.py b/tests/functional/test_config.py index 4fc7270..9f45243 100644 --- a/tests/functional/test_config.py +++ b/tests/functional/test_config.py @@ -125,3 +125,11 @@ def test_introspection_setup_without_secret(test_app): with pytest.raises(TypeError) as err: OAuth2Decorator(test_app) assert str(err.value) == 'OAUTH2_CLIENT_SECRET config property required' + + +def test_set_up_using_flask_application_factory(test_app): + test_app.config['OAUTH2_ISSUER'] = 'https://issuer.local/oauth2' + oauth2 = OAuth2Decorator() + oauth2.init_app(test_app) + assert oauth2._issuer == 'https://issuer.local/oauth2' + assert oauth2._jwks_uri == 'https://issuer.local/oauth2/keys' \ No newline at end of file From 69272fcf599ac1ef5fa4a6f85335d0fd62067830 Mon Sep 17 00:00:00 2001 From: Jonathan Longe Date: Fri, 15 Dec 2023 14:48:29 -0800 Subject: [PATCH 2/3] increment to version 0.1.4 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d73c131..b0fd9cc 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name='flask-oauth2-validation', - version='0.1.3', + version='0.1.4', author='Henrik Sachse', author_email='henrik@0x7d7b.net', description=( From 75c5bf04768c9a02d9b9fdfb7b8787fc8527d5cf Mon Sep 17 00:00:00 2001 From: Jonathan Longe Date: Fri, 15 Dec 2023 15:27:56 -0800 Subject: [PATCH 3/3] fix __init__.py type hinting --- src/flask_oauth2_validation/decorator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flask_oauth2_validation/decorator.py b/src/flask_oauth2_validation/decorator.py index ed4d957..1ec3bb1 100644 --- a/src/flask_oauth2_validation/decorator.py +++ b/src/flask_oauth2_validation/decorator.py @@ -49,7 +49,7 @@ class OAuth2Decorator(): """ - def __init__(self, app=None): + def __init__(self, app: Flask | None = None): """ Reads the app configuration and requests the Authorization Server Metadata as well as the authorization servers public keys.