NOW Experience: How to customize ServiceNow Component source code to build you own Workspaces

ServiceNow Components not only can be used for your workspace development, but you can use existing component source code to change or extend functionality beyond provided component parameters, even for some undocumented components.

Click here to learn how to modify customer hidden classic ServiceNow application files.

Similar to Service Portal widgets, SN Components are read only and cannot be customized. You need to make a copy first. However, you will not find human readable source code anywhere in ServiceNow and you cannot just press ‘Copy’ button to make it work.

Note: not all components can be modified at this time because not all dependencies are available yet, however it is a good tool to browse and learn how Seismic is implemented.

If the component is documented, source code can be installed via NPM install, if not, you will need to utilize Chrome developer tools by having ‘Enable JavaScript source maps’ enabled via settings and by opening any workspace where component source code is executed.

If you open the source code for chrome.jsdbx, you see that source map was detected:

Doing CTRL+F search for ‘sourceMappingURL’ you will find the name and the link for the source map file:

For example: /scripts/@servicenow/now-button/ or /scripts/@servicenow/now-record-common/

Download it and use any source map browser (like this) to find the src folder and copy required source code for the component. Usually source files with a component code has @seismicElement declaration.

Going forward you need to set up your development environment. More info on SN Docs here.

  1. Download VS Code, git Bash, Node.js
  2. Create new project folder – right click to open with VS Code
  3. Set up VS Code terminal to utilize bash
  4. Run following commands:
npm install --global @servicenow/cli@orlando

now-cli login --host --method basic --username username --password password

now-cli project --name @servicenow_think/customize-components

npm install

now-cli develop --open

You should have your component running live by now.

Copy the source code from the map file and required dependencies (this can get tricky). Make sure declarations and names match in your files.

Change element name in the source code as well:

For POC purposes, add console.log statement on click and hardcode the button label in the source code:

Test Component locally:

Now register the component to UI Builder via now-ui.json:

Deploy the component to your instance:

now-cli deploy --open

It should appear in UI builder:

Add the component, save and activate the workspace page.

That’s it, it is possible to customize anything. Don’t forget to follow customization best practices!

How to authenticate with refresh token and Bearer Authorization header – ServiceNow Oauth 2.0

Since Orlando, there is a new feature for configuring Oauth 2.0. Now you can choose how you can authenticate with Oauth 2.0: by sending credentials in request body or as a Basic Authorization header, however not using Bearer.

This makes things a little bit easier, however it could be enhanced to allow more situations where authenticating could be done with 0 code.

For now on, let’s looks at an easy way to get access token when we are required to use refresh token which we can use in our Authorization Bearer HTTP header:

  1. Create application registry for third party Oauth 2.0 application
  2. Set up client_id and client_secret, set default grant type to ‘Client credentials’.
  3. Set Token URL as provided by 3rd party.
  4. Use example code below to execute your REST Message:
var oAuthClient = new sn_auth.GlideOAuthClient();
// Store the refresh token in sys_properties
var params = {grant_type:"refresh_token", refresh_token: gs.getProperty('xxx.refresh_token')};
var request_payload = new global.JSON().encode(params);
// requestToken first param is the Name in Application Registry
, request_payload is what is added to the Request body as chosen in Oauth profile
var tokenResponse = oAuthClient.requestToken("Application Name", request_payload);
var token = tokenResponse.getToken();

var restMessage = new sn_ws.RESTMessageV2('REST MESSAGE XXX', 'Method XXX');
// put a token with token.getAccessToken()
restMessage.setRequestHeader("Authorization", "Bearer " + token.getAccessToken());

var response = restMessage.execute();
var responseBody = response.getBody();;

Note: this way any calls that require Authorization Bearer header can be used. GlideOAuthClient can be modified to retrieve access token in any way 3rd party supports. It gets the token from the database, if it’s expired – makes a call to get a new one.

Hopefully a third OOTB option will be added to send credentials as a Bearer Authorization header or at least we will be allowed to modify HTTP Headers via Oauth API Scripts so we do not need to use the same script in our REST message executions and actual authentication will be controlled via main Oauth config profile.

How to send binary data with multipart from ServiceNow to Third Party applications (Box, Jira, etc…)

Most REST API’s are pretty straight forward, however handling binary data in ServiceNow is more complicated.

Note: this is mainly meant to provide examples of multipart building.

There is a great SN share project that implements how to send binary data through a clever workaround HERE, but there is a missing explanation how to add your binary data properly.

So first, how does this workaround actually work?

  1. Grab the attachment you want to send
  2. Call internal SN REST API that has access to response.getStreamWriter() object
  3. Create a new file using getStreamWriter() and add all boundaries and multipart request specific data parameters
  4. Save response body as an attachment – new binary file will be created that will hold attachment data with multipart parameters in clear text. If you opened the file with notepad, this is what you would see:

5. Send the attachment with setRequestBodyFromAttachment.

6. Send the attachment to third party API.

7. Delete the attachment created just for this.

In this example I will show you how to send binary data to Box and Jira.

JIRA is simpler, as it only requires single multipart piece. This is how you build getStreamWriter() object:

var writer = response.getStreamWriter();
writer.writeString("--" + boundaryValue + "\r\n"); //boundaries are read by the server
writer.writeString('Content-Disposition: form-data; name="file"; filename="' + fileName + '"\r\n');
writer.writeString('Content-Type: ' + contentType +'\r\n');
writer.writeString('\r\n'); // need to leave additional line empty before binary data
writer.writeStream(inputStream); // this is actual binary data
writer.writeString("\r\n--" + boundaryValue + "--\r\n");

BOX requires multiple multipart parameters:

This translates to this in SN:

var writer = response.getStreamWriter();
writer.writeString("--" + boundaryValue + "\r\n");
writer.writeString('Content-Disposition: form-data; name="attributes"\r\n');
writer.writeString('{"name":"' + fileName + '","parent":{"id":"11223334444"}}\r\n'); //this is just text data, could be binary
writer.writeString("--" + boundaryValue + "\r\n"); // note multiple boundaries for each File attribute
writer.writeString('Content-Disposition: form-data; name="file"; filename="' + fileName + '"\r\n');
writer.writeString('Content-Type: ' + contentType +'\r\n');
writer.writeString("\r\n--" + boundaryValue + "--\r\n");

That’s it!

Note: this can also be done using GlideSysAttachment().write(), however above mentioned way is documented and supported by ServiceNow, going GlideSysAttachment().write() route you have to use undocumented getBytes() method which could end up risky down the years.