Service Portal Separation & Redirection
I have been observing this requirement from various MSPs or other clients who have multiple Service Portals implemented and would like to restrict users from accessing one or more portals (i.e. user who belong to another company or a specific group) also would like to redirect users to their authorized portal if they try to access another portal.
While there may be several possible solutions available (i.e. redirection widget in header or customizing header or page code to hide content if user is not permitted to see it), this solution doesn't involve customizing any OOB widgets and/or pages and is purely additive in nature.
This solution provides desired functionality using client side OOTB features provided by ServiceNow platform. It covers:
(a) Redirection to Customer's relevant portal
(b) Restrict any other portal which user should not be able to access
The solution involves 3 components which enable this functionality i.e.
- Global UI Script
- JS Script
- UI Page
These components interact with each other as per below diagram.
I would like to share steps to implement this solution and how you could modify it to fit your needs.
For this proof of concept, I would consider that each company/customer has their own portal and would like to restrict another customer from accessing it. Also, if a user tries to access another customer's portal they are redirected back to their portal.
Pre-Configuration & Data Setup:
Since each customer has their own respective portal, we have created a custom field 'Company' on 'sp_portal' table which references to 'core_company' table. Please see below picture for the dictionary definition.
2. Setup portals for testing
Create couple of portals to use for testing, you may decide to create/use your own portals for this purpose however I have created following portals and associated with respective companies as below:
3. Setup users for testing
Setup couple of users to use for testing, you may decide to use any users for this purpose, however I have associated following users with respective company records as below:
Step 1: Create a Global UI Script
This UI Script will reset browser variables whenever a user is logged in to the system.
Create UI Sript as below:
Name: sf.session.reset
Global: Checked
Script:
addLoadEvent(
function(){
try{
var currentUser=g_user.userID;
var previousUser=localStorage.getItem('user');
if(currentUser!=previousUser){
localStorage.setItem('user',g_user.userID);
localStorage.setItem("custUrl", "");
localStorage.setItem("returnUrl","");
}
}catch(e){}
});
Step 2: Create a UI Page
This UI page will redirect users to their respective Service Portal for the very first time and also set browser variables.
Create UI Page as below:
Name: portal_redirect
HTML:
<?xml version="1.0" encoding="utf-8" ?>
</p> <p> addLoadEvent( function() { </p> <p> redirect(); </p> <p>}); </p> <p>
|
|
Client Script:
function redirect(){
var pageURI = localStorage.getItem('returnUrl');
if(!pageURI){
pageURI = window.location.toString();
}
var portal=getUserPortal();
// setting browser variable
localStorage.setItem("custUrl", portal);
// returns true if user portal does not exists in url
if(pageURI.indexOf("/"+portal+"?")==-1 ||
pageURI.substr(pageURI.length - portal.length)!=portal){
if(pageURI.indexOf('?')!=-1){
window.location="/"+portal+pageURI.substring(pageURI.indexOf('?'));
}
else
{
window.location="/"+portal;
}
}
}
function getUserPortal(){
/* Retrieve user portal based on their company association in portal record, you can change below code to return the portal suffix based on your requirement. i.e. portal which user have access based on their group membership etc.. */
// fetch user company
var grComp= new GlideRecord('sys_user');
grComp.get(g_user.userID);
// fetch user portal
//console.log(grComp.company.toString());
var grPortal= new GlideRecord('sp_portal');
grPortal.addQuery('u_company',grComp.company.toString());
grPortal.query();
grPortal.next();
//console.log(grPortal.url_suffix);
return grPortal.url_suffix;
}
Function getUserPortal() in above client script has all the logic around which portal user need to be redirected to or is authorized to access. Depending on your requirement you can modify script to return desired portal suffix.
Step 3: Create a JS Script
This UI Script serves as JS Script in Service Portal Dependences and gets invoked before service portal / page is loaded.
Create UI Script as per below:
Name: sf.portal.redirect
Script:
invokeRedirector();
function invokeRedirector(){
var portal=localStorage.getItem('custUrl');
var pageURI = window.location.toString();
var redPage="/portal_redirect.do";
var custUrl;
if(pageURI.indexOf('sp')==-1){
if(!portal){
localStorage.setItem("returnUrl", pageURI);
window.location=redPage;
}
else if(pageURI.indexOf("/"+portal+"?")==-1 &&
pageURI.substr(pageURI.length - portal.length)!=portal){
if(pageURI.indexOf('?')!=-1){
custUrl=portal+pageURI.substring(pageURI.indexOf('?'));
window.location="/"+custUrl;
}
else
{
custUrl=portal;
window.location="/"+custUrl;
}
}
}
}
Step 4: Configure Dependency
- Navigate to 'Service Portal>Dependencies'
- Click on 'New' button
- Give it name of 'sf.portal.redirect'
- Enable check box 'Include on page load'
- For 'Portals for page load (optional)' field select all the portals on which you would like to implement this functionality
- Right click in the header and click 'Save'
- On 'JS Includes' related list, click 'New'
- Give a display name 'sf.portal.redirect'
- And in the field named 'UI Script' select UI script 'sf.portal.redirect'
After all this configuration, your form should look like below:
- Navigate to Service Portal > Headers & Footers
- Open your header record i.e. 'Stock Header'
- Right click on page header and add 'Dependencies' related list
- On 'Dependencies' related list, click 'Edit'
- Select & move to right 'sf.portal.redirect' dependency and click 'Save'
- Repeat steps ii to v for all the headers which you may have used in portals.
After this configuration, related list section in header record should look like below:
Testing the Solution
Test Case 1: Redirection to Correct Portal
Login/impersonate with a user who belongs to company 'Cloud Dimensions' and try to access portal of 'ACME Corporation' by navigating to url https:///acme user will be immediately redirected to https:///cd
Test Case 2: Redirection to Correct Portal with specific page
Login/impersonate with a user who belongs to company 'Cloud Dimensions' and try to access service catalog page of 'ACME Corporation' by navigating to url https:///acme?id=sc_home user will be immediately redirected to service catalog page of Cloud Dimensions https:///cd?id=sc_home
Test Case 3: Redirect to a non-restricted portal
Login/impersonate with a user who belongs to any company and try to access a portal which is not restricted i.e. https:///sp users will not be redirected and be able access this unrestricted portal.
Please share your feedback & details on how you implemented this solution to meet your requirement.
Thanks
https://www.servicenow.com/community/now-platform-articles/service-portal-separation-redirection/ta-p/2322079