+ {% block branding_login %}{% trans "Sign in to Wagtail" %}{% endblock %}
+
+
+ {# Always show messages div so it can be appended to by JS #}
+ {% if messages or form.errors %}
+
+ {% if form.errors %}
+ {% for error in form.non_field_errors %}
+ - {{ error }}
+ {% endfor %}
+ {% endif %}
+ {% for message in messages %}
+ - {{ message }}
+ {% endfor %}
+
+ {% endif %}
+
+
+ {% block above_login %}{% endblock %}
+
+
+
+ {% block below_login %}{% endblock %}
+
+ {% block branding_logo %}
+
+ {% include "wagtailadmin/logo.html" with wordmark="True" %}
+
+ {% endblock %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/rca/project_styleguide/templates/patterns/pages/auth/logout_confirmation.html b/rca/project_styleguide/templates/patterns/pages/auth/logout_confirmation.html
new file mode 100644
index 000000000..9b5953041
--- /dev/null
+++ b/rca/project_styleguide/templates/patterns/pages/auth/logout_confirmation.html
@@ -0,0 +1,38 @@
+{% extends "wagtailadmin/admin_base.html" %}
+{% load i18n wagtailadmin_tags %}
+{% block titletag %}{% trans "Log out" %}{% endblock %}
+{% block bodyclass %}login{% endblock %}
+
+{% block furniture %}
+
+ {% block branding_login %}{% trans "Logout from Wagtail" %}{% endblock %}
+
+
+
+ {% block branding_logo %}
+
+ {% include "wagtailadmin/logo.html" with wordmark="True" %}
+
+ {% endblock %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/rca/settings/base.py b/rca/settings/base.py
index 9d3f76535..c950ba3e2 100644
--- a/rca/settings/base.py
+++ b/rca/settings/base.py
@@ -112,6 +112,7 @@
"wagtail_rangefilter",
"rangefilter",
"wagtail_modeladmin",
+ "social_django",
]
# Middleware classes
@@ -150,6 +151,9 @@
# This is a custom context processor that lets us add custom
# global variables to all the templates.
"rca.utils.context_processors.global_vars",
+ # Social auth context_processors
+ "social_django.context_processors.backends",
+ "social_django.context_processors.login_redirect",
],
"builtins": ["pattern_library.loader_tags"],
},
@@ -860,3 +864,35 @@
)
# Vepple
VEPPLE_API_URL = env.get("VEPPLE_API_URL", "https://editor.rca.rvhosted.com")
+
+# Azure AD (SSO)
+AUTHENTICATION_BACKENDS = [
+ "social_core.backends.azuread_tenant.AzureADTenantOAuth2",
+ "django.contrib.auth.backends.ModelBackend",
+]
+
+# Social Auth (SSO)
+SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_KEY = env.get(
+ "SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_KEY", None
+)
+SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET = env.get(
+ "SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET", None
+)
+SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_TENANT_ID = env.get(
+ "SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_TENANT_ID", None
+)
+SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = ["username", "first_name", "last_name", "email"]
+SOCIAL_AUTH_JSONFIELD_ENABLED = True
+SOCIAL_AUTH_USER_MODEL = "users.User"
+SOCIAL_AUTH_PIPELINE = (
+ "social_core.pipeline.social_auth.social_details",
+ "social_core.pipeline.social_auth.social_uid",
+ "social_core.pipeline.social_auth.auth_allowed",
+ "social_core.pipeline.social_auth.social_user",
+ "social_core.pipeline.social_auth.associate_by_email",
+ "social_core.pipeline.user.create_user",
+ "social_core.pipeline.social_auth.associate_user",
+ "social_core.pipeline.social_auth.load_extra_data",
+ "social_core.pipeline.user.user_details",
+ "rca.utils.pipeline.make_sso_users_editors",
+)
diff --git a/rca/urls.py b/rca/urls.py
index ba27d8d4b..3b7833e2c 100644
--- a/rca/urls.py
+++ b/rca/urls.py
@@ -11,7 +11,11 @@
from wagtail.documents import urls as wagtaildocs_urls
from wagtail.utils.urlpatterns import decorate_urlpatterns
-from rca.account_management.views import CustomLoginView
+from rca.account_management.views import (
+ CustomLoginView,
+ CustomLogoutView,
+ SSOLogoutConfirmationView,
+)
from rca.search import views as search_views
from rca.utils.cache import get_default_cache_control_decorator
from rca.wagtailapi.api import api_router
@@ -23,6 +27,10 @@
private_urlpatterns = [
path("admin/login/", CustomLoginView.as_view(), name="wagtailcore_login"),
path("admin/_util/login/", CustomLoginView.as_view(), name="wagtailcore_login"),
+ path("admin/logout/", CustomLogoutView.as_view(), name="wagtailcore_logout"),
+ path(
+ "logout/", SSOLogoutConfirmationView.as_view(), name="sso_logout_confirmation"
+ ),
path("django-admin/", admin.site.urls),
path("admin/", include(wagtailadmin_urls)),
path("documents2/", include(wagtaildocs_urls)),
@@ -37,7 +45,10 @@
# Public URLs that are meant to be cached.
-urlpatterns = [path("sitemap.xml", sitemap)]
+urlpatterns = [
+ path("sitemap.xml", sitemap),
+ path("", include("social_django.urls", namespace="social")),
+]
if settings.DEBUG:
diff --git a/rca/utils/pipeline.py b/rca/utils/pipeline.py
new file mode 100644
index 000000000..ab2960b89
--- /dev/null
+++ b/rca/utils/pipeline.py
@@ -0,0 +1,6 @@
+from django.contrib.auth.models import Group
+
+
+def make_sso_users_editors(backend, user, response, *args, **kwargs):
+ editors = Group.objects.get(name="Editors")
+ user.groups.add(editors)