from django.conf import settings from django.contrib.auth.models import Permission from django.db import transaction from django.db.models import CharField from django.db.models import Value as V from django.db.models.functions import Concat from mozilla_django_oidc.auth import ( OIDCAuthenticationBackend as BaseOIDCAuthenticationBackend, ) from .models import OIDCUser def get_permissions(claims): roles = claims.get("resource_access") if roles is None or settings.OIDC_RP_CLIENT_ID not in roles: return Permission.objects.none() return Permission.objects.annotate( fullname=Concat( "content_type__app_label", V("."), "codename", output_field=CharField() ) ).filter( fullname__in=claims.get("resource_access")[settings.OIDC_RP_CLIENT_ID]["roles"] ) class OIDCAuthenticationBackend(BaseOIDCAuthenticationBackend): @transaction.atomic def create_user(self, claims): user = self.UserModel.objects.create_user( claims.get("preferred_username"), claims.get("email") ) user.first_name = claims.get("given_name", "") user.last_name = claims.get("family_name", "") user.user_permissions.set(get_permissions(claims)) user.save() OIDCUser.objects.create(uuid=claims.get("sub"), user=user) return user def update_user(self, user, claims): user.email = claims.get("email") or user.email user.user_permissions.set(get_permissions(claims)) user.save() return user def filter_users_by_claims(self, claims): uuid = claims.get("sub") if not uuid: return self.UserModel.objects.none() try: oidc_user = OIDCUser.objects.get(uuid=uuid) return [oidc_user.user] except OIDCUser.DoesNotExist: return self.UserModel.objects.none() def verify_claims(self, claims): roles = claims.get("resource_access") return roles is not None and settings.OIDC_RP_CLIENT_ID in roles