Usurpation d’identité utilisateur
Certains bugs n’existent que pour une seule personne. Un enregistrement qui ne s’ouvre pas, un élément de menu absent, un total qui semble incorrect — tout dépend des rôles web, des permissions de table et des rôles de sécurité Dataverse attachés à ce contact. L’usurpation d’identité utilisateur permet à un administrateur interne de se connecter en tant que contact et de voir précisément ce qu’il voit, puis de ressortir.
Quand ça aide
L’usurpation d’identité répond à des questions qu’une description du problème ne peut pas.
- Reproduire un problème de support. Plutôt que de raisonner sur la permission qui pourrait manquer, vous regardez la page comme la personne qui la signale.
- Vérification d’un changement de permission. Après avoir modifié un rôle web ou une permission de table, confirmez l’effet sur un contact réel au lieu de l’inférer.
- Vérifier ce qu’un rôle révèle réellement. Utile avant la mise en service, quand l’écart entre l’accès prévu et l’accès réel est le plus facile à se tromper.
L’utiliser
La possibilité se trouve dans le menu de profil et n’apparaît que pour les utilisateurs autorisés à l’utiliser.
- Connectez-vous en tant qu’utilisateur interne occupant le rôle d’administrateur, puis ouvrez le menu du profil et choisissez Voir en tant qu’autre utilisateur.
- Tapez au moins trois caractères pour rechercher par nom ou adresse e-mail, ou collez un identifiant utilisateur pour une correspondance exacte.
- Choisissez la personne et confirmez. Le portail se recharge en tant qu’elle — mêmes rôles web, mêmes permissions de table, mêmes lignes.
- Une bannière reste épinglée en haut de chaque page aussi longtemps qu’elle dure. Choisissez Arrêter pour revenir à votre propre session.
Qui peut se faire passer pour un personnage
Deux conditions sont vérifiées sur le serveur pour chaque appel, indépendamment de ce que l’interface offre :
- L’utilisateur connecté occupe ce
SystemAdminrôle. Votre projet décide quel rôle de sécurité Dataverse l’accorde — les modèles générés cartographient le rôle intégré d’Administrateur Système ainsi qu’un rôle configurable viaPortalIdentityOptions.SystemAdminRoleName. - L’utilisateur connecté est un véritable utilisateur interne Dataverse. Cela est coché séparément du poste, donc un contact portail ne peut jamais se faire passer pour personne, même si votre projet lui accorde le rôle par erreur.
La cible est toujours un contact de portail, résolu uniquement via la table de contacts. Fournir l’identifiant d’un autre utilisateur interne ne résout tout simplement pas — il n’y a pas de chemin d’ici vers un second compte personnel.
L’usurpation d’identité ne réduit jamais l’accès que
Un utilisateur interne devient un contact, jamais l’inverse et jamais un autre utilisateur interne. Cette direction est ce qui permet à la fonctionnalité de livrer : la session usurpée ne peut faire que moins que l’administrateur, donc il n’y a aucun privilège à en tirer une.
Restreindre qui peut être usurpé d’identité
Par défaut, chaque contact actif est un candidat. Mettez en place IImpersonationTargetFilter une restriction — pour exclure les contacts liés aux comptes du personnel, aux dossiers en dehors de l’unité commerciale de l’administrateur, ou tout autre élément que votre organisation considère comme interdit.
public sealed class StaffContactsAreOffLimits : IImpersonationTargetFilter
{
public async Task<bool> CanImpersonateAsync(
ClaimsPrincipal impersonator, Guid targetContactId, CancellationToken ct)
{
// Return false to hide the contact from search AND refuse impersonation.
return await this.IsOrdinaryPortalContactAsync(targetContactId, ct);
}
}
// Program.cs
builder.Services.AddScoped<IImpersonationTargetFilter, StaffContactsAreOffLimits>();
Le filtre régit la recherche ainsi que l’usurpation d’identité. Un contact que vous rejetez est invisible dans le sélectionneur plutôt que simplement non sélectionnable — sinon, la recherche deviendrait discrètement un moyen d’énumérer des personnes qu’un administrateur ne pourra jamais réellement devenir.
La trace d’audit
Chaque départ, arrêt et refus est enregistré. Les refus sont enregistrés délibérément : une série de succès seule ne peut pas répondre à la question de savoir si quelqu’un a essayé.
Dataverse ne peut pas enregistrer qui était derrière la session
Le portail se connecte à Dataverse en tant qu’utilisateur unique de l’application et exprime la session connectée en usurpant l’identité de la cible. L’administrateur n’est jamais transmis, donc dans le journal d’audit Dataverse, « un administrateur agissant comme contact » et « ce contact se connectant normalement » sont indiscernables — et tout ce qui est écrit lors de l’usurpation d’identité est attribué au contact dans
createdbyetmodifiedby. La piste côté portail est le seul endroit où cette information existe, c’est pourquoi elle n’est pas optionnelle.
Chaque événement est écrit dès la sortie de la boîte, dans le journal d’application. Implémentez IImpersonationAuditSink qu’il le maintient partout où votre organisation conserve ses enregistrements d’audit — les puits sont ajoutés en parallèle de l’intégral plutôt que de le remplacer.
public sealed class ImpersonationAuditTable : IImpersonationAuditSink
{
public Task OnStartedAsync(ImpersonationAuditEvent e, CancellationToken ct) => this.WriteAsync("started", e, ct);
public Task OnStoppedAsync(ImpersonationAuditEvent e, CancellationToken ct) => this.WriteAsync("stopped", e, ct);
// Denied attempts matter as much as successful ones — a trail of
// successes alone can't answer "did anyone try?".
public Task OnDeniedAsync(ImpersonationAuditEvent e, string reason, CancellationToken ct) => this.WriteAsync(reason, e, ct);
}
// Program.cs — added, not replaced: the framework's own logging sink stays.
builder.Services.AddTransient<IImpersonationAuditSink, ImpersonationAuditTable>();
De React
La même expérience est livrée pour React : une entrée dans le menu de profil, le sélecteur et la bannière. Les actions sous-jacentes sont activées useAuth() si vous préférez construire votre propre interface autour d’elles.
const auth = useAuth();
// Search, then start. Both are refused server-side unless the caller
// is an internal user holding the SystemAdmin role.
const { results } = await auth.searchImpersonationTargets('smith');
await auth.impersonate(results[0].contactId);
// While impersonating, `auth.user` describes the CONTACT.
auth.user.isImpersonating; // true
auth.user.impersonatorName; // the administrator behind the session
await auth.stopImpersonation();
Ça vaut la peine de le savoir
- Si le contact usurpé change son mot de passe en cours de session, la session se termine et vous êtes renvoyé à l’état déconnecté plutôt qu’à votre propre compte. Se reconnecter à nouveau le rétablit.
- L’usurpation ne peut pas être imbriquée. Arrêtez la session en cours avant d’en commencer une autre.
- Cela ne dure pas plus longtemps que la session du navigateur — fermer le navigateur la met en fin.
