Few years ago I wrote a post about how you can obtain the ID of a tenant from one of its domains. Something so simple, and yet I am told that it ended up to be of use for lots of people. Yay!

(BTW, at the time the root domain for Azure AD was login.windows.net, but now it is login.microsoftonline.com)

I do often get asked how to do the inverse operation: given the tenantID, how do I determine the domain associated to it?

Before we answer that question, we need to clarify things a bit. Whereas there’s only one immutable, non-reassignable, gloriously opaque tenantID per tenant, every tenant can register a crazy number of domains. That said, only one of those is designated to be the default domain for the tenant. So, a better formulation would be: given the tenantID, how do I determine the default domain associated to it?

As it turns out, I don’t know of a way to do that without doing an authenticated call to the Microsoft Graph API. Luckily, it’s all super straightforward. Here’s what we need to do:

   1: {

   2:  "capabilities": "Email, OfficeCommunicationsOnline",

   3:  "isDefault": true,

   4:  "isInitial": true,

   5:  "name": "developertenant.onmicrosoft.com",

   6:  "type": "Managed"

   7: }

Clear as mud? here there’s a magical ADAL snippet that will do the job for you.

   1: static void Main(string[] args)

   2: {

   3:

   4:     // put your tenantID here

   5:     string tenantID = "6c3d51dd-f0e5-4959-b4ea-a80c4e36fe5e";

   6:     string orgQuery = string.Format("https://graph.microsoft.com/v1.0/{0}/organization/", tenantID)

   7:     string graphResource = "https://graph.microsoft.com";

   8:

   9:     //get a token to call the Microsoft Graph

  10:     AuthenticationContext ac =

  11:         new AuthenticationContext(string.Format("https://login.microsoftonline.com/{0}",tenantID));

  12:     AuthenticationResult ar = ac.AcquireTokenAsync(graphResource,

  13:         "e11a0451-ac9d-4c89-afd8-d2fa3322ef68",

  14:         new Uri("http://li"),

  15:         new PlatformParameters(PromptBehavior.Always)).Result;

  16:

  17:     //get the company info from the graph

  18:     HttpClient client = new HttpClient();

  19:     HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, orgQuery);

  20:     request.Headers.Authorization =

  21:         new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", ar.AccessToken);

  22:     HttpResponseMessage response = client.SendAsync(request).Result;

  23:     string responseString = response.Content.ReadAsStringAsync().Result;

  24:

  25:     //retrieve the default domain for the tenant

  26:     JObject jo = JObject.Parse(responseString);

  27:     JArray domains = jo["value"][0]["verifiedDomains"] as JArray;

  28:     string defaultDomain = string.Empty;

  29:     foreach(JObject domain in domains)

  30:     {

  31:         if ((bool)domain["isDefault"])

  32:         {

  33:             defaultDomain = domain["name"].ToString();

  34:         }

  35:     }

  36:

  37:     Console.WriteLine("The default domain for tenant {0} is {1}", tenantID, defaultDomain);

  38:     Console.ReadLine();

  39: }

Now, I am sure that some of the Microsoft Graph experts will hasten to point out that instead of specifying the tenantID, I could use common and get https://graph.microsoft.com/v1.0/organization, thus making the code more generic. Unfortunately, that’s not a viable approach:

  • If I already know a user UPN in the default domain, I already know the default domain – and the entire brouhaha becomes unnecessary. The approach might work and might be useful if I have access to a user whose UPN belongs to a NON-default domain verified for the tenantID, however it still falls short for the next point.
  • If the user account I have access to for the tenantID happens to be a guest from a different tenant, the approach with common and no tenantID in the resource URI would yield the default domain of the ORIGIN tenant for the user, rather than the domain for the tenantID we are looking for.

Well, there you have it. I asked to my peeps in the directory service if there’s any simpler way to go about retrieving the default verified domain for a given tenantID, but I didn’t hear back. The above isn’t really that hard, it’s just a GET and a big of JSON scavenging – but who knows, maybe there’s some unauthenticated feed somewhere with the domain info. If I’ll hear something in that sense, I’ll update the post accordingly. Enjoy!

 

Leave a Reply

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