Usurpation d'identité
Audience
Cet article s'adresse aux opérateurs de la plateforme GCM. Les administrateurs d'église devraient consulter Utilisateurs et rôles — l'usurpation d'identité n'est disponible que pour le personnel ayant la revendication platform_admin ou superadmin, et c'est l'action la plus auditée de la plateforme.
L'usurpation d'identité permet à un utilisateur du personnel d'entrer dans l'espace de travail d'un client comme s'il était l'administrateur de cette organisation, afin qu'il puisse reproduire un bogue, exécuter une correction unique ou guider un client à travers un écran lors d'un appel. C'est une fonctionnalité régulière, pas une porte dérobée — chaque entrée et chaque sortie est capturée dans platform_audit_log, restreinte à une clé sessionStorage (pas localStorage, pas un cookie) et se termine automatiquement à la fermeture de l'onglet.

Comment démarrer une session
Depuis la liste Organisations, ouvrez la feuille de détails de n'importe quelle ligne (le chevron à la fin de la ligne, ou Ouvrir dans le tableau Opérations de facturation). La feuille latérale droite montre le plan, le statut, le personnel et les modules. Le bouton bleu Ouvrir le compte en haut de la ligne d'actions est le point d'entrée.
Cliquez dessus, et trois choses se produisent dans l'ordre :
- Une boîte de dialogue de confirmation demande une raison en texte libre. C'est obligatoire.
- Le frontend appelle le RPC Postgres
start_impersonationavec l'id de l'organisation cible et la raison. - Si le RPC réussit, la ligne dans
admin_impersonationest créée, l'id de l'organisation est écrit dans sessionStorage sous la clégcm_impersonation, le cache React Query est effacé (pour empêcher la fuite de données inter-organisations), et l'utilisateur est redirigé vers/— qui résout maintenant vers la coque du locataire client.
Une bannière rouge indiquant "Vue en tant que ... (usurpation d'identité)" apparaît en haut de la coque du locataire. Les pages d'administration du client s'affichent comme si vous étiez lui : son tableau de bord, ses membres, ses dons. Vous pouvez cliquer sur n'importe quel bouton que son administrateur pourrait cliquer.
Une cible à la fois
Démarrer une nouvelle usurpation d'identité alors qu'une est en cours est bloqué par le RPC. Mettez fin à la session en cours d'abord. Le comportement est intentionnel — la table d'audit suppose une ligne active par acteur.
À quoi sert la raison
Le champ raison est obligatoire et finit dans trois endroits :
- La colonne
admin_impersonation.reason. - La ligne
platform_audit_logavecaction = 'impersonation_started'. - Le KPI "Usurpations d'identité" sur 7 jours sur l'onglet du journal d'audit.
Écrivez quelque chose qu'un futur auditeur pourra lire. "Ticket de support n°4421 — le donateur voit un 500 sur le formulaire de don" est bon. "vérification" ne l'est pas. L'auditeur, c'est vous, dans 90 jours, après que le client se plaigne.
Comment RLS vous garde dans le périmètre
Pendant que vous usurpez, l'assistant SQL current_org_id() renvoie l'id de l'organisation cible au lieu du vôtre. Chaque politique RLS sur la plateforme utilise current_org_id() (et non les revendications JWT brutes), donc les lectures et les écritures sont silencieusement restreintes aux données du client. Vous pouvez lire ses membres parce que la politique passe ; vous ne pouvez pas lire les membres d'une autre organisation parce que l'assistant ne renvoie pas son id.
C'est pourquoi nous utilisons current_org_id() et non auth.jwt() ->> 'organization_id' dans les politiques. Cette dernière fuirait à travers l'usurpation d'identité.
Il y a un filet de sécurité supplémentaire : les fonctions edge lisent le contexte d'usurpation d'identité via getCallerContext afin qu'elles sachent aussi qu'elles s'exécutent sous l'id d'un client, pas le vôtre. Les journaux d'audit incluent à la fois actor_id (vous) et target_org_id (le client) afin qu'une piste forensique existe de toute façon.
Comment une session se termine
Une session se termine de trois manières :
- Vous revenez au mode plateforme — cliquez sur Retour à la plateforme dans la bannière. Le frontend appelle
end_impersonation, efface sessionStorage, efface le cache React Query, écrit une ligne d'auditimpersonation_endedet vous pousse vers/platform. - Vous fermez l'onglet — sessionStorage est effacé automatiquement. La ligne
admin_impersonationreste ouverte jusqu'à votre prochaine connexion, mais la portée du JWT est partie et la prochaine connexion de l'utilisateur du personnel la ferme. Raison de cette conception : un appareil volé ne peut pas reprendre une session en rouvrant l'onglet. - Vous vous déconnectez — pareil que fermer l'onglet du point de vue de l'usurpation d'identité.
L'imbrication (usurper, rafraîchir l'onglet, usurper quelqu'un d'autre) est bloquée parce que le nouvel appel RPC met fin à la ligne précédente avant d'en créer une nouvelle.
Ce que vous devriez et ne devriez pas faire
À faire
- Reproduire le bogue que le client a signalé, puis revenir.
- Guider un client à travers un écran lors d'un appel — il voit votre curseur, vous voyez ses données.
- Exécuter une correction unique documentée (par exemple, semer un fonds par défaut manquant) quand il a approuvé le changement par écrit.
À ne pas faire
- Modifier la configuration que le client n'attendrait pas que vous touchiez. Si vous n'êtes pas sûr, demandez d'abord et liez la demande dans le champ raison.
- Envoyer des messages, publier dans des canaux ou déclencher des workflows en tant que le client. Le destinataire voit le nom et le numéro de l'organisation, pas les vôtres — tout ce que vous envoyez lui est attribué de façon permanente.
- Rester en usurpation d'identité plus longtemps que la tâche ne prend. La bannière est visible pour quiconque passe devant votre écran.
Lire la piste d'audit d'usurpation d'identité
L'onglet Journal d'audit porte un KPI sur 7 jours pour les usurpations d'identité et le AuditLogViewer vous permet de filtrer par action. Trois actions importent :
impersonation_started— démarrage réussi. Les métadonnées incluenttarget_org_id,org_name,reason.impersonation_ended— sortie propre via Retour à la plateforme.impersonation_failed— le RPCstart_impersonationa rejeté l'appel. Les métadonnées incluent l'erreur sous-jacente. Une tentative échouée est généralement un mauvais déclenchement RLS, une organisation cible qui n'existe plus, ou un compte de personnel qui vient de perdre sa revendication.
Filtrez par actor_email = <vous> pour voir vos propres sessions des 7 derniers jours. Filtrez par metadata->>'target_org_id' = <id> pour voir chaque session du personnel contre un client — une réponse utile à "quelqu'un de votre équipe s'est-il connecté à notre compte récemment ?".
Quand quelque chose semble anormal
Si vous arrivez sur une page de locataire et que les données ne ressemblent pas à celles du client — mauvais noms de membres, mauvaise langue, mauvais logo d'organisation — revenez immédiatement au mode plateforme. Deux modes de défaillance peuvent causer cela :
- Cache obsolète — le cache React Query a survécu à l'entrée. Faites un rafraîchissement forcé de la page ; si cela résout, le bogue est dans le chemin d'entrée et mérite un problème Sentry.
- Ligne d'usurpation d'identité coincée — votre session précédente n'a pas été fermée proprement et
current_org_id()renvoie l'ancienne cible. Déconnectez-vous complètement, reconnectez-vous, et l'auth-hook réinitialisera le JWT.
Dans les deux cas, écrivez une entrée d'audit ensuite expliquant ce que vous avez vu. Tout l'intérêt de l'auditabilité de la surface d'usurpation d'identité est que nous apprenons des cas limites.
