
- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 09-13-2022 11:04 PM
Out of the Box ServiceNow offers us limited option of "Basic" authentication option to authenticate and send out Outbound Requests to Third Party Applications using the SOAP protocol.
Nowadays the most common authentication and reliable method used to authenticate a web service is OAuth 2.0, and most customers has a requirement to use OAuth 2.0 authentication for SOAP based communications between the platforms.
Recently I have come across such requirement and have solved the issue by using a server scripted Approach.
Solution Overview : Used the SOAPMessageV2() function to trigger the SOAP function and since the TPA was accepting a bearer token in the Request Header was able to pass the OAuth Token via script.
Used the OOB Oauth Token Registry configuration and used the Oauth entity profile to generate the Access token using the GlideOauthClient()
try {
var s = new sn_ws.SOAPMessageV2('APINAME', 'FUNCTION NAME');
//Generating O Auth access token via script - OAuth Registry definition//
var oAuthClient = new sn_auth.GlideOAuthClient();
var requestor_context = 'test';
var requestor_id = 'abc@xyz.com';
var oauth_profile_id = 'SYS_ID'; // profile ID [sys_id of 'OAuth Entity Profiles' (oauth_entity_profile) record in OAUTH registry record]
var params = {
grant_type: "client_credentials",
username: 'ClientID',
password: 'ClientSecret',
oauth_requestor_context: requestor_context,
oauth_requestor: requestor_id,
oauth_provider_profile: oauth_profile_id
};
var json = new global.JSON();
var text = json.encode(params);
var tokenResponse = oAuthClient.requestToken('oAuth Test', text); //'oAuth Test' is the name of the OAuth application registry record (oauth_entity)
var token = tokenResponse.getToken();
var access_token = token.getAccessToken();
var token = "Bearer "+ access_token.toString();
s.setRequestHeader("Authorization", token); // Using the token information //
var response = s.execute();
var responseBody = response.getBody();
var status = response.getStatusCode();
} catch (ex) {
var message = ex.message;
}
- 4,022 Views
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Nice article.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Rohit, thanks for this article, please could you expand on this so I may understand the wider picture.
- Where does the Client ID/Client Secret come from ? reading about this seems that it needs to be setup by the Admin who you are trying to connect too. In my case I need my old SOAP function to connect to Exchange Web Services. From reading article KB0816072 it seems the MS Azure Administrator have to setup this for you and supply?
- Also where do you apply the script, currently we have Soap Function/message using Basic Authentication but MS have stopped this protocol. Would we have to write a new Scripted Soap Service, as given in your example ?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Rohit,
Nice article, it is really helpful.
I was able to do the same using the resource owner password credentials grant workflow as mentioned below.
var requestBody;
var response;
var responseBody;
var status;
//var sys_id ='sys_id_of_incident;
try {
var s = new sn_ws.SOAPMessageV2('Incident','get'); //(SOAP messgage name, SOAP function name)
//Generating O Auth access token via script - OAuth Registry definition//
var oAuthClient = new GlideOAuthClient();
var params ={grant_type:"password", username:"test", password:'password123'}; //source instance username and password with user having roles "SOAP" and "ITIL".
var json =new JSON();
var text = json.encode(params);
var tokenResponse = oAuthClient.requestToken('Target SOAP', text); //Target instance Oauth Entity name
var token = tokenResponse.getToken();
var access_token = token.getAccessToken();
var token = "Bearer "+ access_token.toString();
s.setRequestHeader("Authorization", token); // Using the token information //
//s.setRequestHeader("Content-Type", "text/xml");
//s.setStringParameterNoEscape('sys_id', sys_id);
s.setRequestBody('<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:inc="http://www.service-now.com/incident"><soapenv:Header/><soapenv:Body><inc:get><sys_id>{enter_incident_sysid_here}</sys_id></inc:get></soapenv:Body></soapenv:Envelope>');
response = s.execute();
responseBody = response.getBody();
status = response.getStatusCode();
requestBody = s.getRequestBody();
var xmldoc = new XMLDocument(responseBody.toString(), true);
var number =xmldoc.getNodeText('//number');
}
catch (ex) {
var message = ex.message;
}
gs.info("Request Body: " + requestBody);
gs.info("Response: " + responseBody);
gs.info("HTTP Status: " + status);
gs.info("Number: " + number);
However, using the client credentials flow as described in your code throws me an error OAuthProblemException{error='server_error', description='access_denied', uri='null', state='null', scope='null', redirectUri='null', responseStatus=0, parameters={}}
Could you please let me know the values which I should fill for the below fields?
oauth_requestor_context
oauth_requestor
oauth_provider_profile
I don't see a method defined in ServiceNow docs using the parameters mentioned in your code.
Also, I cannot see the values in my requestBody when I pass the arguments using the setStringParameter() method. So I have used setRequestBody() method to perform the same actions.
Regards,
Tharun Kumar