Search code examples
azure-active-directorymicrosoft-graph-apioffice-js

How to get the organization (tenant) id from user profile using the Microsoft Graph API


I'm creating an add-in that I to sell using organizational licenses.

I have implemented an authentication scheme on the add-in. I'm currently asking for User.Read scope for a sure authenticating using and Azure v2 endpoint. To get the user's information I'm querying

https://graph.microsoft.com/v1.0/me

To properly test for the user's license I need extract the user's organization's identification. However, the user information I receive from the Grah request is increadibly lean. For an AAD account the schema looks something like:

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
  businessPhones: [],
  displayName: "FirstName LastName",
  givenName: "FirstName",
  id: "unique-id",
  jobTitle: null,
  mail: "First.LastName@COMPANYDOMAIN.COM",
  mobilePhone: null,
  officeLocation: null,
  preferredLanguage: null,
  surname: "LastName",
  userPrincipalName: "FILastName@COMPANYDOMAIN.COM"
}

If I use

https://graph.microsoft.com/BETA/me

I get more information, but nothing that helps me pin down a unique id on the user's organization.

Is there a different scope I need to use to get information for the user's organization? And if there is not, can I rely on parsing the domain name from the user's email as a unique id for the user's organization? Do I need to query a different API?

Update: the OAuth response

In case it helps, after the user authenticates with AD, I receive the following response:

{
    access_token: "eyJ0eXAiOiJKV1QiLCJub25jZSI6IkFRQUJBQUFBQUFEWDhHQ2k2SnM2U0s4MlRzRDJQYjdyN1VLTzdJSDJSLWpTcmpScU9..."
    expires_at: Fri May 18 2018 07: 18: 42 GMT - 0400(Eastern Daylight Time) {}
    expires_in: "3599"
    provider: "Microsoft"
    scope: "https://graph.microsoft.com/User.Read"
    session_state: "012f4565-31bb-..."
    state: "259309..."
    token_type: "Bearer"
}

Update: The full AD response using https://graph.microsoft.com/BETA/me

{
    @odata.context: "https://graph.microsoft.com/beta/$metadata#users/$entity",
        accountEnabled: true,
        ageGroup: null,
        assignedLicenses: [],
        assignedPlans: [],
        businessPhones: [],
        city: null,
        companyName: null,
        consentProvidedForMinor: null,
        country: null,
        deletedDateTime: null,
        department: null,
        deviceKeys: [],
        displayName: "FirstName LastName",
        employeeId: null,
        givenName: "FirstName",
        id: "ebdcf715-43c5-4f48-ad0d-b798a3330849",
        imAddresses: [],
        jobTitle: null,
        legalAgeGroupClassification: null,
        mail: "FirstName.LastName@COMPANYDOMAIN.COM",
        mailNickname: "FirstName.LastName",
        mobilePhone: null,
        officeLocation: null,
        onPremisesDomainName: "COMPANYDOMAIN.COM",
        onPremisesExtensionAttributes: {
            …
        },
        onPremisesImmutableId: "...RVWAty...",
        onPremisesLastSyncDateTime: "2018-05-10T18:13:45Z",
        onPremisesProvisioningErrors: [],
        onPremisesSamAccountName: "FILastName",
        onPremisesSecurityIdentifier: "...-21-1412366426-...",
        onPremisesSyncEnabled: true,
        onPremisesUserPrincipalName: "FILastName@COMPANYDOMAIN.COM",
        passwordPolicies: "DisablePasswordExpiration",
        passwordProfile: null,
        postalCode: null,
        preferredDataLocation: null,
        preferredLanguage: null,
        provisionedPlans: [],
        proxyAddresses: [],
        refreshTokensValidFromDateTime: "2018-05-10T17:54:45Z",
        showInAddressList: null,
        state: null,
        streetAddress: null,
        surname: "LastName",
        usageLocation: "US",
        userPrincipalName: "FILastName@COMPANYDOMAIN.COM",
        userType: "Member"
}

Update: Decoding access_token with jwt.ms

{
  "typ": "",
  "nonce": "",
  "alg": "",
  "x5t": "",
  "kid": "iBjL1Rcqzhiy4fpxIxdZqohM2Yk"
}.{
  "aud": "",
  "iss": "",
  "iat": "",
  "nbf": "",
  "exp": "",
  "acr": "",
  "aio": "",
  "amr": [
    "pwd"
  ],
  "app_displayname": "",
  "appid": "",
  "appidacr": "",
  "family_name": "",
  "given_name": "",
  "ipaddr": "",
  "name": "",
  "oid": "",
  "onprem_sid": "",
  "platf": "",
  "puid": "",
  "scp": "",
  "sub": "",
  "tid": "",
  "unique_name": "",
  "upn": "",
  "uti": "",
  "ver": "1.0"
}.[Signature]

Solution

  • If nothing else works, you can decode the access token and get the tid claim. That is the id for the Azure AD tenant.

    You can find the documentation for the claims in tokens from here: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-token-and-claims

    For example, here is what it says for tid:

    An immutable, non-reusable identifier that identifies the directory tenant that issued the token. You can use this value to access tenant-specific directory resources in a multi-tenant application. For example, you can use this value to identify the tenant in a call to the Graph API.