Skip to content

Commit

Permalink
Implement OIDC OP Logout
Browse files Browse the repository at this point in the history
  • Loading branch information
sbreker committed Aug 6, 2024
1 parent fe82c25 commit e17e6c8
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 1 deletion.
2 changes: 2 additions & 0 deletions hack/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ services:
- "archivematica-storage-service"

archivematica-dashboard:
stdin_open: true
tty: true
build:
context: "../"
dockerfile: "hack/Dockerfile"
Expand Down
9 changes: 8 additions & 1 deletion src/dashboard/src/components/accounts/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from components.accounts import views
from django.conf import settings
from django.urls import path
from django.urls import reverse

app_name = "accounts"
urlpatterns = [
Expand All @@ -39,6 +40,7 @@

elif "mozilla_django_oidc" in settings.INSTALLED_APPS:
from components.accounts.views import CustomOIDCLoginView
from components.accounts.views import CustomOIDCLogoutView

Check warning on line 43 in src/dashboard/src/components/accounts/urls.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/urls.py#L42-L43

Added lines #L42 - L43 were not covered by tests

urlpatterns += [

Check warning on line 45 in src/dashboard/src/components/accounts/urls.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/urls.py#L45

Added line #L45 was not covered by tests
path(
Expand All @@ -48,7 +50,12 @@
),
name="login",
),
path("logout/", django.contrib.auth.views.logout_then_login, name="logout"),
#path("logout/", django.contrib.auth.views.logout_then_login, name="logout"),
path(
"logout/",
CustomOIDCLogoutView.as_view(),
name="logout",
),
]

else:
Expand Down
75 changes: 75 additions & 0 deletions src/dashboard/src/components/accounts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
from django.utils.translation import gettext as _
from main.models import UserProfile
from mozilla_django_oidc.views import OIDCAuthenticationRequestView
from mozilla_django_oidc.views import OIDCLogoutView
from tastypie.models import ApiKey
from urllib.parse import urlencode


@user_passes_test(lambda u: u.is_superuser, login_url="/forbidden/")
Expand Down Expand Up @@ -243,3 +245,76 @@ def get(self, request):
self.request = request

Check warning on line 245 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L245

Added line #L245 was not covered by tests

return super().get(request)

Check warning on line 247 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L247

Added line #L247 was not covered by tests


class CustomOIDCLogoutView(OIDCLogoutView):
"""
Provide OpenID Logout capability
"""

def get_settings(self, attr, *args):
if attr in ["OIDC_RP_CLIENT_ID", "OIDC_RP_CLIENT_SECRET"]:
# Retrieve the request object stored in the instance.
request = getattr(self, "request", None)

Check warning on line 258 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L258

Added line #L258 was not covered by tests

if request:
provider_name = request.session.get("providername")

Check warning on line 261 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L261

Added line #L261 was not covered by tests

if (
provider_name
and provider_name in settings.OIDC_SECONDARY_PROVIDER_NAMES
):
provider_settings = settings.OIDC_PROVIDERS.get(provider_name, {})
value = provider_settings.get(attr)

Check warning on line 268 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L267-L268

Added lines #L267 - L268 were not covered by tests

if value is None:
raise ImproperlyConfigured(

Check warning on line 271 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L271

Added line #L271 was not covered by tests
f"Setting {attr} for provider {provider_name} not found"
)
return value

Check warning on line 274 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L274

Added line #L274 was not covered by tests

# If request is None or provider_name session var is not set or attr is
# not in the list, call the superclass's get_settings method.
return OIDCLogoutView.get_settings(attr, *args)

Check warning on line 278 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L278

Added line #L278 was not covered by tests

def post(self, request):
self.request = request

Check warning on line 281 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L281

Added line #L281 was not covered by tests

return super().post(request)

Check warning on line 283 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L283

Added line #L283 was not covered by tests

def get(self, request):
self.request = request

Check warning on line 286 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L286

Added line #L286 was not covered by tests

return super().post(request)

Check warning on line 288 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L288

Added line #L288 was not covered by tests

def get_oidc_logout_url(self, request):
"""
Constructs the OIDC logout URL for Keycloak.
"""
# Retrieve the ID token from the session
id_token = request.session.get('oidc_id_token')

Check warning on line 295 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L295

Added line #L295 was not covered by tests

if not id_token:
raise ValueError("ID token not found in session.")

Check warning on line 298 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L298

Added line #L298 was not covered by tests

# Retrieve the current provider name from the session
provider_name = request.session.get("providername", settings.OIDC_PRIMARY_PROVIDER_NAME)
provider_settings = settings.OIDC_PROVIDERS.get(provider_name, {})

Check warning on line 302 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L301-L302

Added lines #L301 - L302 were not covered by tests

# Get the end session endpoint from the provider settings
end_session_endpoint = provider_settings.get("OIDC_OP_LOGOUT_ENDPOINT")

Check warning on line 305 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L305

Added line #L305 was not covered by tests

if not end_session_endpoint:
raise ValueError("OIDC logout endpoint not configured for provider.")

Check warning on line 308 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L308

Added line #L308 was not covered by tests

# Define the post logout redirect URL
post_logout_redirect_uri = request.build_absolute_uri(settings.LOGOUT_REDIRECT_URL)

Check warning on line 311 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L311

Added line #L311 was not covered by tests

# Construct the logout URL with required parameters
params = {

Check warning on line 314 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L314

Added line #L314 was not covered by tests
'id_token_hint': id_token,
'post_logout_redirect_uri': post_logout_redirect_uri,
}
logout_url = f"{end_session_endpoint}?{urlencode(params)}"

Check warning on line 318 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L318

Added line #L318 was not covered by tests

return logout_url

Check warning on line 320 in src/dashboard/src/components/accounts/views.py

View check run for this annotation

Codecov / codecov/patch

src/dashboard/src/components/accounts/views.py#L320

Added line #L320 was not covered by tests

0 comments on commit e17e6c8

Please sign in to comment.