From da49ddabcc7a5fe9bd843bd55f4e8c684cab5297 Mon Sep 17 00:00:00 2001 From: Kumi Date: Sun, 24 Dec 2023 09:16:55 +0100 Subject: [PATCH] Add Django CAS authentication support Introduce support for Central Authentication Service (CAS) alongside existing OIDC and SAML by integrating a new CAS server app and custom CAS authentication user model. Streamline sign-in infrastructure with updated URL patterns. As part of the update, refactor user model `username` resolution to leverage the email field directly. Includes necessary Django migrations to support new authentication features and removes a deprecated OIDC provider dependency. --- .vscode/launch.json | 20 ++++++ authentication/cas.py | 12 ++++ .../migrations/0003_appkey_appsession.py | 64 +++++++++++++++++++ core/migrations/0006_authorizationlog.py | 1 - core/models/auth.py | 6 +- kumidc/settings.py | 5 ++ kumidc/urls.py | 8 +-- requirements.txt | 1 + 8 files changed, 111 insertions(+), 6 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 authentication/cas.py create mode 100644 authentication/migrations/0003_appkey_appsession.py diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..783535c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Django", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/manage.py", + "args": [ + "runserver", + "8087" + ], + "django": true, + "justMyCode": true + } + ] +} \ No newline at end of file diff --git a/authentication/cas.py b/authentication/cas.py new file mode 100644 index 0000000..42a2151 --- /dev/null +++ b/authentication/cas.py @@ -0,0 +1,12 @@ +from cas_server.auth import DjangoAuthUser + +from django.contrib.auth import get_user_model + +class KumiDCAuthUser(DjangoAuthUser): + def __init__(self, username): + User = get_user_model() + try: + self.user = User.objects.get_by_natural_key(username) + except User.DoesNotExist: + pass + super(DjangoAuthUser, self).__init__(username) \ No newline at end of file diff --git a/authentication/migrations/0003_appkey_appsession.py b/authentication/migrations/0003_appkey_appsession.py new file mode 100644 index 0000000..cac03fc --- /dev/null +++ b/authentication/migrations/0003_appkey_appsession.py @@ -0,0 +1,64 @@ +# Generated by Django 5.0 on 2023-12-19 20:19 + +import django.db.models.deletion +import uuid +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("authentication", "0002_alter_totpsecret_user"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="AppKey", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, + editable=False, + primary_key=True, + serialize=False, + ), + ), + ("device", models.CharField(max_length=255)), + ("key", models.TextField()), + ("active", models.BooleanField(default=True)), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + migrations.CreateModel( + name="AppSession", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, + editable=False, + primary_key=True, + serialize=False, + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("used", models.DateTimeField(blank=True, null=True)), + ("approved", models.BooleanField(default=False)), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + ] diff --git a/core/migrations/0006_authorizationlog.py b/core/migrations/0006_authorizationlog.py index 0a3dfe0..018e44f 100644 --- a/core/migrations/0006_authorizationlog.py +++ b/core/migrations/0006_authorizationlog.py @@ -8,7 +8,6 @@ import django.db.models.deletion class Migration(migrations.Migration): dependencies = [ - ('oidc_provider', '0027_auto_20220810_0605'), ('core', '0005_profile_last_name'), ] diff --git a/core/models/auth.py b/core/models/auth.py index f9745b3..4973876 100644 --- a/core/models/auth.py +++ b/core/models/auth.py @@ -11,10 +11,14 @@ class User(AbstractBaseUser, PermissionsMixin): is_active = models.BooleanField(default=True) date_joined = models.DateTimeField(auto_now_add=True) - USERNAME_FIELD = 'email' + USERNAME_FIELD = "email" REQUIRED_FIELDS = [] objects = UserManager() + @property + def username(self): + return self.email + def __str__(self): return self.email diff --git a/kumidc/settings.py b/kumidc/settings.py index fab3e89..354e7ca 100644 --- a/kumidc/settings.py +++ b/kumidc/settings.py @@ -48,6 +48,7 @@ INSTALLED_APPS = [ 'oidc_provider', 'djangosaml2idp', + 'cas_server', ] MIDDLEWARE = [ @@ -238,6 +239,10 @@ DEFAULT_SPCONFIG = { 'show_user_agreement_screen': SAML_IDP_SHOW_USER_AGREEMENT_SCREEN } +# CAS Settings + +CAS_AUTH_CLASS = "authentication.cas.KumiDCAuthUser" + # Session Timeouts REVERIFY_AFTER_INACTIVITY_MINUTES = 5 diff --git a/kumidc/urls.py b/kumidc/urls.py index 0f14b03..1448c2a 100644 --- a/kumidc/urls.py +++ b/kumidc/urls.py @@ -1,12 +1,12 @@ from django.contrib import admin -from django.urls import path, re_path, include, reverse_lazy +from django.urls import path, include, reverse_lazy from django.views.generic import RedirectView urlpatterns = [ - re_path(r'^openid/', include('oidc_provider.urls', namespace='oidc_provider')), - - re_path(r'^saml/', include('djangosaml2idp.urls')), + path('openid/', include('oidc_provider.urls', 'oidc_provider')), + path('saml/', include('djangosaml2idp.urls', 'djangosaml2idp')), + path('cas/', include('cas_server.urls', "cas_server")), path('admin/login/', RedirectView.as_view(url=reverse_lazy("auth:login"), query_string=True)), path('admin/', admin.site.urls), diff --git a/requirements.txt b/requirements.txt index f06eeca..db5b547 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ Django git+https://kumig.it/kumitterer/django-oidc-provider/ +git+https://kumig.it/kumitterer/django-cas-server/ git+https://github.com/OTA-Insight/djangosaml2idp/ dbsettings