Outbound REST web service call using oAuth
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-27-2017 10:52 AM
Hi community,
I need to create a ticket in Salesforce using REST which works fine. The problem is around the authentication method which is oAuth.
Here's the scenario that works:
1. Navigate to System Web Services -> Outbound -> REST Message
2. Select POST from HTTP Methods
3. Select UI Action "Get OAuth Token"
4. Enter username and password provider from 3rd party vendor (this gives me an access token)
OAuth Access token is available but will expire soon at 2017-06-27 14:16:43. Verify the OAuth configuration and click the 'Get OAuth Token' link below to request a new token.
5. From a Purchase Order, the following BR creates a ticket in Salesforce on PO creation:
When to run: ASYNC
(function executeRule(current, previous /*null when async*/) {
//First we need to retrieve RITM information to pass to 3rd party vendor
var req = new GlideRecord('sc_request');
if (req.get(current.init_request)) {
var ritm = new GlideRecord('sc_req_item');
ritm.addQuery('request', req.sys_id);
ritm.query();
if (ritm.next()) {
//retrieve the variables of the ritm
var store = ritm.u_requested_for.getDisplayValue();
var qty = ritm.quantity;
var emp = ritm.u_employee_name;
var oAuthClient = new sn_auth.GlideOAuthClient();
var params = {
grant_type:"password",
username:'xxxxxxxxxxxxxxxxxxxxxxx',
password:'xxxxxxxxxxxxxxxxxxxxxxxx'
};
//var json = new global.JSON();
var text = JSON.stringify(params);
var tokenResponse = oAuthClient.requestToken('3rd party vendor', text);
var token = tokenResponse.getToken();
var accessToken = token.getAccessToken();
var r = new sn_ws.RESTMessageV2('3rd party vendor', 'post');
r.setRequestHeader('Content-Type','application/json');
r.setRequestHeader('Authorization', 'Bearer ' + accessToken);
var aRequest = {
SiteId: "a08P0000002vylpIAA",
PO: 'Test from ServiceNow QA instance',
'Comment': "Created from SN QA for store: " + store + " quantity of " + qty,
OrderItems: [
{
'ItemId': "a1LP0000000mSmL",
Quantity: 2
},
{
'ItemId': "a1LP0000000mSmL",
Quantity: 2
}
]
};
r.setRequestBody(JSON.stringify(aRequest));
r.setStringParameter("short_description", current.short_description);
r.setAuthentication('oauth2', 'AirLiquide');
var response = r.execute();
var responseBody = response.getBody();
var httpStatus = response.getStatusCode();
var responseObj = JSON.parse(responseBody);
//Create entry in External Ticket Match table
createTicketMatchEntry(responseObj.toString(), current.number);
//Update the external reference number
current.u_external_number = responseObj.toString();
current.update();
}
}
function createTicketMatchEntry(externalNum, num) {
var ext = new GlideRecord('u_integration_ticket_match');
ext.initialize();
ext.u_external_vendor = '3rd party vendor';
ext.u_external_number = externalNum;
ext.u_servicenow_ticket_number = num;
ext.u_servicenow_application = 'Purchase Order';
ext.insert();
}
})(current, previous);
Here's the scenario that DOESN'T work:
Skip steps from 1 to 4, which is to get the access token from the REST message and retrieve it using the BR only fails.
So basically, if I do not do steps 1 to 4, I am unable to authenticate to salesforce eventhough I am retrieving a valid access token using my BR.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-27-2017 11:09 AM
Hi Maxime,
What error you are getting in log. Try adding log statements in your business rule.
When OAuth is used for REST then following steps you need to use:
1) Get the Access Token in first step URL for getting the access token should be provided by Salesforce
2) Use this access token obtained in step 1 and pass this in Header as Bearer ${accessToken} to the actual API call.
Mark Correct if this solves your issue and also hit Like and Helpful if you find my response worthy based on the impact.
Thanks
Ankur
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-27-2017 11:16 AM
Hi Ankur,
thanks for the quick response. I removed the logs from the post because they had client information. Here's the error message I get when I skip steps 1 to 4:
com.glide.communications.ProcessingException: User Not Authenticated. OAuth token has expired or has not been retrieved.
Caused by error in sys_trigger.ac11d3e6dbe73a0007dd30cf9d9619d7 at line -1
Please note that I do retrieve the access token from salesforce which I pass to:
r.setRequestHeader('Authorization', 'Bearer ' + accessToken);
but it doesn;t work. Here's actual data if I run the following code:
var oAuthClient = new sn_auth.GlideOAuthClient();
var params = {grant_type:"password", username:'dollarama.orders@airliquide.com', password:'Dollar!42457+Tes57210934ahzJhnAYbUJEhwo0nS0K4sTqZ'};
var json = new global.JSON();
var text = json.encode(params);
var tokenResponse = oAuthClient.requestToken('AirLiquide', text);
var token = tokenResponse.getToken();
var accessToken = token.getAccessToken();
gs.print("AccessToken:" + accessToken);
gs.print("AccessTokenExpiresIn:" + token.getExpiresIn());
gs.print(" RefreshToken:" + token.getRefreshToken());
*** Script: AccessToken:00DP00000002r7t!AQ4AQLAtW1WJCKbXlRECz2XD8sPhHJZimVPDHZe1fO66cBbtyDhdp.QE7xDvHlKHljJKPDTanPGz1VMNq1k.nlpiQyzVI8xa
*** Script: AccessTokenExpiresIn:0
*** Script: RefreshToken:null
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-27-2017 11:23 AM
Hi Maxime,
That's fine.
Can you try consuming this API using Postman tool.
First try getting the access token in Postman and consume the actual API using this accesstoken.
Also I can see you are not sending client_id and client_secret in the first step to get access token and these parameters are required.
http://wiki.servicenow.com/index.php?title=Generating_OAuth_Tokens#gsc.tab=0
Also in your logs I could see that the AccessTokenExpiresIn has value as 0 seconds. Does that mean the accessToken cannot be used as soon as it was obtained.
May be that can be an issue since AccessToken they are generating is expiring soon before you do actual api call using this accessToken in Authorization header.
Can you check with their team on this why you are getting that 0 seconds. Are they trying
Mark Correct if this solves your issue and also hit Like and Helpful if you find my response worthy based on the impact.
Thanks
Ankur
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-27-2017 12:51 PM
Hi again,
it works fine in Postman. I am not sure I need to send the client_id and client_secret since I am using:
r.setAuthentication('oauth2', '3rd party vendor');
Maybe I am wrong, since it is afterall not working...
I don't believe AccessTokenExpiresIn is an issue either because it works when I execute steps 1 to 4.