From 9ee17e2b5215e3e482e22f3856bd69e2e219f39f Mon Sep 17 00:00:00 2001 From: Harris Tzovanakis Date: Tue, 17 Sep 2024 09:58:29 +0200 Subject: [PATCH] orcid: addition of dj-rest-auth --- backoffice/backoffice/users/api/views.py | 12 ++ backoffice/config/settings/base.py | 20 ++- backoffice/config/urls.py | 10 ++ backoffice/poetry.lock | 150 ++++------------------- backoffice/pyproject.toml | 3 +- ruff.toml | 2 +- 6 files changed, 68 insertions(+), 129 deletions(-) diff --git a/backoffice/backoffice/users/api/views.py b/backoffice/backoffice/users/api/views.py index 18e38ae0..695e13eb 100644 --- a/backoffice/backoffice/users/api/views.py +++ b/backoffice/backoffice/users/api/views.py @@ -1,3 +1,6 @@ +from allauth.socialaccount.providers.oauth2.client import OAuth2Client +from allauth.socialaccount.providers.orcid.views import OrcidOAuth2Adapter +from dj_rest_auth.registration.views import SocialConnectView, SocialLoginView from django.contrib.auth import get_user_model from rest_framework import status from rest_framework.decorators import action @@ -23,3 +26,12 @@ def get_queryset(self, *args, **kwargs): def me(self, request): serializer = UserSerializer(request.user, context={"request": request}) return Response(status=status.HTTP_200_OK, data=serializer.data) + + +class OrcidLogin(SocialLoginView): + adapter_class = OrcidOAuth2Adapter + client_class = OAuth2Client + + +class OrcidConnect(SocialConnectView): + adapter_class = OrcidOAuth2Adapter diff --git a/backoffice/config/settings/base.py b/backoffice/config/settings/base.py index e8fa6288..2e213489 100644 --- a/backoffice/config/settings/base.py +++ b/backoffice/config/settings/base.py @@ -95,19 +95,29 @@ "allauth", "allauth.account", "allauth.socialaccount", + "allauth.headless", + "allauth.socialaccount.providers.orcid", "django_celery_beat", "rest_framework", "rest_framework.authtoken", "corsheaders", "drf_spectacular", - "allauth.socialaccount.providers.orcid", "django_prometheus", "django_opensearch_dsl", "django_elasticsearch_dsl_drf", "rest_framework_simplejwt", "django_json_widget", + "dj_rest_auth", + "dj_rest_auth.registration", ] +REST_AUTH = { + "SESSION_LOGIN": True, + "USE_JWT": True, + "JWT_AUTH_COOKIE": "auth", + "JWT_AUTH_HTTPONLY": False, +} + LOCAL_APPS = ["backoffice.users", "backoffice.workflows", "backoffice.management"] # https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS @@ -127,7 +137,7 @@ # https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model AUTH_USER_MODEL = "users.User" # https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url -LOGIN_REDIRECT_URL = "users:redirect" +LOGIN_REDIRECT_URL = "/accounts/login/success" # https://docs.djangoproject.com/en/dev/ref/settings/#login-url LOGIN_URL = "account_login" @@ -349,6 +359,7 @@ "rest_framework.authentication.SessionAuthentication", "rest_framework.authentication.TokenAuthentication", "rest_framework_simplejwt.authentication.JWTAuthentication", + "dj_rest_auth.jwt_auth.JWTCookieAuthentication", ), "DEFAULT_PERMISSION_CLASSES": ( "backoffice.management.permissions.IsAdminOrCuratorUser", @@ -378,10 +389,11 @@ "APP": { "client_id": env("ORCID_CLIENT_ID", default=""), "secret": env("ORCID_CLIENT_SECRET", default=""), - "key": "", - } + }, } } +SOCIALACCOUNT_EMAIL_VERIFICATION = False +ACCOUNT_EMAIL_VERIFICATION = False # Opensearch diff --git a/backoffice/config/urls.py b/backoffice/config/urls.py index 045b7976..8bfbcc21 100644 --- a/backoffice/config/urls.py +++ b/backoffice/config/urls.py @@ -1,3 +1,4 @@ +from allauth.socialaccount.providers.orcid.views import oauth2_callback from django.conf import settings from django.conf.urls.static import static from django.contrib import admin @@ -9,6 +10,8 @@ from rest_framework.authtoken.views import obtain_auth_token from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView +from backoffice.users.api.views import OrcidConnect, OrcidLogin + urlpatterns = [ path("", TemplateView.as_view(template_name="pages/home.html"), name="home"), path( @@ -25,9 +28,11 @@ # Static file serving when using Gunicorn + Uvicorn for local web socket development urlpatterns += staticfiles_urlpatterns() + # API URLS urlpatterns += [ # API base url + path("api/oauth/authorized/orcid/", oauth2_callback, name="orcid_callback"), path("api/", include("config.search_router")), path("api/", include("config.api_router")), # DRF auth token @@ -40,6 +45,11 @@ ), path("api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair"), path("api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"), + path("_allauth/", include("allauth.headless.urls")), + path("dj-rest-auth/", include("dj_rest_auth.urls")), + path("dj-rest-auth/registration/", include("dj_rest_auth.registration.urls")), + path("dj-rest-auth/orcid/", OrcidLogin.as_view(), name="orcid_login"), + path("dj-rest-auth/orcid/connect/", OrcidConnect.as_view(), name="orcid_connect"), ] diff --git a/backoffice/poetry.lock b/backoffice/poetry.lock index 0ea52909..c910bd36 100644 --- a/backoffice/poetry.lock +++ b/backoffice/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "amqp" @@ -702,51 +702,6 @@ files = [ [package.extras] dev = ["polib"] -[[package]] -name = "cryptography" -version = "41.0.4" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = ">=3.7" -files = [ - {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:80907d3faa55dc5434a16579952ac6da800935cd98d14dbd62f6f042c7f5e839"}, - {file = "cryptography-41.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:35c00f637cd0b9d5b6c6bd11b6c3359194a8eba9c46d4e875a3660e3b400005f"}, - {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cecfefa17042941f94ab54f769c8ce0fe14beff2694e9ac684176a2535bf9714"}, - {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e40211b4923ba5a6dc9769eab704bdb3fbb58d56c5b336d30996c24fcf12aadb"}, - {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:23a25c09dfd0d9f28da2352503b23e086f8e78096b9fd585d1d14eca01613e13"}, - {file = "cryptography-41.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2ed09183922d66c4ec5fdaa59b4d14e105c084dd0febd27452de8f6f74704143"}, - {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5a0f09cefded00e648a127048119f77bc2b2ec61e736660b5789e638f43cc397"}, - {file = "cryptography-41.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9eeb77214afae972a00dee47382d2591abe77bdae166bda672fb1e24702a3860"}, - {file = "cryptography-41.0.4-cp37-abi3-win32.whl", hash = "sha256:3b224890962a2d7b57cf5eeb16ccaafba6083f7b811829f00476309bce2fe0fd"}, - {file = "cryptography-41.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c880eba5175f4307129784eca96f4e70b88e57aa3f680aeba3bab0e980b0f37d"}, - {file = "cryptography-41.0.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:004b6ccc95943f6a9ad3142cfabcc769d7ee38a3f60fb0dddbfb431f818c3a67"}, - {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:86defa8d248c3fa029da68ce61fe735432b047e32179883bdb1e79ed9bb8195e"}, - {file = "cryptography-41.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:37480760ae08065437e6573d14be973112c9e6dcaf5f11d00147ee74f37a3829"}, - {file = "cryptography-41.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b5f4dfe950ff0479f1f00eda09c18798d4f49b98f4e2006d644b3301682ebdca"}, - {file = "cryptography-41.0.4-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7e53db173370dea832190870e975a1e09c86a879b613948f09eb49324218c14d"}, - {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5b72205a360f3b6176485a333256b9bcd48700fc755fef51c8e7e67c4b63e3ac"}, - {file = "cryptography-41.0.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:93530900d14c37a46ce3d6c9e6fd35dbe5f5601bf6b3a5c325c7bffc030344d9"}, - {file = "cryptography-41.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efc8ad4e6fc4f1752ebfb58aefece8b4e3c4cae940b0994d43649bdfce8d0d4f"}, - {file = "cryptography-41.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c3391bd8e6de35f6f1140e50aaeb3e2b3d6a9012536ca23ab0d9c35ec18c8a91"}, - {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0d9409894f495d465fe6fda92cb70e8323e9648af912d5b9141d616df40a87b8"}, - {file = "cryptography-41.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8ac4f9ead4bbd0bc8ab2d318f97d85147167a488be0e08814a37eb2f439d5cf6"}, - {file = "cryptography-41.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:047c4603aeb4bbd8db2756e38f5b8bd7e94318c047cfe4efeb5d715e08b49311"}, - {file = "cryptography-41.0.4.tar.gz", hash = "sha256:7febc3094125fc126a7f6fb1f420d0da639f3f32cb15c8ff0dc3997c4549f51a"}, -] - -[package.dependencies] -cffi = ">=1.12" - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] -nox = ["nox"] -pep8test = ["black", "check-sdist", "mypy", "ruff"] -sdist = ["build"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] -test-randomorder = ["pytest-randomly"] - [[package]] name = "cssbeautifier" version = "1.14.9" @@ -788,17 +743,6 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] -[[package]] -name = "defusedxml" -version = "0.7.1" -description = "XML bomb protection for Python stdlib modules" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, - {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, -] - [[package]] name = "dill" version = "0.3.7" @@ -839,6 +783,23 @@ files = [ Django = ">=3.2" typing-extensions = ">=3.10.0.0" +[[package]] +name = "dj-rest-auth" +version = "6.0.0" +description = "Authentication and Registration in Django Rest Framework" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dj-rest-auth-6.0.0.tar.gz", hash = "sha256:760b45f3a07cd6182e6a20fe07d0c55230c5f950167df724d7914d0dd8c50133"}, +] + +[package.dependencies] +Django = ">=3.2,<6.0" +djangorestframework = ">=3.13.0" + +[package.extras] +with-social = ["django-allauth (>=0.56.0,<0.62.0)"] + [[package]] name = "django" version = "4.2.6" @@ -861,24 +822,23 @@ bcrypt = ["bcrypt"] [[package]] name = "django-allauth" -version = "0.57.0" +version = "64.2.1" description = "Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "django-allauth-0.57.0.tar.gz", hash = "sha256:a095ef0db7de305d9175772c78e765ebd5fceb004ae61c1383d7fc1af0f7c5b1"}, + {file = "django_allauth-64.2.1.tar.gz", hash = "sha256:54bf0af8dc5c334254dd56f9069447c19b9b623110a095b2a0dcb82a414e1055"}, ] [package.dependencies] -Django = ">=3.2" -pyjwt = {version = ">=1.7", extras = ["crypto"]} -python3-openid = ">=3.0.8" -requests = ">=2.0.0" -requests-oauthlib = ">=0.3.0" +Django = ">=4.2" [package.extras] -mfa = ["qrcode (>=7.0.0)"] +mfa = ["fido2 (>=1.1.2)", "qrcode (>=7.0.0)"] +openid = ["python3-openid (>=3.0.8)"] saml = ["python3-saml (>=1.15.0,<2.0.0)"] +socialaccount = ["pyjwt[crypto] (>=1.7)", "requests (>=2.0.0)", "requests-oauthlib (>=0.3.0)"] +steam = ["python3-openid (>=3.0.8)"] [[package]] name = "django-anymail" @@ -2222,22 +2182,6 @@ files = [ [package.dependencies] setuptools = "*" -[[package]] -name = "oauthlib" -version = "3.2.2" -description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" -optional = false -python-versions = ">=3.6" -files = [ - {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, - {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, -] - -[package.extras] -rsa = ["cryptography (>=3.0.0)"] -signals = ["blinker (>=1.4.0)"] -signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] - [[package]] name = "opensearch" version = "0.9.2" @@ -2628,9 +2572,6 @@ files = [ {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, ] -[package.dependencies] -cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} - [package.extras] crypto = ["cryptography (>=3.4.0)"] dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] @@ -2844,24 +2785,6 @@ text-unidecode = ">=1.3" [package.extras] unidecode = ["Unidecode (>=1.1.1)"] -[[package]] -name = "python3-openid" -version = "3.2.0" -description = "OpenID support for modern servers and consumers." -optional = false -python-versions = "*" -files = [ - {file = "python3-openid-3.2.0.tar.gz", hash = "sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf"}, - {file = "python3_openid-3.2.0-py3-none-any.whl", hash = "sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b"}, -] - -[package.dependencies] -defusedxml = "*" - -[package.extras] -mysql = ["mysql-connector-python"] -postgresql = ["psycopg2"] - [[package]] name = "pytz" version = "2023.3.post1" @@ -2898,7 +2821,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -3084,24 +3006,6 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] -[[package]] -name = "requests-oauthlib" -version = "1.3.1" -description = "OAuthlib authentication support for Requests." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"}, - {file = "requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5"}, -] - -[package.dependencies] -oauthlib = ">=3.0.0" -requests = ">=2.0.0" - -[package.extras] -rsa = ["oauthlib[signedtoken] (>=3.0.0)"] - [[package]] name = "rpds-py" version = "0.10.4" @@ -4033,4 +3937,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "~3.11" -content-hash = "3792d78500a0345b91bebb37193b90820bc1a0beb8838881f6015bbdf6ca3a9d" +content-hash = "2d3bd25465d3c5d26450e22bf0e46b993fc1e79997b98c7637f5e99aeec8bc32" diff --git a/backoffice/pyproject.toml b/backoffice/pyproject.toml index 97c59d7c..46992303 100644 --- a/backoffice/pyproject.toml +++ b/backoffice/pyproject.toml @@ -124,7 +124,7 @@ uvicorn = {version = "0.23.2", extras = ["standard"]} django = "4.2.6" django-environ = "0.11.2" django-model-utils = "4.3.1" -django-allauth = "0.57.0" +django-allauth = {extras = ["headless"], version = "^64.2.1"} django-crispy-forms = "2.1" crispy-bootstrap5 = "0.7" django-redis = "5.4.0" @@ -150,6 +150,7 @@ opensearch-py = "2.6.0" djangorestframework-simplejwt = "^5.3.1" django-json-widget = "^2.0.1" sentry-sdk = "1.19.1" +dj-rest-auth = "^6.0.0" [tool.poetry.dev-dependencies] factory-boy = "3.3.0" diff --git a/ruff.toml b/ruff.toml index d849b4ae..00a551a8 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,5 +1,5 @@ target-version = "py311" -ignore = ["PT009"] +lint.ignore = ["PT009"] [lint.flake8-tidy-imports] ban-relative-imports = "all"