diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/caret.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/caret.png new file mode 100644 index 00000000..13a132ab Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/caret.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/crane.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/crane.png new file mode 100644 index 00000000..225ecf3f Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/crane.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_1.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_1.png new file mode 100644 index 00000000..c9c56824 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_1.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_2.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_2.png new file mode 100644 index 00000000..4cb18873 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_2.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_3.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_3.png new file mode 100644 index 00000000..c2495cb0 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_3.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_4.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_4.png new file mode 100644 index 00000000..651d487f Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_4.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_5.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_5.png new file mode 100644 index 00000000..b50cb56b Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_5.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_6.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_6.png new file mode 100644 index 00000000..fd73a92b Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_6.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_7.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_7.png new file mode 100644 index 00000000..a4c5ab39 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_7.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_8.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_8.png new file mode 100644 index 00000000..daa836b6 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_8.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_9.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_9.png new file mode 100644 index 00000000..7134a1c0 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/eapi_9.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/facebook.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/facebook.png new file mode 100644 index 00000000..fa3f0e02 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/facebook.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_13.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_13.png new file mode 100644 index 00000000..abd41144 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_13.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_14.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_14.png new file mode 100644 index 00000000..750d8b68 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_14.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_15.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_15.png new file mode 100644 index 00000000..ec89f993 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_15.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_4.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_4.png new file mode 100644 index 00000000..42184717 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_4.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_5.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_5.png new file mode 100644 index 00000000..5680492e Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_5.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_6.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_6.png new file mode 100644 index 00000000..3b7f89ac Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_6.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_7.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_7.png new file mode 100644 index 00000000..401426d7 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_7.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_9.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_9.png new file mode 100644 index 00000000..176bfb11 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/gs_9.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/heart_icon.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/heart_icon.png new file mode 100644 index 00000000..bff9ea90 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/heart_icon.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/horizonalline.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/horizonalline.png new file mode 100644 index 00000000..7c49d872 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/horizonalline.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/linkedin.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/linkedin.png new file mode 100644 index 00000000..d1a0636d Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/linkedin.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sigma_footer.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sigma_footer.png new file mode 100644 index 00000000..df51d771 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sigma_footer.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_1.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_1.png new file mode 100644 index 00000000..4e15133d Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_1.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_10.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_10.png new file mode 100644 index 00000000..8f4e9107 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_10.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_11.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_11.png new file mode 100644 index 00000000..57f31f16 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_11.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_12.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_12.png new file mode 100644 index 00000000..4e1a1ca3 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_12.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_13.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_13.png new file mode 100644 index 00000000..6582b7e5 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_13.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_14.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_14.png new file mode 100644 index 00000000..c6b9f8c6 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_14.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_15.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_15.png new file mode 100644 index 00000000..653ed88f Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_15.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_16.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_16.png new file mode 100644 index 00000000..59053170 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_16.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_2.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_2.png new file mode 100644 index 00000000..bf86a1a5 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_2.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_3.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_3.png new file mode 100644 index 00000000..ac79be98 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_3.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_4.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_4.png new file mode 100644 index 00000000..60d47f08 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_4.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_5.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_5.png new file mode 100644 index 00000000..2ebe1f99 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_5.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_6.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_6.png new file mode 100644 index 00000000..ebb9b411 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_6.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_7.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_7.png new file mode 100644 index 00000000..2a15e2c9 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_7.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_8.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_8.png new file mode 100644 index 00000000..20fb3247 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/sn_8.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/assets/twitter.png b/site/sigmaguides/src/embedding_use_case_servicenow/assets/twitter.png new file mode 100644 index 00000000..5a827d72 Binary files /dev/null and b/site/sigmaguides/src/embedding_use_case_servicenow/assets/twitter.png differ diff --git a/site/sigmaguides/src/embedding_use_case_servicenow/embedding_use_case_embed_into_servicenow_v3.md b/site/sigmaguides/src/embedding_use_case_servicenow/embedding_use_case_embed_into_servicenow_v3.md new file mode 100644 index 00000000..62bef3ba --- /dev/null +++ b/site/sigmaguides/src/embedding_use_case_servicenow/embedding_use_case_embed_into_servicenow_v3.md @@ -0,0 +1,718 @@ +author: pballai +id: embedding_use_case_servicenow +summary: embedding_use_case_servicenow +categories: Embedding +environments: web +status: published +feedback link: https://github.com/sigmacomputing/sigmaquickstarts/issues +tags: default +lastUpdated: 2025-06-07 + +# Use Case: Embed into ServiceNow + +## Overview +Duration: 5 + +This QuickStart introduces you to embedding Sigma into ServiceNow. + +We will use a ServiceNow developer account and a Sigma trial to demonstrate how to minimally embed Sigma into a ServiceNow page using an iframe and a JSON Web Token (JWT) to secure the connection and provide the necessary JWT claims. + + + +For more information on Sigma's product release strategy, see [Sigma product releases](https://help.sigmacomputing.com/docs/sigma-product-releases). + +If something doesn’t work as expected, here's how to [contact Sigma support](https://help.sigmacomputing.com/docs/sigma-support). + +### Target Audience +The typical audience for this QuickStart includes users of Excel, common Business Intelligence or reporting tools, and semi-technical users who want to try out or learn Sigma. + +### Prerequisites + + + + + + + + + + + +![Footer](assets/sigma_footer.png) + + +## Required Sigma Configuration +Duration: 5 + +We need to create a few things in Sigma to embed into our host application. We will keep this part simple, as it is not the primary focus of this QuickStart. + +### Client Credentials +Client credentials (a unique Client ID and Embed Secret) are the foundation of secure embedding. + +Sigma uses the Client ID to determine which Embed Secret is referenced in a request. Each time a request is made, the server-side embed API uses the Embed Secret to generate an encrypted signature. + +Together, the Client ID and Embed Secret create a robust security framework for server-side interactions with Sigma. + +Navigate to `Administration` and scroll down to `Developer Access`. + +Click `Create New`: + + + +In the `Create client credentials` modal, select both the `REST API` and `Embedding` checkboxes, provide a name, and assign an administrative user as the owner: + + + + + +Click `Create`. + + + + + +Copy and paste the `Client ID` and `Secret` into a text file for later use. + +### Teams +Next, we’ll create a team and share the workbook with that team. The host application will then pass Sigma the team information when accessing content, along with other user details. + +Create a team named `Embed_Users` (creating a workspace is not required): + + + +### Create Content to Embed +Return to the homepage and click the `+ Create new` button, then select `Workbook`: + + + +Drag a new `Table` from the `Data` group on the `Element bar`: + + + +Click `Select source`. + +Sigma allows users to search for tables by name; type `hands` in the search bar and select the `PLUGS_ELECTRONICS_HANDS_ON_LAB_DATA` table from the `RETAIL` schema: + + + +This opens the selected table in a new, unsaved workbook named `Exploration`: + + + +Rename the table by double-clicking its name and changing it to `Plugs_Sales_Transactions`. + +Click the `Save as` button and save the workbook as `Embed_Service_QuickStart`. + +### Share the Workbook +Share **both workbooks** as shown below, setting the permission level to `View`: + + + +This will allow the `View` user to look at the workbook and perform basic actions like sorting and filtering. + + + +For more information on Sigma default account types, see [Default account types](https://help.sigmacomputing.com/docs/create-and-manage-account-types#default-account-types). + +### Workbook baseURL +Open the workbook's menu and select `Go to published version`: + + + +Copy the entire URL from the browser and paste into a text file for later use: + + + +![Footer](assets/sigma_footer.png) + + +## ServiceNow (SN) - Initial Configuration +Duration: 5 + +Navigating in ServiceNow can be challenging for those unfamiliar with its many features. For this reason, we will provide direct links for each configuration step. All links follow the same pattern: + +**:** Replace this with the portion of the URL that identifies your ServiceNow developer instance. + +For example, if the page URL is: +```code +https://dev274798.service-now.com/sys_properties_list.do +``` + +use https://dev274798.service-now.com in place of . + +If you prefer to use the ServiceNow navigation menu instead of direct links, that is also fine. + +### Create System Properties +We will use ServiceNow `System Properties` to configure required parameters (JWT claims) used when securely embedding Sigma. + +For more information, see [JSON web token claims reference](https://help.sigmacomputing.com/docs/json-web-token-claims-reference) + +Log in to your ServiceNow developer instance. Once the instance is running (this can take a few minutes), navigate to: +```code +.service-now.com/sys_properties_list.do +``` + +This process is repetitive, so we’ll show the steps for the first property and then list the others. + +Click `New` + + + +Name the new system property `x_sigma.client_id`, set the `Type` to `String`, and paste the Sigma `Client ID` created earlier into the `Value` box. + +Click `Submit`: + + + +Repeat the same process for the remaining required system properties: + +`x_sigma.debug` – 'true' or 'false'. + +`x_sigma.secret` – Sigma embed secret created early. + +`x_sigma.base_url` – Sigma embed base URL from earlier steps + +`x_sigma.session_length` – session lifetime in seconds. Use `3600`. + +`x_sigma.account_type` - "View". + +`x_sigma.teams` - as created earlier, "Embed_Users". + +`x_sigma.email` - use "view.embed.qs@example.com" or another email address you prefer, as long as it is not an existing Sigma portal user. + +Once created, we can see then all at once by setting a filter: + + + +![Footer](assets/sigma_footer.png) + + +## ServiceNow - Create Script Include +Duration: 5 + +We need to create a **Script Include** that will handle the server-side generation of the Sigma embed JWT. This script will securely read the system properties we created earlier, construct the JWT claims, and sign them with the Sigma Embed Secret. The output will be a valid JWT that can be passed to the Sigma embed URL in our widget. + + + +Navigate to: +```code +.service-now.com/sys_script_include_list.do +``` + +Click `New` + +- Set the name to `Sigma_Embed_API`. +- Make it Accessible from: `All application scopes`. +- Set `Active` to checked. + +Paste the following script into the script section (#4): +```code +/** + * Script Include: Sigma_Embed_API + * Purpose: Generate a Sigma embed URL signed with HS256 (no platform crypto). + * Inputs via sys_properties: + * x_sigma.client_id (Sigma Embed Client ID) [required] + * x_sigma.secret (Sigma Embed Secret) [required] + * x_sigma.base_url (Workbook/Dashboard URL) [required] + * x_sigma.session_length (seconds, default 3600; hard-capped at 30d) + * x_sigma.email (default subject email if not passed) + * x_sigma.account_type (e.g., View) + * x_sigma.teams (comma-separated team names) + * x_sigma.ua_* (user_attributes map; keys are after ua_) + * x_sigma.eval_connection_id (optional) + * x_sigma.secret_is_base64 (true if secret is base64-encoded) + * x_sigma.debug (true to enable gs.info logs) + */ +var Sigma_Embed_API = Class.create(); +Sigma_Embed_API.prototype = { + initialize: function () { + // Load core config from sys_properties + this.debug = (gs.getProperty('x_sigma.debug', 'false') === 'true'); + this.client_id = gs.getProperty('x_sigma.client_id', ''); + this.secret = gs.getProperty('x_sigma.secret', ''); + this.base_url = gs.getProperty('x_sigma.base_url', ''); + this.session_len = parseInt(gs.getProperty('x_sigma.session_length', '3600'), 10) || 3600; + + // Hard fail early if required inputs are missing + if (!this.client_id || !this.secret || !this.base_url) { + throw 'Missing required properties: x_sigma.client_id, x_sigma.secret, x_sigma.base_url'; + } + }, + + /** + * Build a signed Sigma embed URL. + * @param {string} email Optional subject email; falls back to x_sigma.email + * @returns {string} Full URL with :embed=true&:jwt= + */ + generateSignedUrl: function (email) { + var now = Math.floor(Date.now() / 1000); + var exp = now + Math.min(this.session_len, 2592000); // enforce 30d max + + // Subject (user identity) + var subject_email = (email && ('' + email).trim()) || + gs.getProperty('x_sigma.email', this.client_id); + + // Access claims + var account_type = (gs.getProperty('x_sigma.account_type', 'View') || 'View').trim(); + + // Teams (CSV → array) + var teams = []; + var teams_raw = (gs.getProperty('x_sigma.teams', '') || '').trim(); + if (teams_raw) { + var parts = teams_raw.split(','); + for (var i = 0; i < parts.length; i++) { + var t = ('' + parts[i]).trim(); + if (t) teams.push(t); + } + } + + // user_attributes: gather all x_sigma.ua_* properties + var user_attributes = {}; + var gr = new GlideRecord('sys_properties'); + gr.addQuery('name', 'STARTSWITH', 'x_sigma.ua_'); + gr.query(); + while (gr.next()) { + var key = ('' + gr.getValue('name')).replace(/^x_sigma\.ua_/, ''); + var val = '' + gr.getValue('value'); + if (key) user_attributes[key] = val; + } + + // Optional eval_connection_id + var eval_connection_id = (gs.getProperty('x_sigma.eval_connection_id', '') || '').trim(); + + // --- JWT header & payload (HS256) --- + var header = { alg: 'HS256', typ: 'JWT', kid: this.client_id }; + var payload = { + sub: subject_email, + iss: this.client_id, + jti: gs.generateGUID(), + iat: now, + exp: exp, + account_type: account_type, + user_attributes: user_attributes + }; + if (teams.length > 0) payload.teams = teams; + if (eval_connection_id) payload.eval_connection_id = eval_connection_id; + + // Sign the token (pure-JS HMAC-SHA256 → compact JWS) + var token = this._sign_jwt(header, payload, this.secret); + + // Base URL + required embed params + var joiner = (this.base_url.indexOf('?') >= 0) ? '&' : '?'; + var url = this.base_url + joiner + ':embed=true&:jwt=' + encodeURIComponent(token); + + // Optional UI params passthrough (if set as x_sigma.*) + var opt_keys = [ + 'disable_mobile_view', 'hide_menu', 'hide_folder_navigation', 'hide_tooltip', + 'lng', 'menu_position', 'responsive_height', 'theme' + ]; + var extras = []; + for (var k = 0; k < opt_keys.length; k++) { + var prop = 'x_sigma.' + opt_keys[k]; + var val = gs.getProperty(prop, null); + if (val !== null && val !== '' && typeof val !== 'undefined') { + extras.push(':' + opt_keys[k] + '=' + encodeURIComponent('' + val)); + } + } + if (extras.length) url += '&' + extras.join('&'); + + if (this.debug) gs.info('[Sigma_Embed_API] final_url=' + url); + return url; + }, + + // ------------------------------------------------------------ + // JWT signer (compact JWS) using pure-JS HMAC-SHA256 + // ------------------------------------------------------------ + _sign_jwt: function (header_obj, payload_obj, secret) { + var header_b64 = this._b64url_string(this._json(header_obj)); + var payload_b64 = this._b64url_string(this._json(payload_obj)); + var signing_in = header_b64 + '.' + payload_b64; + + // Support base64-encoded secrets if x_sigma.secret_is_base64=true + var isB64 = (gs.getProperty('x_sigma.secret_is_base64', 'false') === 'true'); + var keyBytes = isB64 ? this._from_b64(('' + secret).replace(/[\r\n]/g, '').trim()) + : this._utf8(('' + secret)); + + var msgBytes = this._utf8(signing_in); + var sigBytes = this._hmac_sha256(msgBytes, keyBytes); // bytes + var sigB64 = this._b64_from_bytes(sigBytes); // Base64 + var sigUrl = this._to_b64url(sigB64); // base64url + + return signing_in + '.' + sigUrl; + }, + + // ------------------------------------------------------------ + // Helpers: JSON, UTF-8, Base64, SHA-256, HMAC-SHA256 + // ------------------------------------------------------------ + _json: function (obj) { return new global.JSON().encode(obj); }, + + _utf8: function (str) { + var out = [], i = 0, c, c2; + for (; i < str.length; i++) { + c = str.charCodeAt(i); + if (c < 0x80) out.push(c); + else if (c < 0x800) out.push(0xc0 | (c >> 6), 0x80 | (c & 0x3f)); + else if (c >= 0xd800 && c < 0xe000) { + i++; c2 = str.charCodeAt(i); + var u = 0x10000 + (((c & 0x3ff) << 10) | (c2 & 0x3ff)); + out.push(0xf0 | (u >> 18), 0x80 | ((u >> 12) & 0x3f), 0x80 | ((u >> 6) & 0x3f), 0x80 | (u & 0x3f)); + } else { + out.push(0xe0 | (c >> 12), 0x80 | ((c >> 6) & 0x3f), 0x80 | (c & 0x3f)); + } + } + return out; + }, + + _b64_from_bytes: function (bytes) { + var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', out = '', i = 0; + for (; i < bytes.length; i += 3) { + var b0 = bytes[i] & 0xff, + b1 = (i + 1 < bytes.length) ? (bytes[i + 1] & 0xff) : 0, + b2 = (i + 2 < bytes.length) ? (bytes[i + 2] & 0xff) : 0; + var tri = (b0 << 16) | (b1 << 8) | b2; + out += chars[(tri >>> 18) & 0x3f]; + out += chars[(tri >>> 12) & 0x3f]; + out += (i + 1 < bytes.length) ? chars[(tri >>> 6) & 0x3f] : '='; + out += (i + 2 < bytes.length) ? chars[tri & 0x3f] : '='; + } + return out; + }, + + _to_b64url: function (b64) { + return ('' + b64).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, ''); + }, + + _b64url_string: function (plain_str) { + return this._to_b64url(this._b64_from_bytes(this._utf8(plain_str))); + }, + + // Base64 decoder (used only when x_sigma.secret_is_base64=true) + _from_b64: function (b64) { + var s = ('' + b64).replace(/[\r\n\s]/g, ''); + var table = {}, chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + for (var i = 0; i < chars.length; i++) table[chars.charAt(i)] = i; + var out = [], j = 0, acc = 0, bits = 0, c, val; + for (i = 0; i < s.length; i++) { + c = s.charAt(i); if (c === '=') break; + val = table[c]; if (val === undefined) continue; + acc = (acc << 6) | val; bits += 6; + if (bits >= 8) { bits -= 8; out[j++] = (acc >> bits) & 0xff; } + } + return out; + }, + + // SHA-256 (bytes → 32-byte array) + _sha256: function (bytes) { + function rotr(n, x){ return (x >>> n) | (x << (32 - n)); } + function Ch(x,y,z){ return (x & y) ^ (~x & z); } + function Maj(x,y,z){ return (x & y) ^ (x & z) ^ (y & z); } + function Σ0(x){ return rotr(2,x) ^ rotr(13,x) ^ rotr(22,x); } + function Σ1(x){ return rotr(6,x) ^ rotr(11,x) ^ rotr(25,x); } + function σ0(x){ return rotr(7,x) ^ rotr(18,x) ^ (x >>> 3); } + function σ1(x){ return rotr(17,x) ^ rotr(19,x) ^ (x >>> 10); } + + var K = [ + 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, + 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, + 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, + 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, + 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, + 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, + 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, + 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + ]; + + var l = bytes.length, bitHi = Math.floor(l / 0x20000000), bitLo = (l << 3) >>> 0; + var withOne = bytes.slice(0); withOne.push(0x80); + while ((withOne.length % 64) !== 56) withOne.push(0); + + var words = []; + for (var i = 0; i < withOne.length; i += 4) { + words.push(((withOne[i] << 24) | (withOne[i+1] << 16) | (withOne[i+2] << 8) | (withOne[i+3] | 0)) >>> 0); + } + words.push(bitHi >>> 0); words.push(bitLo >>> 0); + + var H0=0x6a09e667,H1=0xbb67ae85,H2=0x3c6ef372,H3=0xa54ff53a, + H4=0x510e527f,H5=0x9b05688c,H6=0x1f83d9ab,H7=0x5be0cd19; + + var W = new Array(64); + for (var j = 0; j < words.length; j += 16) { + for (var t = 0; t < 16; t++) W[t] = words[j+t] >>> 0; + for (t = 16; t < 64; t++) W[t] = (σ1(W[t-2]) + W[t-7] + σ0(W[t-15]) + W[t-16]) >>> 0; + + var a=H0,b=H1,c=H2,d=H3,e=H4,f=H5,g=H6,h=H7; + for (t = 0; t < 64; t++) { + var T1 = (h + Σ1(e) + Ch(e,f,g) + K[t] + W[t]) >>> 0; + var T2 = (Σ0(a) + Maj(a,b,c)) >>> 0; + h=g; g=f; f=e; e=(d + T1) >>> 0; + d=c; c=b; b=a; a=(T1 + T2) >>> 0; + } + H0=(H0+a)>>>0; H1=(H1+b)>>>0; H2=(H2+c)>>>0; H3=(H3+d)>>>0; + H4=(H4+e)>>>0; H5=(H5+f)>>>0; H6=(H6+g)>>>0; H7=(H7+h)>>>0; + } + + var out = []; + function push(w){ out.push((w>>>24)&255,(w>>>16)&255,(w>>>8)&255,w&255); } + push(H0); push(H1); push(H2); push(H3); push(H4); push(H5); push(H6); push(H7); + return out; + }, + + // HMAC-SHA256 (bytes → 32-byte array) + _hmac_sha256: function (msgBytes, keyBytes) { + var block = 64; // 512-bit block size + if (keyBytes.length > block) keyBytes = this._sha256(keyBytes); + if (keyBytes.length < block) { + var pad = new Array(block - keyBytes.length); + for (var i = 0; i < pad.length; i++) pad[i] = 0; + keyBytes = keyBytes.concat(pad); + } + var oKey = [], iKey = []; + for (var j = 0; j < block; j++) { oKey[j] = keyBytes[j] ^ 0x5c; iKey[j] = keyBytes[j] ^ 0x36; } + return this._sha256(oKey.concat(this._sha256(iKey.concat(msgBytes)))); + }, + + // Class marker + type: 'Sigma_Embed_API' +}; +``` + + + +Click `Submit` + + + +![Footer](assets/sigma_footer.png) + + +## ServiceNow - Create REST Resource +Duration: 5 + +We need to create a **REST API Resource** that will act as the endpoint for generating and returning the Sigma embed JWT. This REST Resource will call the `Sigma_Embed_API` Script Include we created earlier, receive the signed JWT, and return it to the widget or page requesting the embed. + + + + +Navigate to: +```code +.service-now.com/sys_ws_definition_list.do +``` + +Click `New` + +- Set the name to `Sigma Embed`. +- The API ID should be `sigma_embed`. +- Set `Active` to checked. + +Click `Submit`: + + + +The UI will return to the `Scripted REST APIs` page. Search for `Sigma` and click into the `Sigma Embed` just created. + +Click the `New` button in the lower right corner to create a new resource inside the service: + + + +- Set the name to `sigma-embed-url`. +- Set `Active` to checked. +- The HTTP method should be `GET`. +- Relative path should be `/sigma-embed-url`. + +Paste the following script in the `* Script` box: +```code +(function process(request, response) { + var email = (request.queryParams.email || gs.getProperty('x_sigma.email') || '').trim(); + + var svc = new Sigma_Embed_API(); + var signedUrl = svc.generateSignedUrl(email); + + // simplest: return an object and let SN serialize it + response.setStatus(200); + return { url: '' + signedUrl }; +})(request, response); +``` + +Click `Submit`: + + + +![Footer](assets/sigma_footer.png) + + +## ServiceNow - Create Widget +Duration: 5 + +We need to create a **Service Portal Widget** that will request the Sigma embed JWT from our REST Resource and then dynamically render the Sigma content inside an `iframe`. + +This widget will be placed on a page in the Service Portal. + +Navigate to: +```code +.service-now.com/sp_widget_list.do +``` + +Click `New` + +Set the Name to `Sigma iFrame`. + +In each of the following sections we apply code to operations and styling to the Iframe. + +In `Body HTML template` copy/paste the following code: +```code +
+ +
+``` + + + + +In the `CSS` section: +```code +#sigma_embed { + width: 100%; + height: 90vh; + border: none; +} +``` + +In the `Client controller` section: +```code +api.controller = function($scope, $http, $sce) { + var c = this; + c.sigmaUrl = ''; + + c.$onInit = function() { + $http.get('/api/1807505/sigma_embed/sigma-embed-url').then(function(res) { + var rawUrl = (res.data && res.data.result && res.data.result.url) || + (res.data && res.data.url) || ''; + if (rawUrl) { + // Tell Angular this URL is safe to use in an