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

Migration vers ProConnect #325

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open

Migration vers ProConnect #325

wants to merge 8 commits into from

Conversation

ikarius
Copy link
Contributor

@ikarius ikarius commented Jul 17, 2024

Backend migration ProConnect

Cette PR ajoute la couche technique OIDC nécessaire à une connexion à ProConnect (PC).
La couche de connexion Inclusion-Connect (IC) reste en place comme solution de repli en cas de problèmes lors du déploiement de PC.
Ce déploiement est pour l'instant prévu pour le début 2025.

Utilisation de mozilla-django-oidc

La quasi-totalité du flow OIDC est géré par la librairie mozilla-django-oidc choisie pour sa simplicité et parce que déjà utilisée par d'autres startups de l'écosystème beta.gouv.
Son code est simple, lisible et peut-être facilement assimilé et étendu au besoin (ce qui est notre cas).

La mise en oeuvre de mozilla-django-oidc est essentiellement déclarative :
la plupart des actions, endpoints, callbacks .. sont configurables via de simple settings Django.

Pour les aspects :

  • création et récupération d'utilisateur,
  • personnalisation des interactions : SAFIR, SIRET ...
  • déconnexion

certaines portions de la librairie ont dues être enrobées ou étendues pour ajouter ces fonctionnalités.

Configuration de Django pour PC :

Voir tous les paramètres Django préfixés OIDC_ , ainsi que :

  • LOGIN_REDIRECT_URL
  • LOGOUT_REDIRECT_URL : pour les 2 étapes de déconnexion,
  • OIDC_CALLBACK_CLASS : pour le gestionnaire d'identification personnalisé.

Description des particularités DORA / PC

Connexion au frontend

Pour la connectique IC, certaines parties du flow OIDC sont implémentées coté frontend (appels initiaux, callbacks).

Pour PC, tout est centralisé au niveau du backend.

Une fois le flow OIDC terminé, un token DRF est transmis à la partie frontend pour être stocké sous forme d'entrée localStorage (même mécanisme que pour la connexion actuelle avec IC).

Ce mécanisme devra être revu, ou au moins renforcé une fois IC complètement décommissionné.

Ajouts d'étapes intermédiaires dans le flow OIDC

oidc/oidc_logged_in

Après le callback d'identification OIDC pour permettre :

  • de gérer correctement la redirection en cas de next_url ,
  • de passer le token DRF au frontend.

oidc/oidc_pre_logout

Une déconnexion complète avec PC nécessite 2 étapes, dans l'ordre :

  • effacement des données PC sur le site PC via un token stocké à la connexion et un endpoint spécifique (effacement des cookies du domaines PC),
  • l'effacement de la session sur le serveur Django.

Mal gérer cette phase mène à des états de connexion instables et dans certains cas des problèmes de redirections infinies.

Adaptation de certaines fonctions OIDC

Essentiellement représentées par des vues Django et le gestionnaire d'identification.

Vue CustomLogoutView

Enrobe la vue de déconnexion de mozilla-django-oidc pour permettre les deux étapes :

  • vérification d'un state ,
  • redirection vers le logout de PC,
  • effacement de la session Django.

Vue CustomAuthorizationCallbackView

Permet essentiellement de bien gérer le paramètre next_url et d'effectuer correctement la redirection entre backend et frontend après une identification réussie.

Gestionnaire OIDCAuthenticationBackend

La création d'un gestionnaire d'identification personnalisé est nécessaire pour plusieurs raisons.

D'abord à cause d'un problème (?) d'implémentation par PC lors du retour du token JWT.
Le type de contenu de la réponse n'est pas celui attendu, et un reformatage du token est nécessaire pour éviter une erreur de traitement (voir get_user_info).

