Update web/core/auth_oidc.py

This commit is contained in:
Joshua Laymon 2026-01-09 23:52:22 +00:00
parent 47bcc0c33c
commit c0acced574

View File

@ -1,43 +1,58 @@
from mozilla_django_oidc.auth import OIDCAuthenticationBackend from mozilla_django_oidc.auth import OIDCAuthenticationBackend
class AuthentikOIDCBackend(OIDCAuthenticationBackend): class AuthentikOIDCBackend(OIDCAuthenticationBackend):
""" """
Minimal, safe backend: Custom backend to integrate Authentik OIDC with existing Django users
- preserves existing local auth (ModelBackend stays enabled) without breaking local authentication.
- creates/updates Django users from Authentik claims
""" """
def filter_users_by_claims(self, claims): def filter_users_by_claims(self, claims):
# Prefer stable identifiers. Authentik often provides email + preferred_username.
email = (claims.get("email") or "").strip().lower() email = (claims.get("email") or "").strip().lower()
username = (claims.get("preferred_username") or claims.get("username") or "").strip() username = (
claims.get("preferred_username")
or claims.get("username")
or ""
).strip()
# If you want "email is identity", use email matching first: # 1) Prefer matching by email
if email: if email:
return self.UserModel.objects.filter(email__iexact=email) qs = self.UserModel.objects.filter(email__iexact=email)
if qs.exists():
return qs
# Fallback to username matching if no email # 2) Fallback to username match (critical for existing local users)
if username: if username:
return self.UserModel.objects.filter(username__iexact=username) qs = self.UserModel.objects.filter(username__iexact=username)
if qs.exists():
return qs
# 3) Otherwise, no match -> create user
return self.UserModel.objects.none() return self.UserModel.objects.none()
def create_user(self, claims): def create_user(self, claims):
user = super().create_user(claims) user = super().create_user(claims)
email = (claims.get("email") or "").strip().lower() email = (claims.get("email") or "").strip().lower()
username = (claims.get("preferred_username") or claims.get("username") or email or "").strip() username = (
claims.get("preferred_username")
or claims.get("username")
or email
or ""
).strip()
if username:
user.username = username
if email: if email:
user.email = email user.email = email
# Optional nice-to-have mappings # Only set username if Django hasn't already set one
if username and not user.username:
user.username = username
user.first_name = claims.get("given_name", "") or user.first_name user.first_name = claims.get("given_name", "") or user.first_name
user.last_name = claims.get("family_name", "") or user.last_name user.last_name = claims.get("family_name", "") or user.last_name
user.set_unusable_password() # SSO-only unless you explicitly set local passwords # SSO-only account unless you explicitly add a password later
user.set_unusable_password()
user.save() user.save()
return user return user
@ -46,7 +61,6 @@ class AuthentikOIDCBackend(OIDCAuthenticationBackend):
if email and user.email.lower() != email: if email and user.email.lower() != email:
user.email = email user.email = email
# keep username stable once set, unless you *want* it to track upstream changes
user.first_name = claims.get("given_name", "") or user.first_name user.first_name = claims.get("given_name", "") or user.first_name
user.last_name = claims.get("family_name", "") or user.last_name user.last_name = claims.get("family_name", "") or user.last_name