- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-18-2025 02:59 PM
Hi there, I'm having a bit of trouble dynamically retrieving AD groups in a catalog item variable through the Microsoft Entra ID Spoke OAuth. As part of the solution for the business, we want to perform this function through a Script Include.
Currently the error we see in the logs is: API response: null. Afterwards we can see it attempts to make a HTTPRequest: Starting _makeHttpRequest function and then stops.
Here is the Script Include (with sensitive information taken out):
var AzureADIntegration = Class.create();
AzureADIntegration.prototype = Object.extendsObject(AbstractAjaxProcessor, {
// Function to retrieve groups from Azure AD
getAzureADGroups: function() {
gs.info('Starting getAzureADGroups function');
// Retrieve the token from the Application Registry
var token = this._getTokenFromRegistry();
gs.info('Using token from Application Registry: ' + token);
// Make the API call to Azure AD to fetch groups
var url = 'https://graph.microsoft.com/v1.0/groups';
var headers = {
'Authorization': 'Bearer ' + token
};
gs.info('Making API call to Azure AD to fetch groups');
var response = this._makeHttpRequest(url, 'GET', headers);
gs.info('API response: ' + response);
return response;
},
// Function to make an HTTP request
_makeHttpRequest: function(url, method, headers) {
gs.info('Starting _makeHttpRequest function');
var request = new GlideHTTPClient();
var response = request.send(url, method, '', headers);
gs.info('HTTP request sent. Status code: ' + response.getStatusCode());
if (response.getStatusCode() == 200) {
gs.info('Request successful. Response body: ' + response.getBody());
return response.getBody();
} else {
gs.error('Request failed. Status code: ' + response.getStatusCode());
return null;
}
},
// Function to get token from Application Registry
_getTokenFromRegistry: function() {
gs.info('Starting _getTokenFromRegistry function');
var gr = new GlideRecord('oauth_credential');
gr.addQuery('name', 'Your Application Registry Name'); // Replace with your Application Registry name
gr.query();
if (gr.next()) {
gs.info('Token found in Application Registry');
return gr.token_received;
}
gs.error('No token found in Application Registry');
return null;
},
type: 'AzureADIntegration'
});
Here is the catalog Client Script (with sensitive information taken out):
function onLoad() {
// Define the function to get Azure AD Groups
var ga = new GlideAjax('AzureADIntegration'); // Name of the Script Include AzureADIntegration
ga.addParam('sysparm_name', 'getAzureADGroups'); // The function to call in Script Include
ga.getXMLAnswer(function(response) {
var result = response.responseXML.documentElement.getAttribute("answer");
// Log the raw result for debugging
console.log('Response from GlideAjax:', result);
if (result) {
try {
var groups = JSON.parse(result); // Assuming response is in JSON format
// Log the groups array for debugging
console.log('Parsed groups:', groups);
// Assuming we want to populate the dropdown with group names
var dropdown = g_form.getControl('azure_ad_groups'); // Get the dropdown element by variable name
dropdown.options.length = 0; // Clear any existing options
// Add a default option
var defaultOption = new Option('Select an Azure AD group', '');
dropdown.add(defaultOption);
// Populate the dropdown with the group names
groups.value.forEach(function(group) {
var option = new Option(group.displayName); // Add group name
dropdown.add(option);
});
} catch (error) {
console.error('Error parsing Azure AD groups:', error);
// Handle parsing errors
var dropdown = g_form.getControl('azure_ad_groups');
dropdown.options.length = 0;
var errorOption = new Option('Error loading groups', '');
dropdown.add(errorOption);
}
} else {
// Handle the case where no result was returned
console.warn('No result received from GlideAjax call');
var dropdown = g_form.getControl('azure_ad_groups');
dropdown.options.length = 0;
}
});
}
I'm very new to all this, so any gentle and detailed advice would be greatly appreciated.
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-20-2025 09:41 PM
A solution has been found. Just in case anyone faces the same issues I did, here's the coding solution:
Script Include: (Replace all "<...>" with actual values)
var <SCRIPT INCLUDE> = Class.create();
<SCRIPT NCLUDE>.prototype = Object.extendsObject(AbstractAjaxProcessor, {
// Function to retrieve groups from Azure AD
getADGroups: function() {
gs.info('Starting getADGroups function');
// Retrieve the token from the Application Registry
var token = this._getTokenFromRegistry();
if (!token) {
gs.error('Failed to retrieve token from Application Registry');
return null;
}
gs.info('Using token from Application Registry');
// Make the API call to Azure AD to fetch groups
try {
var r = new sn_ws.RESTMessageV2('<REST MESSAGE NAME>', 'Default GET');
var response = r.execute();
var responseBody = response.getBody();
var httpStatus = response.getStatusCode();
gs.info('API response received with status code: ' + httpStatus);
gs.info('Raw response body: ' + responseBody); // Log the raw response
// Directly parse the response body to get group names
var groupNames = JSON.parse(responseBody).value.map(function(group) {
return group.displayName;
});
// Log the group names
gs.info('Group names: ' + JSON.stringify(groupNames));
// Return the array of group names as a JSON string
return JSON.stringify(groupNames); // This ensures it's properly escaped for JSON
} catch (ex) {
var message = ex.message;
gs.error('API call failed: ' + message);
return 'API call failed: ' + message;
}
},
// Function to get OAuth2 token
_getOAuthToken: function(url, client_id, client_secret) {
gs.info('Starting _getOAuthToken function');
var requestBody = 'client_id=' + client_id + '&client_secret=' + client_secret + '<OAUTH 2.0 CLIENT CREDENTIALS GRANT FLOW>';
var request = new GlideHTTPRequest(url);
request.setRequestBody(requestBody);
request.setMethod('POST');
var response = request.execute();
gs.info('Token request sent. Status code: ' + response.getStatusCode());
if (response.getStatusCode() == 200) {
gs.info('Token request successful. Response body: ' + response.getBody());
return response.getBody();
}
gs.error('Token request failed. Status code: ' + response.getStatusCode());
return null;
},
// Function to get token from Application Registry
_getTokenFromRegistry: function() {
gs.info('Starting _getTokenFromRegistry function');
var gr = new GlideRecord('oauth_credential');
gr.addQuery('sys_id', '<YOUR APPLICATION REGISTRY ID>'); // Replace with your Application Registry name
gr.query();
if (gr.next()) {
gs.info('Token found in Application Registry');
return gr.token_received;
}
gs.error('No token found in Application Registry');
return null; // Added return statement to handle case where no record is found
},
type: '<SCRIPT INCLUDE>'
});
And the Catalog Client Script:
function onLoad() {
// Define the function to get Azure AD Groups
var ga = new GlideAjax('<SCRIPT INCLUDE>'); // Name of the Script Include
ga.addParam('sysparm_name', 'getAzureAD'); // The function to call in Script Include
ga.getXML(triggerCallBack);
function triggerCallBack(response) {
var result = response.responseXML.documentElement.getAttribute("answer");
alert('Result from GlideAjax: ' + result); // Log the raw result for debugging
console.log('Result from GlideAjax:', result);
if (result) {
try {
var responseBody = JSON.parse(result); // Parse the JSON response from the Script Include
if (responseBody.length > 0) {
// If we have groups, populate them into the dropdown
for (var i = 0; i < responseBody.length; i++) {
g_form.addOption("<CATALOG VARIABLE>", responseBody[i], responseBody[i], i);
}
} else {
g_form.addOption("<CATALOG VARIABLE>", "Error", "No groups found");
alert('No groups found');
}
} catch (e) {
alert('Error parsing JSON: ' + e.message); // Catch parsing errors
console.error('Error parsing JSON:', e);
}
} else {
g_form.addOption("<CATALOG VARIABLE>", "Error", "Could not populate groups");
alert('No groups found or returned from GlideAjax call.');
console.error('No groups found or returned from GlideAjax call.');
}
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-18-2025 08:11 PM
Hello @JayAdmin_16
In the getTokenFromRegistry - you have used token_received - is it a valid field in Oauth application registry ? Have you removed some lines here ?
Have you added logs in this and checked where is the script actually breaking ?
Kindly mark my answer as helpful and accept solution if it helped you in anyway,
Regards,
Shivalika
My LinkedIn - https://www.linkedin.com/in/shivalika-gupta-540346194
My youtube - https://youtube.com/playlist?list=PLsHuNzTdkE5Cn4PyS7HdV0Vg8JsfdgQlA&si=0WynLcOwN
eEISQCY
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-20-2025 09:41 PM
A solution has been found. Just in case anyone faces the same issues I did, here's the coding solution:
Script Include: (Replace all "<...>" with actual values)
var <SCRIPT INCLUDE> = Class.create();
<SCRIPT NCLUDE>.prototype = Object.extendsObject(AbstractAjaxProcessor, {
// Function to retrieve groups from Azure AD
getADGroups: function() {
gs.info('Starting getADGroups function');
// Retrieve the token from the Application Registry
var token = this._getTokenFromRegistry();
if (!token) {
gs.error('Failed to retrieve token from Application Registry');
return null;
}
gs.info('Using token from Application Registry');
// Make the API call to Azure AD to fetch groups
try {
var r = new sn_ws.RESTMessageV2('<REST MESSAGE NAME>', 'Default GET');
var response = r.execute();
var responseBody = response.getBody();
var httpStatus = response.getStatusCode();
gs.info('API response received with status code: ' + httpStatus);
gs.info('Raw response body: ' + responseBody); // Log the raw response
// Directly parse the response body to get group names
var groupNames = JSON.parse(responseBody).value.map(function(group) {
return group.displayName;
});
// Log the group names
gs.info('Group names: ' + JSON.stringify(groupNames));
// Return the array of group names as a JSON string
return JSON.stringify(groupNames); // This ensures it's properly escaped for JSON
} catch (ex) {
var message = ex.message;
gs.error('API call failed: ' + message);
return 'API call failed: ' + message;
}
},
// Function to get OAuth2 token
_getOAuthToken: function(url, client_id, client_secret) {
gs.info('Starting _getOAuthToken function');
var requestBody = 'client_id=' + client_id + '&client_secret=' + client_secret + '<OAUTH 2.0 CLIENT CREDENTIALS GRANT FLOW>';
var request = new GlideHTTPRequest(url);
request.setRequestBody(requestBody);
request.setMethod('POST');
var response = request.execute();
gs.info('Token request sent. Status code: ' + response.getStatusCode());
if (response.getStatusCode() == 200) {
gs.info('Token request successful. Response body: ' + response.getBody());
return response.getBody();
}
gs.error('Token request failed. Status code: ' + response.getStatusCode());
return null;
},
// Function to get token from Application Registry
_getTokenFromRegistry: function() {
gs.info('Starting _getTokenFromRegistry function');
var gr = new GlideRecord('oauth_credential');
gr.addQuery('sys_id', '<YOUR APPLICATION REGISTRY ID>'); // Replace with your Application Registry name
gr.query();
if (gr.next()) {
gs.info('Token found in Application Registry');
return gr.token_received;
}
gs.error('No token found in Application Registry');
return null; // Added return statement to handle case where no record is found
},
type: '<SCRIPT INCLUDE>'
});
And the Catalog Client Script:
function onLoad() {
// Define the function to get Azure AD Groups
var ga = new GlideAjax('<SCRIPT INCLUDE>'); // Name of the Script Include
ga.addParam('sysparm_name', 'getAzureAD'); // The function to call in Script Include
ga.getXML(triggerCallBack);
function triggerCallBack(response) {
var result = response.responseXML.documentElement.getAttribute("answer");
alert('Result from GlideAjax: ' + result); // Log the raw result for debugging
console.log('Result from GlideAjax:', result);
if (result) {
try {
var responseBody = JSON.parse(result); // Parse the JSON response from the Script Include
if (responseBody.length > 0) {
// If we have groups, populate them into the dropdown
for (var i = 0; i < responseBody.length; i++) {
g_form.addOption("<CATALOG VARIABLE>", responseBody[i], responseBody[i], i);
}
} else {
g_form.addOption("<CATALOG VARIABLE>", "Error", "No groups found");
alert('No groups found');
}
} catch (e) {
alert('Error parsing JSON: ' + e.message); // Catch parsing errors
console.error('Error parsing JSON:', e);
}
} else {
g_form.addOption("<CATALOG VARIABLE>", "Error", "Could not populate groups");
alert('No groups found or returned from GlideAjax call.');
console.error('No groups found or returned from GlideAjax call.');
}
}
}