Add support for OIDC (#389)

* added support for oidc auth

* fixed oidc usernames

* hiding password for users that aren't logged in via local auth

* add dependency, update settings

* keep change password link

* add tests

* add docs

---------

Co-authored-by: Sascha Ißbrücker <sascha.issbruecker@gmail.com>
This commit is contained in:
ηg
2024-03-16 23:42:46 +01:00
committed by GitHub
parent 4bee104b62
commit 39782e75e7
12 changed files with 192 additions and 17 deletions

View File

@@ -43,6 +43,7 @@ INSTALLED_APPS = [
"rest_framework",
"rest_framework.authtoken",
"background_task",
"mozilla_django_oidc",
]
MIDDLEWARE = [
@@ -182,6 +183,24 @@ MAX_ATTEMPTS = 5
BACKGROUND_TASK_RUN_ASYNC = True
BACKGROUND_TASK_ASYNC_THREADS = 2
# Enable OICD support if configured
LD_ENABLE_OIDC = os.getenv("LD_ENABLE_OIDC", False) in (True, "True", "1")
AUTHENTICATION_BACKENDS = ["django.contrib.auth.backends.ModelBackend"]
if LD_ENABLE_OIDC:
AUTHENTICATION_BACKENDS.append("mozilla_django_oidc.auth.OIDCAuthenticationBackend")
OIDC_USERNAME_ALGO = "bookmarks.utils.generate_username"
OIDC_RP_CLIENT_ID = os.getenv("OIDC_RP_CLIENT_ID")
OIDC_OP_AUTHORIZATION_ENDPOINT = os.getenv("OIDC_OP_AUTHORIZATION_ENDPOINT")
OIDC_OP_TOKEN_ENDPOINT = os.getenv("OIDC_OP_TOKEN_ENDPOINT")
OIDC_OP_USER_ENDPOINT = os.getenv("OIDC_OP_USER_ENDPOINT")
OIDC_USE_PKCE = os.getenv("OIDC_USE_PKCE", True) in (True, "True", "1")
OIDC_RP_CLIENT_SECRET = os.getenv("OIDC_RP_CLIENT_SECRET")
OIDC_RP_SIGN_ALGO = os.getenv("OIDC_RP_SIGN_ALGO", "HS256")
OIDC_OP_JWKS_ENDPOINT = os.getenv("OIDC_OP_JWKS_ENDPOINT")
# Enable authentication proxy support if configured
LD_ENABLE_AUTH_PROXY = os.getenv("LD_ENABLE_AUTH_PROXY", False) in (True, "True", "1")
LD_AUTH_PROXY_USERNAME_HEADER = os.getenv(
@@ -194,9 +213,7 @@ if LD_ENABLE_AUTH_PROXY:
# in the LD_AUTH_PROXY_USERNAME_HEADER request header
MIDDLEWARE.append("bookmarks.middlewares.CustomRemoteUserMiddleware")
# Configure auth backend that does not require a password credential
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.RemoteUserBackend",
]
AUTHENTICATION_BACKENDS = ["django.contrib.auth.backends.RemoteUserBackend"]
# Configure logout URL
if LD_AUTH_PROXY_LOGOUT_URL:
LOGOUT_REDIRECT_URL = LD_AUTH_PROXY_LOGOUT_URL

View File

@@ -19,16 +19,27 @@ from django.contrib.auth import views as auth_views
from django.urls import path, include
from bookmarks.admin import linkding_admin_site
from .settings import ALLOW_REGISTRATION, DEBUG
class LinkdingLoginView(auth_views.LoginView):
"""
Custom login view to lazily add additional context data
Allows to override settings in tests
"""
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["allow_registration"] = settings.ALLOW_REGISTRATION
context["enable_oidc"] = settings.LD_ENABLE_OIDC
return context
urlpatterns = [
path("admin/", linkding_admin_site.urls),
path(
"login/",
auth_views.LoginView.as_view(
redirect_authenticated_user=True,
extra_context=dict(allow_registration=ALLOW_REGISTRATION),
),
LinkdingLoginView.as_view(redirect_authenticated_user=True),
name="login",
),
path("logout/", auth_views.LogoutView.as_view(), name="logout"),
@@ -45,13 +56,16 @@ urlpatterns = [
path("", include("bookmarks.urls")),
]
if settings.LD_ENABLE_OIDC:
urlpatterns.append(path("oidc/", include("mozilla_django_oidc.urls")))
if settings.LD_CONTEXT_PATH:
urlpatterns = [path(settings.LD_CONTEXT_PATH, include(urlpatterns))]
if DEBUG:
if settings.DEBUG:
import debug_toolbar
urlpatterns.append(path("__debug__/", include(debug_toolbar.urls)))
if ALLOW_REGISTRATION:
if settings.ALLOW_REGISTRATION:
urlpatterns.append(path("", include("django_registration.backends.one_step.urls")))