Last week I saw a StackOverflow question where a user was wrestling with an app requesting admin consent. The user wanted to contact an administrator, to ask for the app to be consented, and didn’t know how to do that.

That’s actually an excellent question. I asked around, and it would appear that there’s no efficient way find out who’s a tenant admin (the exact role denomination is “company administrator”) in our current portals. Eran Dvir, a good friend on the directory team, suggested that one could simply use the Graph to find out who’s a member of that particular role… so yesterday night I wrote a quick&dirty app that does just that. I called it Who’s your admin, and you can find it here.

The code is really super simple. First, I get a token for the graph; any directory user will do, given that I am giving the app permission to sign in as the current user and this kind of query can be done by anyone in the org (as long as you do it in a native app).

   1: AuthenticationContext ac = new AuthenticationContext("");

   2: AuthenticationResult ar = ac.AcquireTokenAsync("",

   3:     "f357e8fa-87dd-44f2-84f4-40c2a53e3daf",

   4:     new Uri("http://whatevs"),

   5:     new PlatformParameters(PromptBehavior.Auto)).Result;

Then, I find out what is the objectID of the company administrator role in this particular tenant. I do that by getting all the roles and filtering for the one with display name “company administrator”. As usual, I prefer to do raw REST calls rather than using an SDK. Just personal preference Smile

   1: HttpClient client = new HttpClient();

   2: client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ar.AccessToken);

   3: HttpResponseMessage response = client.GetAsync("").Result;

   4: string rez = response.Content.ReadAsStringAsync().Result;

   5: JObject jo = JObject.Parse(rez);

   6: JObject companyAdminRole = jo["value"].Values<JObject>().Where(m => m["displayName"].Value<string>() == "Company Administrator").FirstOrDefault();

   7: string roleObjID = companyAdminRole["objectId"].ToString();

Once I have that, I can use it to retrieve all the members in that role. Given that I already set up all the HttpClient machinery, the code required is really tiny.

   1: response = client.GetAsync(string.Format("{0}/members?api-version=1.6", roleObjID)).Result;


   3: rez = response.Content.ReadAsStringAsync().Result;

   4: jo = JObject.Parse(rez);

Finally, I just print out some contact info from the results.

   1: foreach (var adm in jo["value"])

   2: {

   3:     // we only want people you can email, not bots

   4:     if (adm["objectType"].ToString() == "User")

   5:     {

   6:         Console.WriteLine("Admin found: {0} ", adm["displayName"]);

   7:         // note: UPN!= email. Also, guess users will have an odd ID here

   8:         Console.WriteLine("UPN: {0} ", adm["userPrincipalName"]);

   9:         // note: mail is not always populated (for example in case of guest users).

  10:         // Try getting otherMails too, for example. 

  11:         Console.WriteLine("Email: {0}",adm["mail"]);

  12:         Console.WriteLine("==========================");

  13:     }

  14: }

Here there’s the output for my usual test tenant. You can see some oddities due to the guest status of one of the users: please refer to the comments in code for some explanation and suggested actions.


Here there’s the thing. This approach can help you if you find yourself precisely in the situation described by the StackOverflow poster, an app needs admin consent and you want to contact an administrator to grant that consent. But it will NOT help if the admin has turned off user consent for the tenant. Why? Well, the console app itself needs to receive your user consent at first run- but if the admin tuned that off, that can’t happen to begin with. Other than sifting through the users in the directory in the portal to find who’s an admin, I wouldn’t know what to do in that case as of today- apart from doing the Italian thing and simply ask my contacts Smile.


Dang. Here you have it.
Note, it is perfectly possible that there’s already a way to find this info without having to run some code (or equivalent powershell if you’re an admin, I guess Smile) – and if I find it, I’ll break my habit of never updating posts and add the new relevant info here. Until then, have fun!


Leave a Reply

Your email address will not be published. Required fields are marked *