Get all the users from multi-tenant AD Application using graph API

Viewed 4326

I'm trying to get all the users for a multi-tenant application using the graph API. For the purpose, I generated the access token using the request:

POST https://login.microsoftonline.com/common/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret=qWgdYAmab0YSkuL1qKv5bPX
&grant_type=client_credentials

Note: Please note that, in above request, I used common in place of {tenantID}. That was just a hit and try as the same was suggested for adminConsent in the doc.

By using the above generated access token, I requested the user API and got the following error

{
    "error": {
        "code": "Authorization_IdentityNotFound",
        "message": "The identity of the calling application could not be established.",
        "innerError": {
            "request-id": "56141b7d-dd5e-44b1-9395-cd15d02b52de",
            "date": "2019-06-17T12:42:19"
        }
    }
}

And when I generate the token using tenant ID, it only returns the users of one active directory.

Can anyone suggest, where I'm going wrong?

4 Answers

Since you are using common endpoint, you can not use client credentials flow(get access without user) here. You need to refer to this document(get access on behalf of a user) .

Note: When you use auth code grant flow(get access on behalf of a user), you need to grant delegated permission instead of application permission.

enter image description here

get access token

enter image description here

In a Multi-tenant Application, Service principal objects are created in each tenant which access the application. These service principal objects will hold the consent (user/admin) objects which are specific to that tenant and the secret is linked to these objects as well.

So when you get a token, it is always tenant-specific and you need to get separate tokens for each tenant to perform any operation in that tenant.

Example: Consider you have a multi-tenant application registered in tenant A and is also being used by tenants B, C and D. This will create SP objects in tenants B, C, and D as well.

So if you need to perform any operation in tenant B, you need a token for the SP B and use the secret linked to it.

In short, you need creds from all the tenants if you want to perform these operations in the context of the application.

I recently had to implement this, was successful in that. These are the steps I had done.

  1. Created a multi-tenant application
  2. Gave Application permissions
  3. Configure the GraphClient with a tenant-specific auth header.

Here is the code to get the tenant-specific graph client.

private ClientCredentialProvider GetGraphAuthProvider(Guid tenantId) {
            IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
                .Create(_configuration["AzureAd:ClientId"])
                .WithTenantId(Convert.ToString(tenantId))
                .WithClientSecret(_configuration["AzureAd:ClientSecret"])
                .Build();
            return new ClientCredentialProvider(confidentialClientApplication);
        }

        public GraphServiceClient GetGraphServiceClient(Guid tenantId) = >new GraphServiceClient(GetGraphAuthProvider(tenantId));
    }
}

I have explained everything in my blog here.

I see that you are trying to get an app-level access token using the "common" and you are not specifying the tenant id anywhere in your request. You could either specify the tenant id in the url: https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token or you could specify it within the request body. In that case, your request should look like this:

POST https://login.microsoftonline.com/common/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id={client Id}
&scope={scopes, in your case ".default"}
&client_secret={client secret}
&tenant_id={organization's tenant id}
&grant_type=client_credentials
Related