Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
Vérification de la déconnexion ProConnect
Browse files Browse the repository at this point in the history
En 2 étapes déjà gérées, mais cette fois-ci en véfifiant l'état du
paramètre `state` passé par ProConnect (sécurité).
  • Loading branch information
ikarius committed Oct 7, 2024
1 parent fabef28 commit 53eb69b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
6 changes: 6 additions & 0 deletions dora/oidc/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,17 @@
# dans le fichier `urls.py` de mozilla_django_oidc
# redirection vers ProConnect pour la connexion
path("oidc/login/", views.oidc_login, name="oidc_login"),

# redirection une fois la connexion terminée
path("oidc/logged_in/", views.oidc_logged_in, name="oidc_logged_in"),

# preparation au logout : 2 étapes nécessaires
# l'une de déconnexion sur ProConnect, l'autre locale de destruction de la session active
path("oidc/pre_logout/", views.oidc_pre_logout, name="oidc_pre_logout"),

# la plupart des vues de `mozilla-django-oidc` sont paramètrables
# pas le logout
path("oidc/logout/", views.CustomLogoutView.as_view(), name="oidc_logout"),
]


Expand Down
36 changes: 30 additions & 6 deletions dora/oidc/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import time

from django.core.exceptions import SuspiciousOperation
import jwt
import requests
from django.conf import settings
Expand All @@ -11,7 +12,7 @@
from django.urls import reverse
from django.utils.crypto import get_random_string
from furl import furl
from mozilla_django_oidc.views import OIDCAuthenticationCallbackView, resolve_url
from mozilla_django_oidc.views import OIDCAuthenticationCallbackView, OIDCLogoutView, resolve_url
from rest_framework import permissions
from rest_framework.authtoken.models import Token
from rest_framework.decorators import api_view, permission_classes
Expand Down Expand Up @@ -215,21 +216,22 @@ def oidc_logged_in(request):
@permission_classes([permissions.AllowAny])
def oidc_pre_logout(request):
# attention : le nom oidc_logout est pris par mozilla-django-oidc
# récuperation du token stocké en session:
# récupération du token stocké en session:
if oidc_token := request.session.get("oidc_id_token"):
# construction de l'URL de logout
# ProConnect nécessite un `state` pour vérifier la déconnexion effective
logout_state = get_random_string(32)
request.session["logout_state"] = logout_state
params = {
"id_token_hint": oidc_token,
"state": "todo_xxx",
"state": logout_state,
"post_logout_redirect_uri": request.build_absolute_uri(
reverse("oidc_logout")
),
}
logout_url = furl(settings.OIDC_OP_LOGOUT_ENDPOINT, args=params)
return HttpResponseRedirect(redirect_to=logout_url.url)

# FIXME: URL de fallback ?
return HttpResponseForbidden("Déconnexion incorrecte")
raise SuspiciousOperation("Tentative de déconnexion avec un token incorrect")


class CustomAuthorizationCallbackView(OIDCAuthenticationCallbackView):
Expand Down Expand Up @@ -260,3 +262,25 @@ def success_url(self):

# redirection vers le front via `oidc/logged_in`
return success_url


class CustomLogoutView(OIDCLogoutView):
"""
Logout OIDC :
ProConnect effectue des vérifications avant de déconnecter l'utilisateur
sur sa plateforme.
Essentiellement en vérifiant la validité d'un `state` passé en paramètre
avant la destruction de la session.
Cette classe effectue simplement la vérification du `state` précédemment stocké
en session (voir `oidc/pre_logout`) et réutilise la classe de vue originale
de `mozilla-django-oidc`.
"""

def post(self, request):
if logout_state := request.session.pop("logout_state", None):
if request.GET.get("state") != logout_state:
raise SuspiciousOperation("La vérification de la déconnexion a échoué")
else:
raise SuspiciousOperation("Vérification de la déconnexion impossible")

return super().post(request)

0 comments on commit 53eb69b

Please sign in to comment.