From 3b5c592b8d47df277d8385e1cbdafe3951cb76ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Birk=20Jernstr=C3=B6m?= Date: Fri, 13 May 2022 21:24:31 +0200 Subject: [PATCH 1/3] Fix issue #94: Support for authlib 1.0.0 Use FlaskOAuth2App instead of FlaskRemoteApp since authlib 1.0.0 refactored accordingly and removed FlaskRemoteApp. --- loginpass/_flask.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loginpass/_flask.py b/loginpass/_flask.py index 5f21742..d6be06a 100644 --- a/loginpass/_flask.py +++ b/loginpass/_flask.py @@ -80,9 +80,9 @@ def login(name): def register_to(oauth, backend_cls): - from authlib.integrations.flask_client import FlaskRemoteApp + from authlib.integrations.flask_client import FlaskOAuth2App - class RemoteApp(backend_cls, FlaskRemoteApp): + class RemoteApp(backend_cls, FlaskOAuth2App): OAUTH_APP_CONFIG = backend_cls.OAUTH_CONFIG oauth.register(RemoteApp.NAME, overwrite=True, client_cls=RemoteApp) From b42feb4876c7b79ddda9c798de873e67613a136c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Birk=20Jernstr=C3=B6m?= Date: Sat, 14 May 2022 23:20:32 +0200 Subject: [PATCH 2/3] Support Authlib >= 1.0.0 for Flask, Django & FastAPI. Register & use the correct remote application (OAuth 1 or 2) based on the backend configuration. --- loginpass/_core.py | 24 ++++++++++++++++++++++++ loginpass/_django.py | 12 ++++-------- loginpass/_fastapi.py | 14 +++----------- loginpass/_flask.py | 14 +++----------- 4 files changed, 34 insertions(+), 30 deletions(-) diff --git a/loginpass/_core.py b/loginpass/_core.py index 750301c..b68be4b 100644 --- a/loginpass/_core.py +++ b/loginpass/_core.py @@ -20,3 +20,27 @@ def map_profile_fields(data, fields): profile[dst] = value return profile + + +def oauth_register_remote_app(oauth, backend, **kwargs): + """Registers & returns an instance of a remote application for + the given ``backend`` service. + + :param oauth: Authlib OAuth instance + :param backend: Backend class to register, e.g GitHub, Twitter etc + :param kwargs: Optional, additional, parameters for Authlib OAuth.register() + :return: Authlib OAuth remote app + """ + client_cls = oauth.oauth2_client_cls + if backend.OAUTH_CONFIG.get('request_token_url'): + client_cls = oauth.oauth1_client_cls + + class RemoteApp(backend, client_cls): + OAUTH_APP_CONFIG = backend.OAUTH_CONFIG + + return oauth.register( + RemoteApp.NAME, + overwrite=True, + client_cls=RemoteApp, + **kwargs + ) \ No newline at end of file diff --git a/loginpass/_django.py b/loginpass/_django.py index 4a1e02b..2b2861a 100644 --- a/loginpass/_django.py +++ b/loginpass/_django.py @@ -1,20 +1,16 @@ +from ._core import oauth_register_remote_app def create_django_urlpatterns(backend, oauth, handle_authorize): - from authlib.integrations.django_client import DjangoRemoteApp from django.urls import path - class RemoteApp(backend, DjangoRemoteApp): - OAUTH_APP_CONFIG = backend.OAUTH_CONFIG - token_name = '_loginpass_{}_token'.format(backend.NAME) auth_route_name = 'loginpass_{}_auth'.format(backend.NAME) login_route_name = 'loginpass_{}_login'.format(backend.NAME) - remote = oauth.register( - backend.NAME, - overwrite=True, + remote = oauth_register_remote_app( + oauth, + backend, fetch_token=lambda request: getattr(request, token_name, None), - client_cls=RemoteApp, ) auth = create_auth_endpoint(remote, handle_authorize) diff --git a/loginpass/_fastapi.py b/loginpass/_fastapi.py index ef05920..448fc9c 100644 --- a/loginpass/_fastapi.py +++ b/loginpass/_fastapi.py @@ -1,3 +1,4 @@ +from ._core import oauth_register_remote_app def create_fastapi_routes(backends, oauth, handle_authorize): """Create a Fastapi routes that you can register it directly to fastapi @@ -38,7 +39,7 @@ async def handle_authorize(remote, token, user_info, request): router = APIRouter() for b in backends: - register_to(oauth, b) + oauth_register_remote_app(oauth, b) @router.get("/auth/{backend}") async def auth( @@ -82,13 +83,4 @@ async def login(backend: str, request: Request): params = oauth.config.get(conf_key, default={}) return await remote.authorize_redirect(request, redirect_uri, **params) - return router - - -def register_to(oauth, backend_cls): - from authlib.integrations.starlette_client import StarletteRemoteApp - - class RemoteApp(backend_cls, StarletteRemoteApp): - OAUTH_APP_CONFIG = backend_cls.OAUTH_CONFIG - - oauth.register(RemoteApp.NAME, overwrite=True, client_cls=RemoteApp) + return router \ No newline at end of file diff --git a/loginpass/_flask.py b/loginpass/_flask.py index d6be06a..6a6b724 100644 --- a/loginpass/_flask.py +++ b/loginpass/_flask.py @@ -1,3 +1,4 @@ +from ._core import oauth_register_remote_app def create_flask_blueprint(backends, oauth, handle_authorize): """Create a Flask blueprint that you can register it directly to Flask @@ -35,7 +36,7 @@ def handle_authorize(remote, token, user_info): from flask import Blueprint, request, url_for, current_app, abort for b in backends: - register_to(oauth, b) + oauth_register_remote_app(oauth, b) bp = Blueprint('loginpass', __name__) @@ -76,13 +77,4 @@ def login(name): params = current_app.config.get(conf_key, {}) return remote.authorize_redirect(redirect_uri, **params) - return bp - - -def register_to(oauth, backend_cls): - from authlib.integrations.flask_client import FlaskOAuth2App - - class RemoteApp(backend_cls, FlaskOAuth2App): - OAUTH_APP_CONFIG = backend_cls.OAUTH_CONFIG - - oauth.register(RemoteApp.NAME, overwrite=True, client_cls=RemoteApp) + return bp \ No newline at end of file From 0c4f3ea2bcf846cbc85968c8bd8bf7c512ba4bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Birk=20Jernstr=C3=B6m?= Date: Mon, 16 May 2022 11:00:58 +0200 Subject: [PATCH 3/3] Fix import of OAuth module in Django example --- django_example/website/logins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django_example/website/logins.py b/django_example/website/logins.py index 1141fa2..68fa2d7 100644 --- a/django_example/website/logins.py +++ b/django_example/website/logins.py @@ -1,6 +1,6 @@ from django.http import HttpResponse, JsonResponse from django.urls import include, path -from authlib.django.client import OAuth +from authlib.integrations.django_client import OAuth from loginpass import create_django_urlpatterns from loginpass import Twitter, GitHub, Google