Skip to content

Commit 246d2e9

Browse files
committed
Add OIDCLogoutOnlyMixin to RPInitiatedLogoutView
1 parent 4d98b58 commit 246d2e9

File tree

3 files changed

+64
-2
lines changed

3 files changed

+64
-2
lines changed

oauth2_provider/views/mixins.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,3 +326,27 @@ def dispatch(self, *args, **kwargs):
326326
log.warning(self.debug_error_message)
327327
return HttpResponseNotFound()
328328
return super().dispatch(*args, **kwargs)
329+
330+
331+
class OIDCLogoutOnlyMixin(OIDCOnlyMixin):
332+
"""
333+
Mixin for views that should only be accessible when OIDC and OIDC RP-Initiated Logout are enabled.
334+
335+
If either is not enabled:
336+
337+
* if DEBUG is True, raises an ImproperlyConfigured exception explaining why
338+
* otherwise, returns a 404 response, logging the same warning
339+
"""
340+
341+
debug_error_message = (
342+
"The django-oauth-toolkit OIDC RP-Initiated Logout view is not enabled unless you "
343+
"have configured OIDC_RP_INITIATED_LOGOUT_ENABLED in the settings"
344+
)
345+
346+
def dispatch(self, *args, **kwargs):
347+
if not oauth2_settings.OIDC_RP_INITIATED_LOGOUT_ENABLED:
348+
if settings.DEBUG:
349+
raise ImproperlyConfigured(self.debug_error_message)
350+
log.warning(self.debug_error_message)
351+
return HttpResponseNotFound()
352+
return super().dispatch(*args, **kwargs)

oauth2_provider/views/oidc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from ..http import OAuth2ResponseRedirect
2323
from ..models import get_application_model
2424
from ..settings import oauth2_settings
25-
from .mixins import OAuthLibMixin, OIDCOnlyMixin
25+
from .mixins import OAuthLibMixin, OIDCLogoutOnlyMixin, OIDCOnlyMixin
2626

2727

2828
Application = get_application_model()
@@ -207,7 +207,7 @@ def validate_logout_request(user, id_token_hint, client_id, post_logout_redirect
207207
return prompt_logout, (post_logout_redirect_uri, application)
208208

209209

210-
class RPInitiatedLogoutView(OIDCOnlyMixin, FormView):
210+
class RPInitiatedLogoutView(OIDCLogoutOnlyMixin, FormView):
211211
template_name = "oauth2_provider/logout_confirm.html"
212212
form_class = ConfirmLogoutForm
213213

tests/test_mixins.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from oauth2_provider.oauth2_validators import OAuth2Validator
1212
from oauth2_provider.views.mixins import (
1313
OAuthLibMixin,
14+
OIDCLogoutOnlyMixin,
1415
OIDCOnlyMixin,
1516
ProtectedResourceMixin,
1617
ScopedResourceMixin,
@@ -145,6 +146,15 @@ def get(self, *args, **kwargs):
145146
return TView.as_view()
146147

147148

149+
@pytest.fixture
150+
def oidc_logout_only_view():
151+
class TView(OIDCLogoutOnlyMixin, View):
152+
def get(self, *args, **kwargs):
153+
return HttpResponse("OK")
154+
155+
return TView.as_view()
156+
157+
148158
@pytest.mark.oauth2_settings(presets.OIDC_SETTINGS_RW)
149159
def test_oidc_only_mixin_oidc_enabled(oauth2_settings, rf, oidc_only_view):
150160
assert oauth2_settings.OIDC_ENABLED
@@ -153,6 +163,14 @@ def test_oidc_only_mixin_oidc_enabled(oauth2_settings, rf, oidc_only_view):
153163
assert rsp.content.decode("utf-8") == "OK"
154164

155165

166+
@pytest.mark.oauth2_settings(presets.OIDC_SETTINGS_RP_LOGOUT)
167+
def test_oidc_logout_only_mixin_oidc_enabled(oauth2_settings, rf, oidc_only_view):
168+
assert oauth2_settings.OIDC_RP_INITIATED_LOGOUT_ENABLED
169+
rsp = oidc_only_view(rf.get("/"))
170+
assert rsp.status_code == 200
171+
assert rsp.content.decode("utf-8") == "OK"
172+
173+
156174
def test_oidc_only_mixin_oidc_disabled_debug(oauth2_settings, rf, settings, oidc_only_view):
157175
assert oauth2_settings.OIDC_ENABLED is False
158176
settings.DEBUG = True
@@ -161,6 +179,14 @@ def test_oidc_only_mixin_oidc_disabled_debug(oauth2_settings, rf, settings, oidc
161179
assert "OIDC views are not enabled" in str(exc.value)
162180

163181

182+
def test_oidc_logout_only_mixin_oidc_disabled_debug(oauth2_settings, rf, settings, oidc_logout_only_view):
183+
assert oauth2_settings.OIDC_RP_INITIATED_LOGOUT_ENABLED is False
184+
settings.DEBUG = True
185+
with pytest.raises(ImproperlyConfigured) as exc:
186+
oidc_logout_only_view(rf.get("/"))
187+
assert str(exc.value) == OIDCLogoutOnlyMixin.debug_error_message
188+
189+
164190
def test_oidc_only_mixin_oidc_disabled_no_debug(oauth2_settings, rf, settings, oidc_only_view, caplog):
165191
assert oauth2_settings.OIDC_ENABLED is False
166192
settings.DEBUG = False
@@ -169,3 +195,15 @@ def test_oidc_only_mixin_oidc_disabled_no_debug(oauth2_settings, rf, settings, o
169195
assert rsp.status_code == 404
170196
assert len(caplog.records) == 1
171197
assert "OIDC views are not enabled" in caplog.records[0].message
198+
199+
200+
def test_oidc_logout_only_mixin_oidc_disabled_no_debug(
201+
oauth2_settings, rf, settings, oidc_logout_only_view, caplog
202+
):
203+
assert oauth2_settings.OIDC_RP_INITIATED_LOGOUT_ENABLED is False
204+
settings.DEBUG = False
205+
with caplog.at_level(logging.WARNING, logger="oauth2_provider"):
206+
rsp = oidc_logout_only_view(rf.get("/"))
207+
assert rsp.status_code == 404
208+
assert len(caplog.records) == 1
209+
assert caplog.records[0].message == OIDCLogoutOnlyMixin.debug_error_message

0 commit comments

Comments
 (0)