In this article, I would like to explain and share the NodeJS code to get all the users from O365 using Graph API and we will see how to validate the Graph API user results with the O365 Admin Portal.
What is Microsoft Graph API?
It is a developer platform API that is used to get the data from O365 Azure, Outlook, SharePoint, Intune, Skype, OneDrive etc. It gives you a single REST API endpoint to interact with the Office 365.
From Microsoft documentation:
“Microsoft Graph is the gateway to data and intelligence in Microsoft 365. Microsoft Graph provides a unified programmability model that you can use to take advantage of the tremendous amount of data in Office 365, Enterprise Mobility + Security, and Windows 10.
You can use the Microsoft Graph API to build apps for organizations and consumers that interact with the data of millions of users. With Microsoft Graph, you can connect to a wealth of resources, relationships, and intelligence, all through a single endpoint: https://graph.microsoft.com”
Reference URL - https://developer.microsoft.com/en-us/graph/docs/concepts/overview
Steps to use O365 to get all the users in an organization
Follow the below-listed steps and code,
End Point for user’s API - https://graph.microsoft.com/V1.0/users
Graph Token URL - https://login.microsoftonline.com/{tenantID}/oauth2/v2.0/token
Graph Token body - client_id=" + configValues.clientId + "&scope=" + configValues.scope + "&client_secret=" + configValues.clientSecretId + "&grant_type=client_credentials
Step 1
Register the app in Azure AD using that client ID, Tenant ID, and secret key.
Follow the below URL to Register the app in Azure.
Make sure to check that your registered Azure app has permission to read the directory data.
Step 2
In your node js solution just create the config file and provide the below values. We have created the config file to avoid the hard-coded things. Provide your tenantId , clientId and secret key don't use the below mentioned one , it is just sample (it won't work)
- {
- "scope": "https%3A%2F%2Fgraph.microsoft.com%2F.default",
- "tenantId": "7aa111ae-1ab6-4256-af4c-a0c1cdb4575d",
- "clientId": "bff7fae8-c253-37e5-9b6a-e096bed54f11",
- "clientSecretId": "XgfrmWfX0K/N7SRouCdAskTKrz0cnKN2rS12IkJ9SJk="
- }
Step 3
Refer to that config file in your js file, as shown below,
- var request = require('sync-request');
- var fs = require('fs');
- var configValues = JSON.parse(fs.readFileSync('UsersConfig.json'));
Step 4
Then frame the Graph token URL and Graph token body to get the auth token,
- var graphAccessUrl = "https://login.microsoftonline.com/" + configValues.tenantId + "/oauth2/v2.0/token";
- var graphTokenBody = "client_id=" + configValues.clientId + "&scope=" + configValues.scope + "&client_secret=" + configValues.clientSecretId + "&grant_type=client_credentials";
Step 4
Get the Authorized token using the below method,
- var contentType = "application/x-www-form-urlencoded; charset=utf-8";
- var graphTokenError = "Failed to get graph token";
- var graphToken = "";
-
- getToken(graphAccessUrl, contentType, graphTokenBody, graphTokenError);
-
- function getToken(url, type, content, errorMessage, callback) {
- var options = {
- 'headers':
- {
- 'Content-Type': type
- },
- 'body': content
- };
-
-
- var tokenResponse = httpPost(url, options);
-
- if (tokenResponse.statusCode === 200) {
- error = errorMessage;
- if (errorMessage === graphTokenError) {
- var token = JSON.parse(tokenResponse.body.toString('utf-8'));
- graphToken = token.access_token;
- }
- if (callback) {
- return callback();
- }
- } else {
- Console.log(errorMessage);
- }
- }
Step 5
Once you received the token then do the http call using the EndPoint and get the results,
Note
In a single API call, we are able to get only 100 users so pass the top ten API endpoints to get up to 1000 users. If you have more than 1000 users, we can use the next link to get another 1000 users.
https://graph.microsoft.com/V1.0/users?$top=999
Nextlink is like pagination - On the response, you can pass this string to get the next set of users,
- var nextLink = "@odata.nextLink";
- reqUrl = https:
-
- function getUsers(reqUrl) {
- try {
- var userList = [];
- console.log(MESSAGE + "Inside get users data method!!!");
-
- while(reqUrl)
- {
- var usersResponse = httpGet(reqUrl, graphToken);
- if (usersResponse.statusCode == 200) {
- failIndex = 0;
- var responseBlob = JSON.parse(usersResponse.body.toString('utf-8'));
- var parsedJsonres = responseBlob.value;
- userList = parsedJsonres;
-
- for (var i = 0; i < parsedJsonres.length; i++) {
- var currItem = parsedJsonres[i];
- if (currItem) {
- bindUsers(currItem);
- }
- }
-
- if (responseBlob[nextLink]) {
- reqUrl=responseBlob[nextLink];
- continue;
- }
- else {
- console.log(MESSAGE + "There is no next page..")
- break;
- }
- }
- else {
- if (usersResponse.statusCode === 401 && JSON.parse(usersResponse.body.toString('utf-8'))["error"]["message"] === "Access token has expired.") {
- getToken(graphAccessUrl, contentType, graphTokenBody, graphTokenError);
- userList = userDetails.concat(getUsers(responseBlob[nextLink]));
- }
- else {
- failIndex++;
- if (failIndex == retryCount) {
- console.log(errorMessage + "User API Call has been failed..");
- failIndex = 0;
- }
- else
- userList = userDetails.concat(getUsers(responseBlob[nextLink]));
- }
- }
- }
-
- }
- catch (ex) {
- console.log(EXCEPTION_MESSAGE + ex);
- }
- return userList;
- }
-
- function httpGet(url, bearerToken) {
- var request = require('sync-request');
- var res = request('GET', url,
- {
- 'headers': {
- 'Authorization': 'Bearer ' + bearerToken,
- 'Accept': "application/json"
- }
- }
- );
- return res;
- }
Step 6
Then, bind the results based on your requirement. You will receive the below object when you call the user's API.
Version 1.0
Beta API - Available columns
- {
- "id": "24144c99-354b-4190-8d62-8ba7d2671939",
- "deletedDateTime": null,
- "accountEnabled": true,
- "ageGroup": null,
- "businessPhones": [],
- "city": null,
- "createdDateTime": "2018-09-06T08:22:28Z",
- "companyName": null,
- "consentProvidedForMinor": null,
- "country": null,
- "department": null,
- "displayName": "Test 10",
- "employeeId": null,
- "faxNumber": null,
- "givenName": "Test",
- "imAddresses": [
- "10@apptiodemo.onmicrosoft.com"
- ],
- "isResourceAccount": null,
- "jobTitle": null,
- "legalAgeGroupClassification": null,
- "mail": "10@apptiodemo.onmicrosoft.com",
- "mailNickname": "10",
- "mobilePhone": null,
- "onPremisesDistinguishedName": null,
- "officeLocation": null,
- "onPremisesDomainName": null,
- "onPremisesImmutableId": null,
- "onPremisesLastSyncDateTime": null,
- "onPremisesSecurityIdentifier": null,
- "onPremisesSamAccountName": null,
- "onPremisesSyncEnabled": null,
- "onPremisesUserPrincipalName": null,
- "otherMails": [],
- "passwordPolicies": "None",
- "passwordProfile": null,
- "postalCode": null,
- "preferredDataLocation": null,
- "preferredLanguage": null,
- "proxyAddresses": [
- "SMTP:10@apptiodemo.onmicrosoft.com"
- ],
- "refreshTokensValidFromDateTime": "2018-09-06T08:22:28Z",
- "showInAddressList": null,
- "state": null,
- "streetAddress": null,
- "surname": "10",
- "usageLocation": "US",
- "userPrincipalName": "10@apptiodemo.onmicrosoft.com",
- "externalUserState": null,
- "externalUserStateChangeDateTime": null,
- "userType": "Member",
- "assignedLicenses": [
- {
- "disabledPlans": [],
- "skuId": "6fd2c87f-b296-42f0-b197-1e91e994b900"
- }
- ],
- "assignedPlans": [
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "exchange",
- "servicePlanId": "efb87545-963c-4e0d-99df-69c6916d9eb0"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "SharePoint",
- "servicePlanId": "5dbe027f-2339-4123-9542-606e4d348a72"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "SharePoint",
- "servicePlanId": "e95bec33-7c88-4a70-8e19-b10bd9d0c014"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "MicrosoftCommunicationsOnline",
- "servicePlanId": "0feaeb32-d00e-4d66-bd5a-43b5b83db82c"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "MicrosoftOffice",
- "servicePlanId": "43de0ff5-c92c-492b-9116-175376d08c38"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "RMSOnline",
- "servicePlanId": "bea4c11e-220a-4e6d-8eb8-8ea15d019f90"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "YammerEnterprise",
- "servicePlanId": "7547a3fe-08ee-4ccb-b430-5077c5041653"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "Sway",
- "servicePlanId": "a23b959c-7ce8-4e57-9140-b90eb88a9e97"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "ProjectWorkManagement",
- "servicePlanId": "b737dad2-2f6c-4c65-90e3-ca563267e8b9"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "TeamspaceAPI",
- "servicePlanId": "57ff2da0-773e-42df-b2af-ffb7a2317929"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "PowerAppsService",
- "servicePlanId": "c68f8d98-5534-41c8-bf36-22fa496fa792"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "ProcessSimple",
- "servicePlanId": "76846ad7-7776-4c40-a281-a386362dd1b9"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "Deskless",
- "servicePlanId": "8c7d2df8-86f0-4902-b2ed-a0458298f3b3"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "MicrosoftStream",
- "servicePlanId": "9e700747-8b1d-45e5-ab8d-ef187ceec156"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "OfficeForms",
- "servicePlanId": "2789c901-c14e-48ab-a76a-be334d9d793a"
- },
- {
- "assignedDateTime": "2018-09-06T08:22:28Z",
- "capabilityStatus": "Deleted",
- "service": "To-Do",
- "servicePlanId": "c87f142c-d1e9-4363-8630-aaea9c4d9ae5"
- }
- ],
- "deviceKeys": [],
- "onPremisesExtensionAttributes": {
- "extensionAttribute1": null,
- "extensionAttribute2": null,
- "extensionAttribute3": null,
- "extensionAttribute4": null,
- "extensionAttribute5": null,
- "extensionAttribute6": null,
- "extensionAttribute7": null,
- "extensionAttribute8": null,
- "extensionAttribute9": null,
- "extensionAttribute10": null,
- "extensionAttribute11": null,
- "extensionAttribute12": null,
- "extensionAttribute13": null,
- "extensionAttribute14": null,
- "extensionAttribute15": null
- },
- "onPremisesProvisioningErrors": [],
- "provisionedPlans": [
- {
- "capabilityStatus": "Enabled",
- "provisioningStatus": "Success",
- "service": "MicrosoftCommunicationsOnline"
- },
- {
- "capabilityStatus": "Enabled",
- "provisioningStatus": "Success",
- "service": "exchange"
- },
- {
- "capabilityStatus": "Enabled",
- "provisioningStatus": "Success",
- "service": "SharePoint"
- },
- {
- "capabilityStatus": "Enabled",
- "provisioningStatus": "Success",
- "service": "SharePoint"
- }
- ]
- }
How to verify the results in O365?
Once you get the results, you can verify the results from O365 and also, follow the below listed steps to verify the output.
Step 1
Log into Microsoft 365 Admin Center. Learn more here.
https://admin.microsoft.com/AdminPortal
Step 2
From Microsoft 365 Admin Center, click Users option and then Active Users option.
Step 3
From Active Users, click any one user’s display name and validate the email address.
Step 4
Then scroll down the page and select the contact information
Step 5
From Edit Contact Information, verify the following fields First Name, Last Name, Location, Department.
And also, you can export the users and validate the details.
Step 6
From Active users, click Export option (select all users and click on export button, and you will get the Excel sheet with all the O365 Users)
Summary
In this article, we have explored how to get the information of all the users from O365 organization using Graph API. Happy learning.