Skip to Content
Technical Articles
Author's profile photo d jaiswal

ServiceNow (SNOW) connectivity using Oauth grant_type “password” in SAP Cloud Integration

Introduction:

In a requirement where we need to connect SAP Cloud Integration( SAP CPI) with ServiceNow Instance for creation of case/Incident. We need to call the ServiceNow APIs to authenticate via several authentication mechanism few of them are Basic Authentication(username and password) and Oauth Authentication.

Now, in this blog , I am going to demonstrate how we can use Oauth Connectivity between SAP Cloud Integration (SAP CPI) and ServiceNow using grant_type = “Password”.

While demonstrating the step by step process, we may go through few important technical aspects as below:

  1. Leveraging Security Artifacts–> User Credential type to store Username,Password,Client ID and Client Secret which I have used as a trick to avoid exposure of connectivity details over iflow build steps.
  2. Setting up of Authorization Header body using credentials from above step1 and setting content type “application/x-www-form-urlencoded” through a groovy script.
  3. Use of Authentication bearer token by setting up Auth Token Header using a groovy script which will be used to send data/file attachment to ServiceNow API for incident creation.
  4. Capturing HTTP response body received from ServiceNow incident/case creation using a groovy script.

This sample process can be leveraged by developers to edit, modify and enhanced according to other business requirements as well.

Prerequisites:

You should have CPI tenant access and have understanding on Integration flow development.

You should have ServiceNow OAuth details like Username,Password,ClientID,Client Secret to be configured on CPI tenant.

Design approach: To explain these scenario, I have created sample iflow:

Below Figure1 will show the high level steps performed on the iflow development

Figure 1 : Iflow Steps

 

Step1(Figure1) : Sender System(Participants) : This System name is defined to connect to Sender system SFTP to poll the file.

Step2(Figure1) : Sender SFTP Channel to Poll the files to be sent to ServiceNow API for incident creation. Files to be picked up from Sender SFTP folder path as configured.

Step3(Figure1) : Content Modifier in this usecase used to set properties for below externalized parameters like:

Filename : To get the polled filename

FilePath : Archive folder path for polled files to move.

SYS_ID : for ServiceNow API parameter

SnowCredential : To specify the security artifact name

inputfilepayload : To store input file payload body.

Content%20Modifier%20-%20Externalization%20of%20Parameters

Content Modifier – Externalization of Parameters

 

Here Property SnowCredential  : “testServiceNow2″ is defined on Security artifacts as User Credential type to avoid exposure of password,clientid and client secret to be hardcoded on the Iflow.(this is one of the trick I have used to configure and retrieved on groovy script on next step).

Developers can explore more ways of hiding secure connectivity credentials details and post as blog comments.

 

Security%20Artifacts%20-%20User%20Credential%20Type

Security Artifacts – User Credential Type

 

Step4(Figure1) :Groovy Script : This step is used to retrieve Username, Client_Id, Client_Secret from Deployed Security Artifact ” testServiceNow2″ and prepare an authorization body for Oauth grant_type = “Password” connectivity and this body will be passed on the next step via HTTP channel for authentication request with ServiceNow instance.

On this groovy script message header Content-type is also set to “application/x-www-form-urlencoded” which is required for making successful authentication.

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import com.sap.it.api.ITApiFactory;
import com.sap.it.api.securestore.SecureStoreService;
import com.sap.it.api.securestore.UserCredential;

def Message processData(Message message) {
    


//Credentials // the same user credentials needs to be avaliable in secure material.
//def user = "YOUR_UserCredentials";
def user = message.getProperty("SnowCredential");// externalise to provide different name configured in other instances on transport
message.setHeader("Content-type", "application/x-www-form-urlencoded");

//service to get the credentials
def service = ITApiFactory.getApi(SecureStoreService.class, null);

//get user credential
def userCred = service.getUserCredential(user);
if (userCred == null){
throw new IllegalStateException("No User credential found for alias" + user);
}

String username = userCred.getUsername();
String password = new String(userCred.getPassword());


//store password parameters i.e password client id and client secret delimited with * symbol as mentioned on respective security artifact
String[] entry = password.split("\\*"); 
password = entry[0].trim();// retrive password
client_id = entry[1].trim(); // retrive cleint Id
client_secret = entry[2].trim(); // retrive Client_secret


//HTTP Parameters value
String grant_type = "password"; // Service Now grant type

//Query
def query = "";
query = query + "client_id=" + client_id + "&";
query = query + "client_secret=" + client_secret + "&";
query = query + "grant_type=" + grant_type + "&";
query = query + "username=" + username + "&";
query = query + "password=" + password;

message.setBody(query);


return message;
}

Groovy Script Code Snippet (Prepare Authentication Body and set content-type message header)

 

Step5/Step6/and Step7 (Figure1) : Request Reply/ServiceNow Receiver component/HTTP Channel: These steps are used to call ServiceNow system using HTTP adapter which tries to authenticate with prepared Authentication body and prepared Content-Type on step 4:

HTTP%20Channel%20for%20OAuth%20Authentication%20Request

HTTP Channel for OAuth Authentication Request

Here, Http Address format is “ https://<ServiceNowInstance-Address>/Oauth_token.do

Where, <ServiceNowInstance-Address> = Service now instance connectivity address.

 

