Service Portal Separation & Redirection

Version 1

    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.

    1. Global UI Script
    2. JS Script
    3. UI Page

     

    These components interact with each other as per below diagram.

    Service Portal Separation & Redirection - Page 1.jpeg

     

    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:

    1. Configure Portal Record

         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.

    portal_cfg.png

     

         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:

    portals.jpg

         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:

    users.jpg

     

     

    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" ?>
    <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
    <script> 
                      addLoadEvent( function() {  
                      redirect();  
    });  
    </script>                
        <div >
          <table><tr>
            <td style='width: 300px; vertical-align: top;'>
              <p><img src="./images/loading_anim4.gifx"/> Redirecting </p>                     
                                          </td>
                                          </tr>
                        </table>
                       </div>     
    </j:jelly>
    
    

     

    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

     

    1. Navigate to ‘Service Portal>Dependencies’
    2. Click on ‘New’ button
    3. Give it name of ‘sf.portal.redirect’
    4. Enable check box ‘Include on page load’
    5. For ‘Portals for page load (optional)’ field select all the portals on which you would like to implement this functionality
    6. Right click in the header and click ‘Save’
    7. On ‘JS Includes’ related list, click ‘New’
    8. Give a display name ‘sf.portal.redirect’
    9. And in the field named ‘UI Script’ select UI script ‘sf.portal.redirect’

     

    After all this configuration, your form should look like below:

     

    widget.png

     

    1. Navigate to Service Portal > Headers & Footers
    2. Open your header record i.e. ‘Stock Header
    3. Right click on page header and add ‘Dependencies’ related list
    4. On ‘Dependencies’ related list, click ‘Edit’
    5. Select & move to right ‘sf.portal.redirect’ dependency and click ‘Save’
    6. 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:

     

    dep.png

     

     

    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://<instancename>/acme user will be immediately redirected to https://<instancename>/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://<instancename>/acme?id=sc_home user will be immediately redirected to service catalog page of Cloud Dimensions https://<instancename>/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://<instancebame>/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

     

    Cheers
    Syed Faheem
    ---------------
    Psst: Hit like, Helpful or Correct depending on the impact of the response