Retrouver ”l’object SID” de l’utilisateur enregistré par SharePoint

Voilà un petit article pour partager un “trick” pour un cas d’usage bien particulier mais qui vous dépannera peut être un jour et vous sauvera même peut être la journée !

Je suis donc dans le contexte suivant :

  • un application développée en C#, tournant sur un SharePoint On Premises, hébergée dans une web application dédiée, avec une seule collection de site à la racine
  • Pas de service de UserProfile associé à la WebApp
  • Une partie du code de l’application doit retrouver des informations sur un utilisateur, à partir du login au format claims, dans l’active directory via des requêtes LDAP.

Jusque là rien de très méchant, l’utilisateur étant retrouvé par son login (décodage au format Windows, et recherche LDAP sur la propriété samAccountName).

MAIS le problème se produit lorsque le login de l’utilisateur change côté AD (par exemple un mariage (donc un changement de nom) ou un changement d’entité ce qui entraine par exemple un changement de préfix dans le login.

Peu importe… ce qui pose soucis c’est que sans service de synchronisation de profil, ce changement n’est pas reflété sur le login utilisateur côté SharePoint, car l’utilisateur en question s’étant déjà connecté au site, son “ancien” login est associé à la collection de site. Même si en fait en “interne” SharePoint autorise bien l’utilisateur avec son “nouveau” login car il est reconnu via son identifiant unique AD, l’object SID !

Le bon moyen serait de mettre à jour le login de l’utilisateur dans la base de SharePoint, en utilisant par exemple la commande PowerShell Move-SPUser (ou MigrateUser avec stsadm)

Mais quand est il du code (le temps que le SharePoint soit mis à jour) ?

Il faut l’adapter donc pour faire une recherche par SID dans l’AD. Comme ça quelque soit le login “vu” par SharePoint, on tombe sur le bon utilisateur dans l’AD.

Ok, mais comment récupérer ce SID côté SharePoint ? ça semble simple de premier abords, mais il y a en fait quelques pièges :

  1. Ma première idée est d’utiliser la méthode EnsureUser de la classe SPWeb. En lui passant le login il devrait me retrouver l’objet de type SPUser qui va bien et avec un peu de chance j’aurais une propriété SID dessus. Sauf que EnsureUser plante en disant qu’il ne trouve pas l’utilisateur ! Il semble qu’il y ai un appel à l’AD se basant sur le login et donc qui échoue….
  2. Donc je décide de finalement utiliser la collection AllUsers du root web, et de chercher le bon SPUser par comparaison de logins. Au final ça marche pas mal.
  3. J’ai donc un SPUser, et coup de bol la classe SPUser a bien une propriété SID. MAIS second drame, cette propriété est dans mon cas systématiquement vide (même pour les utilisateurs “valide”) pour les utilisateurs ayant un login au format CLAIMS :
    SNAGHTML4f8ce31
  4. Et c’est là qu’on découvre une nouvelle propriété sous SharePoint 2013 sur la classe SPUser : SystemUserKey. Et vous constaterez qu’à 2 ou 3 caractères près (le prefix) vous retrouverez un SID, celui de l’objet d’origine dans l’AD.
    SNAGHTML4faf6a7
  5. Et dernier drame, je suis dans une application SharePoint 2010, cette propriété n’existe pas… en tout cas elle n’est pas publique. Pour y accéder, il faut donc passer par un bout de reflection, voici le code :
usrSID = ausr.GetType().InvokeMember("SystemUserKey", System.Reflection.BindingFlags.GetProperty | System.Reflection.BindingFlags.NonPublic | BindingFlags.Instance, null, ausr, null).ToString();
 usrSID = usrSID.Substring(usrSID.IndexOf("s"));


(la variable ausr est une instance de SPUser)

Voilà pour résumer, retrouver un utilisateur par son login c’est mal, le retrouver par un vrai identifiant qui ne change jamais c’est mieux ! Et maintenant même si cet identifiant unique est bien planqué dans votre SharePoint, vous savez où le trouver !

Tagués avec : , , , , , , , , ,

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*

Verifions que vous êtes un humain * Time limit is exhausted. Please reload CAPTCHA.