Ensuite les traditionnelles étapes de création ou de récupération d'un utilisateur existant après une identification réussie doivent être améliorés pour :

  • la récupération du SIRET et éventuellement du code SAFIR,
  • utiliser un token DRF plutôt que l'identication par défaut de Django,
  • le stockage du sub OIDC en base (pour l'instant pas utilisé).

Voir les méthodes :

  • get_user,
  • update_user,
  • create_user,
  • get_user_info : pour le reformatage du token.

@ikarius ikarius self-assigned this Jul 17, 2024
@ikarius ikarius marked this pull request as draft July 17, 2024 10:31
@ikarius ikarius force-pushed the pro-connect-migration branch 2 times, most recently from 1d18f95 to 90c14c1 Compare September 26, 2024 17:23
Copy link

socket-security bot commented Sep 26, 2024

New dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
pypi/[email protected] environment, eval, filesystem, network, shell Transitive: unsafe +35 303 MB parsys-python

View full report↗︎

@ikarius
Copy link
Contributor Author

ikarius commented Sep 26, 2024

Ca avance, la prochaine fois, ça sort du draft ...

@ikarius ikarius force-pushed the pro-connect-migration branch 3 times, most recently from c48aa4d to cfc0907 Compare October 3, 2024 13:57
@ikarius ikarius marked this pull request as ready for review October 3, 2024 13:58
@ikarius ikarius force-pushed the pro-connect-migration branch 2 times, most recently from d081d75 to 27659ad Compare October 3, 2024 18:06
@ikarius ikarius force-pushed the pro-connect-migration branch 3 times, most recently from b9a4ca2 to 028677c Compare October 7, 2024 10:01
- ajouts des routes pesonnalisées OIDC pour les redirections vers le
front-end
- modification de certaines portions de `mozilla-django-oidc` avec une
vue custom
Ainsi que sa configuration et la modification des routes pour permettre
à la fois l'utilisation de ProConnect et d'Inclusion-Connect
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é).
Dans la configuration précédente, seule l'identification par OIDC était
possible.
Mais la partie admin de Django à besoin de l'identification par "modéle"
(qui est celle par défaut).
Les deux oexistent sereinement maintenant.
Même si on n'en fait encore rien, le point de récupération de la donnée
est identifié dans le code.
Résidu des tests, maintenant l'absence d'e-mail doit lever une
exception.
Copy link
Collaborator

@ggounot ggounot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sacré travail. C'est propre et très bien documenté. Chapeau !

J'ai relu le code et je n'ai rien à redire, mais le « métier » est complexe.

Copy link
Collaborator

@ggounot ggounot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Après avoir fait une recherche, je me connecte avec Pro Connect.

Mon URL passée par par le paramètre next est : /recherche?city=75112&cl=Paris (75)&l=Rue de Lyon 75012 Paris&lat=48.849221&lon=2.370927

À la fin du processus d'identification, je suis redirigé vers : /recherche?city=75112

Il y a donc perte de paramètres de l'URL.

En revanche, quand je me connecte à partir d'une page service avec seulement l'ID de la recherche dans l'URL : /services/bimbamjob-jlgu-titre-professionnel-?searchId=194805 je suis bien redirigé vers cette exacte URL.

dora/oidc/__init__.py Outdated Show resolved Hide resolved
dora/oidc/__init__.py Outdated Show resolved Hide resolved
# attention : l'utilisateur est toujours anonyme (a ce point il n'existe qu'un token DRF)
token = Token.objects.get(user_id=request.session["_auth_user_id"])

redirect_uri = f"{settings.FRONTEND_URL}/auth/pc-callback/{token}/"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question : est-ce qu'on aurait un autre moyen de transmettre le token ? Le faire passer par l'URL n'est pas optimal d'un point de vue sécurité car l'URL peut être loguée, enregistrée dans l'historique et être transmise à un autre site par le header referer.

Copy link
Contributor Author

@ikarius ikarius Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je sais, c'est pour ça que je comptais refaire une passe après.
Inclusion-Connect utilise un POST, mais ce n'est pas possible pour un redirect qui viendrait s'insérer dans le flow OIDC.
C'est un bon point toutefois, je regarde si je peux améliorer de suite ou pas, merci !

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants