Azure UPN Display (#7585)

stephannn committed Jan 31, 2026 at 11:40 UTC 2542fc857b7ae01c461c2ec948a80309c4af3979
1 file changed +110 -1
agents/meshcore.js
+110 -1
@@ -137,6 +137,100 @@ function getDomainInfo() {
137 return (ret);
138 }
139
140 +function getLogonCacheKeys() {
141 + var registry = require('win-registry');
142 + var HKLM = registry.HKEY.LocalMachine;
143 +
144 + var userObj = [];
145 +
146 + function readSubKeys(path) {
147 + var vals = registry.QueryKey(HKLM, path);
148 + if (!vals) return;
149 +
150 + // Extract IdentityName, SAMName, SID if they exist
151 + var identityName = null, samName = null, sid = null;
152 +
153 + for (var i = 0; i in vals.values; i++) {
154 + if (vals.values[i].toLowerCase() === 'identityname' && identityName === null) {
155 + identityName = registry.QueryKey(HKLM, path, vals.values[i]);
156 + }
157 + if (vals.values[i].toLowerCase() === 'samname' && samName === null) {
158 + samName = registry.QueryKey(HKLM, path, vals.values[i]);
159 + }
160 + if (vals.values[i].toLowerCase() === 'sid' && sid === null) {
161 + sid = registry.QueryKey(HKLM, path, vals.values[i]);
162 + }
163 + }
164 +
165 + // If IdentityName exists, add to userObj
166 + if (identityName) {
167 + userObj.push({
168 + UPN: identityName,
169 + SAM: samName,
170 + SID: sid
171 + });
172 + }
173 +
174 + // Recurse into subkeys if any
175 + if (vals.subkeys && vals.subkeys.length > 0) {
176 + for (var j = 0; j < vals.subkeys.length; j++) {
177 + readSubKeys(path + '\\' + vals.subkeys[j]);
178 + }
179 + }
180 + }
181 +
182 + // Start recursion from the LogonCache root
183 + readSubKeys('SOFTWARE\\Microsoft\\IdentityStore\\LogonCache');
184 +
185 + var grouped = {};
186 +
187 + function pushUnique(arr, val) {
188 + if (val && arr.indexOf(val) === -1) arr.push(val);
189 + }
190 +
191 + // Group by UPN and merge values
192 + for (var i = 0; i < userObj.length; i++) {
193 + var u = userObj[i];
194 +
195 + if (!grouped[u.UPN]) grouped[u.UPN] = {UPN: u.UPN, SID: [], SAM: []};
196 +
197 + pushUnique(grouped[u.UPN].SID, u.SID);
198 + pushUnique(grouped[u.UPN].SAM, u.SAM);
199 + }
200 +
201 + userObj = [];
202 + // Convert grouped object to array
203 + for (var k in grouped) if (grouped.hasOwnProperty(k)) userObj.push(grouped[k]);
204 +
205 + return userObj;
206 +
207 +}
208 +
209 +function getJoinState() {
210 + if (process.platform != 'win32') { return -1; }
211 +
212 + var isAzureAD = false;
213 + var isOnPrem = false;
214 +
215 + // 1 Azure AD / Entra ID
216 + try {
217 + const joinInfo = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Control\\CloudDomainJoin\\JoinInfo');
218 + isAzureAD = Array.isArray(joinInfo.subkeys) && joinInfo.subkeys.length > 0;
219 + } catch (e) {}
220 +
221 + // 2 On-prem AD
222 + try {
223 + const tcpip = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters','Domain');
224 + isOnPrem = !!(tcpip !== "" || null);
225 + } catch (e) {}
226 +
227 + if (isAzureAD && isOnPrem) return 12;
228 + if (isAzureAD) return 1;
229 + if (isOnPrem) return 2;
230 +
231 + return 0;
232 +
233 +}
234
235
236 try {
@@ -688,13 +782,28 @@ function onUserSessionChanged(user, locked) {
782 if (user && locked && (JSON.stringify(a[i]) === JSON.stringify(user))) { if (meshCoreObj.lusers.indexOf(un) == -1) { meshCoreObj.lusers.push(un); } }
783 else if (user && !locked && (JSON.stringify(a[i]) === JSON.stringify(user))) { meshCoreObj.lusers.splice(meshCoreObj.lusers.indexOf(un), 1); }
784 if (u.indexOf(un) == -1) { u.push(un); } // Only push users in the list once.
691 - if (a[i].Domain != null && a[i].Domain == 'AzureAD'){
785 + if ((a[i].Domain != null && a[i].Domain == 'AzureAD') || getJoinState() == 1 ){
786 // AzureAD to-do
787 // var userGUID = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Control\\CloudDomainJoin\\JoinInfo');
788 // if (userGUID != null){
789 // var user = require('win-registry').QueryKey(require('win-registry').HKEY.LocalMachine, 'SYSTEM\\CurrentControlSet\\Control\\CloudDomainJoin\\JoinInfo\\' + userGUID.subkeys[0], 'UserEmail');
790 // if (user != null) u[i].UPN = user;
791 // }
792 + var userobj = getLogonCacheKeys();
793 +
794 + if(userobj && userobj.length > 0){
795 +
796 + for (var j = 0; j < userobj.length; j++) {
797 + var u = userobj[j];
798 +
799 + if (u && u.SAM && u.SAM[0].trim().toLowerCase() === a[i].Username) {
800 + meshCoreObj.upnusers.push(u.UPN);
801 + break;
802 + }
803 + }
804 +
805 + }
806 +
807 } else if (a[i].Domain != null) {
808 if (ret != null && ret.PartOfDomain === true) {
809 meshCoreObj.upnusers.push(a[i].Username + '@' + ret.Domain);