All checks were successful
Build containers when image tags change / build-if-image-changed (., web, containers, main container, git.baumann.gr/adebaumann/labhelper) (push) Successful in 17s
Build containers when image tags change / build-if-image-changed (data-loader, loader, initContainers, init-container, git.baumann.gr/adebaumann/labhelper-data-loader) (push) Successful in 3s
55 lines
2.1 KiB
Python
55 lines
2.1 KiB
Python
from mozilla_django_oidc.auth import OIDCAuthenticationBackend
|
|
from django.contrib.auth.models import Group
|
|
|
|
# Keycloak group name → Django group name mapping.
|
|
# Keycloak may send group paths with a leading slash (e.g. "/LabHelper Administrators");
|
|
# these are stripped before comparison.
|
|
KEYCLOAK_GROUP_MAP = {
|
|
'LabHelper Administrators': 'LabHelper Administrators',
|
|
'LabHelper Staff': 'LabHelper Staff',
|
|
'LabHelper Viewers': 'LabHelper Viewers',
|
|
}
|
|
|
|
# Members of these groups receive is_staff=True (Django admin access)
|
|
STAFF_GROUPS = {'LabHelper Administrators'}
|
|
|
|
|
|
class KeycloakOIDCBackend(OIDCAuthenticationBackend):
|
|
"""OIDC backend that maps Keycloak groups to Django groups on every login."""
|
|
|
|
def get_username(self, claims):
|
|
return claims.get('preferred_username') or super().get_username(claims)
|
|
|
|
def create_user(self, claims):
|
|
user = super().create_user(claims)
|
|
self._sync_from_claims(user, claims)
|
|
return user
|
|
|
|
def update_user(self, user, claims):
|
|
user = super().update_user(user, claims)
|
|
self._sync_from_claims(user, claims)
|
|
return user
|
|
|
|
def _sync_from_claims(self, user, claims):
|
|
"""Sync user attributes and group memberships from Keycloak token claims."""
|
|
user.first_name = claims.get('given_name', user.first_name)
|
|
user.last_name = claims.get('family_name', user.last_name)
|
|
|
|
# Keycloak sends group paths like "/LabHelper Administrators"; normalise them.
|
|
raw_groups = claims.get('groups', [])
|
|
keycloak_groups = {g.lstrip('/') for g in raw_groups}
|
|
|
|
user.is_staff = bool(keycloak_groups & STAFF_GROUPS)
|
|
user.save()
|
|
|
|
# Add/remove the user from each managed Django group to match Keycloak.
|
|
for kc_group, django_group_name in KEYCLOAK_GROUP_MAP.items():
|
|
try:
|
|
group = Group.objects.get(name=django_group_name)
|
|
except Group.DoesNotExist:
|
|
continue
|
|
if kc_group in keycloak_groups:
|
|
user.groups.add(group)
|
|
else:
|
|
user.groups.remove(group)
|