Step8(Figure1) :Groovy Script : This step is used to retrieve the the response from ServiceNow and store the Auth bearer token generated and configured as Authorization Header parameter after successful authentication from last step.

ServiceNow session remains open for this authenticated token until timeout. This token authenticate directly for further data transfer(in our case sending incoming file) through ServiceNow API until token session expired at ServiceNow side.

import groovy.json.*;
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
    //Body 
       def body = message.getBody(String.class);
       def jsonSlurper = new JsonSlurper()
       def list = jsonSlurper.parseText(body)
       def token="Bearer "+list.access_token.toString();
       //Headers 
       def map = message.getHeaders();
       message.setHeader("Authorization", token);
      
       return message;
}

Groovy Script Code Snippet (Prepare Authorization Header from generated authentication Token)

Step9(Figure1) : Content Modifier : This step is used to retrieve incoming payload body of the polled file.

Content%20Modifier%20-%20Get%20Incoming%20payload

Content Modifier – Get Incoming payload

 

Step10/Step6/and Step11 (Figure1) : Request Reply/ServiceNow Receiver component/HTTP Channel: These steps are used to call the actual ServiceNow API for incident creation.

It will internally make use of set Token Authorization Header to authenticate and pass the incoming payload/data to ServiceNow system.

Sending%20File%20to%20ServiceNow%20API%20for%20incident/Case%20creation

Sending File to ServiceNow API for incident/Case creation

Here, URL configured is :

https://<ServiceNow-Address>/api/now/attachment/file?table_name={property.SYS_tablename}&table_sys_id=${property.SYS_ID}&file_name=${property.Filename}

Where:{property.SYS_tablename} , ${property.SYS_ID},${property.Filename} are externalized parameter for user inputs screen.

 

Step12/Step13(Figure1) :Groovy Script/end : This step is used to retrieve the the response from ServiceNow final API call and log the HTTP response and end the process.

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;

def Message processData(Message message) 
{
	def body = message.getBody(java.lang.String) as String;
	def messageLog = messageLogFactory.getMessageLog(message);
	if(messageLog != null)
	{
	messageLog.addAttachmentAsString("HTTP Response after attachment upload:", body, "text/plain");
     }
	return message;
}

Conclusion:

In this blog post, I demonstrated how to make use of Oauth grant_type = password based connectivity leveraging below points:

  1. How to retrieve Oauth credential parameters using groovy script from Security artifacts User Credential type and a trick used to maintain password as combination of password, clientId, client_secret delimited with character(in my usecase it’s a “*” star-symbol).
  2. Set Authentication Body and Content- type using script for initial ServiceNow instance authentication.
  3. Creating an Authorization header from Service Now Bearer token retrieved.
  4. Calling the ServiceNow API for transmitting data using Authorization Token header .
  5. Capturing the HTTP response from ServiceNow API call.

Hope this blog post will help CPI developers to achieve similar functionality and this can be enhanced more to meet the technical business requirements.

Assigned Tags

      8 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Madhubala Chandran
      Madhubala Chandran

      Hi Deepak ,

      Good and useful blog . Thanks for this knowledge sharing ..

       

      Author's profile photo Vimal Surendranathan Pillai
      Vimal Surendranathan Pillai

      Excellent blog Deepak.. The explanation has the depth to enable a novice person perform the ServiceNow integration.. Brilliant!!!

      Author's profile photo Vidyadhar Kurmala
      Vidyadhar Kurmala

      Hi Deepak,

      We can implement caching and use refresh_token grant type to get a new token.. However w.r.t this link ROPC is NOT a recommended approach. Best practice is to implement Auth Code grant type and as of today SAP Cloud Integration supports Authorization code grant type with Microsoft as a provider. Hence I have used open connectors to connect with ServiceNow using auth code grant type with ServiceNow as provider.

      Thanks,

      Vidyadhar K

      Author's profile photo d jaiswal
      d jaiswal
      Blog Post Author

      Hi Vidyadhar,

      Yes, I also want to see some blogs how to configure it through Auth Code grant type.It's open for the developer to explore and keep on sharing the knowledge and learning they adopted while facing such requirements.

      I will also check if I get such opportunity to work on this scenario too to share in coming days.Idea is to keep things reusable if requirement matches with different clients through sap blogs.

      Regards

      Deepak

      Author's profile photo Vidyadhar Kurmala
      Vidyadhar Kurmala

      Hi Deepak,

       

      I just saw your reply and hence providing the information now. There are many blogs already available on how to connect to ServiceNow using open connectors with basic authentication. however now SAP itself released OAUTH with authorization code artifact.. so you can utilize that if you want.

       

      Here is the open connector blog for your reference if interested: openconnectors-servicenow

      Thanks,

      Vidyadhar K

      Author's profile photo rshashi rshashi
      rshashi rshashi

      Explained well, good one Deepak. keep posting.

      Author's profile photo Ana Caorsi
      Ana Caorsi

      Excellent explanation! it helped me to build the connection with other partner that had grant-type:password credentials.

      Author's profile photo duarte guerreiro
      duarte guerreiro

      Hello Deepak. I am trying to replicate what you've done to obtain the token but I am getting a 401 error when making the request to the "..oauth_token.do" address. I checked the message body before the Request Reply step and it is as expected. Do you have any suggestion for the troubleshooting? Thank you.