- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hi Community,
I am working on a requirement to strictly isolate user access between two ServiceNow Portals based on roles.
Requirement Details:
Partner users should only be able to access the Partner Portal (/partner)
Employee users should only be able to access the Employee Center (/esc)
Current Configuration:
Login redirection has been implemented using SPEntryPage, and users are correctly redirected to their respective portals after authentication.
Challenge:
While the redirection works as expected, users are still able to manually access unauthorized portals via direct URL manipulation (for example, a Partner user entering /esc in the browser).
Expectation:
I am looking to enforce strict access control at the portal level, such that:
Unauthorized users are completely blocked from accessing the portal
Access results in a server-side Access Denied or 404-style response
The solution follows ServiceNow best practices and is secure and maintainable
Questions:
What is the recommended best practice in ServiceNow to restrict Service Portal access based on roles?
Is there a standard server-side mechanism to enforce this restriction rather than relying only on UI redirection?
Are there any OOB approaches (ACLs, portal configuration, or scripting) that should be preferred for this use case?
Any guidance or proven approach from real-world implementations would be highly appreciated.
Thank you.
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
2 weeks ago
[SOLVED] Workaround: Restricting Manual URL Access to Portals using a Header Widget
Post Body:
Thanks @VANSHIKAMUKand @Ankur Bawiskar for your detailed responses and guidance.
The Challenge:
While SPEntryPage successfully handled the initial login redirection, I faced an issue where users could still access unauthorized portals by manually typing the URL (e.g., a Partner user typing /esc).
The Constraint:
As @VANSHIKAMUK mentioned, the standard OOB method is using User Criteria (Can View/Cannot View related lists) on the Portal record. However, in my specific instance, the Service Portal User Criteria Support plugin was not active, and I did not have the permissions/access to enable the specific system properties to expose those related lists.
The Solution (Workaround):
I implemented a "Security Guard" logic directly within the Portal Header. Since the header loads on every page, it acts as a gatekeeper. If an unauthorized user tries to force their way in via URL, the header script detects their role and immediately redirects them back to their allowed portal.
Here is the implementation steps for anyone facing similar constraints:
Step 1: Create a new Widget
Name: Portal Security Redirect
ID: portal-security-redirect
Server Script:
(function() { var user = gs.getUser(); var portal = $sp.getPortalRecord().url_suffix.toString(); data.redirect = false; data.redirect_url = ""; // SCENARIO 1: Partner User trying to access Employee Center (/esc) // Check if user is a Partner (and NOT an Admin) var isPartner = user.hasRole('partner_user') || user.hasRole('partner_mgmt_user'); if (portal == 'esc' && isPartner) { if (!user.hasRole('admin')) { data.redirect = true; data.redirect_url = '/partner'; // Route back to Partner Portal } } // SCENARIO 2: Internal Employee trying to access Partner Portal (/partner) if (portal == 'partner') { // If they are NOT a partner and NOT an admin, don't allow them if (!isPartner && !user.hasRole('admin')) { data.redirect = true; data.redirect_url = '/esc'; // Route back to Employee Center } } })();
Client Controller:
api.controller = function($window) { var c = this; if (c.data.redirect) { $window.location.href = c.data.redirect_url; } };
Step 2: Embed this Widget in your Portal Header
I opened my custom Header widget (used by the Portal Theme) and added the security widget to the very top.
Header Widget Server Script:
data.securityRedirect = $sp.getWidget('portal-security-redirect');
Header Widget HTML Template (at the very top):
<sp-widget widget="data.securityRedirect"></sp-widget>
This successfully blocks manual URL manipulation without requiring the User Criteria plugin. Thanks again for the help!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
2 weeks ago
I believe I also shared a working solution using UI script.
Thank you for marking my response as helpful.
💡 If my response helped, please mark it as correct ✅ as well so that this helps future readers find the solution faster! 🙏
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
1) Page‑level authorization with roles (primary control)
- On each Service Portal page (sp_page), populate the Roles related list with the role that are required to view it.
- For the Partner Portal pages, add a role like x_partner.user (or your equivalent).
- For Employee Center (/esc) pages, add sn_hr_sp.hrsp_employee / sn_hr_core or your chosen employee role.
- When a user without the role hits the page URL, Service Portal won’t render it. Instead, it routes to the portal’s Access denied page (configurable per portal). That’s server‑side enforcement.
2) Configure “Access denied” and “Page not found” pages per portal
- In each sp_portal record:
- Requires login: ✅ enabled.
- Access denied page: point to a page that shows a clear 403‑style message to unauthorized users.
- Page not found page: point to a page with a 404‑style message.
- These are server‑side outcomes—not just UI messages.
3) Enforce with ACLs (data‑level protection)
- Even if someone finds a way to call a widget or data source directly, the table/field ACLs must block them.
- Lock down tables used by the Partner portal to x_partner.user (or group/role equivalents).
- Lock down HR/ESC data to employee roles only (e.g., sn_hr_sp.hrsp_employee).
4) Widget, menu, and module roles (defense‑in‑depth)
- sp_widget: set Roles on widgets so they can’t execute server scripts for unauthorized users.
- sp_menu / sp_menu_item: add Roles to keep navigation from surfacing cross‑portal links.
- Catalogs, Categories, and Items: restrict with roles so they don’t render in the “wrong” portal even if a page is reachable.
5) Routing/layout guards (optional belt‑and‑suspenders)
- If you have a global layout widget (present on every page), you can add a server‑side guard that:
- Checks the current portal vs. the user’s allowed audience and,
- If mismatched, sets a flag to render an Access Denied fragment or route to the portal’s Access Denied page.
- Treat this as secondary; your primary controls should be sp_page roles + ACLs.
Addressing your questions directly
1) Best practice to restrict Service Portal access based on roles?
Use sp_page Roles to authorize pages (server‑side), backed by table/field ACLs for data. Keep page sets distinct per portal so role gating is absolute.
2) Is there a standard server‑side mechanism rather than UI redirection?
Yes. Service Portal page authorization is done server‑side via sp_page Roles. Unauthorized users do not get the page rendered; the request routes to the portal’s Access denied page. Complement with ACLs to protect data.
3) OOB approaches to prefer (ACLs, portal config, scripting)?
- OOB & preferred: sp_page Roles, ACLs, Portal → Access denied/Page not found configuration, widget/menu roles, catalog/KB role restrictions.
- Optional scripting: A global layout widget server script as an extra guard, but avoid making it your only control.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
you are already redirecting but users can change browser URL and navigate and see
For this you can use this workaround
use custom UI script and Ajax to inform them and redirect them to CSM portal automatically.
for that check this
Solution: Redirecting Users to the CSM Portal Based on Roles in ServiceNow
💡 If my response helped, please mark it as correct ✅ and close the thread 🔒— this helps future readers find the solution faster! 🙏
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hope you are doing good.
Did my reply answer your question?
💡 If my response helped, please mark it as correct ✅ and close the thread 🔒— this helps future readers find the solution faster! 🙏
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
2 weeks ago
[SOLVED] Workaround: Restricting Manual URL Access to Portals using a Header Widget
Post Body:
Thanks @VANSHIKAMUKand @Ankur Bawiskar for your detailed responses and guidance.
The Challenge:
While SPEntryPage successfully handled the initial login redirection, I faced an issue where users could still access unauthorized portals by manually typing the URL (e.g., a Partner user typing /esc).
The Constraint:
As @VANSHIKAMUK mentioned, the standard OOB method is using User Criteria (Can View/Cannot View related lists) on the Portal record. However, in my specific instance, the Service Portal User Criteria Support plugin was not active, and I did not have the permissions/access to enable the specific system properties to expose those related lists.
The Solution (Workaround):
I implemented a "Security Guard" logic directly within the Portal Header. Since the header loads on every page, it acts as a gatekeeper. If an unauthorized user tries to force their way in via URL, the header script detects their role and immediately redirects them back to their allowed portal.
Here is the implementation steps for anyone facing similar constraints:
Step 1: Create a new Widget
Name: Portal Security Redirect
ID: portal-security-redirect
Server Script:
(function() { var user = gs.getUser(); var portal = $sp.getPortalRecord().url_suffix.toString(); data.redirect = false; data.redirect_url = ""; // SCENARIO 1: Partner User trying to access Employee Center (/esc) // Check if user is a Partner (and NOT an Admin) var isPartner = user.hasRole('partner_user') || user.hasRole('partner_mgmt_user'); if (portal == 'esc' && isPartner) { if (!user.hasRole('admin')) { data.redirect = true; data.redirect_url = '/partner'; // Route back to Partner Portal } } // SCENARIO 2: Internal Employee trying to access Partner Portal (/partner) if (portal == 'partner') { // If they are NOT a partner and NOT an admin, don't allow them if (!isPartner && !user.hasRole('admin')) { data.redirect = true; data.redirect_url = '/esc'; // Route back to Employee Center } } })();
Client Controller:
api.controller = function($window) { var c = this; if (c.data.redirect) { $window.location.href = c.data.redirect_url; } };
Step 2: Embed this Widget in your Portal Header
I opened my custom Header widget (used by the Portal Theme) and added the security widget to the very top.
Header Widget Server Script:
data.securityRedirect = $sp.getWidget('portal-security-redirect');
Header Widget HTML Template (at the very top):
<sp-widget widget="data.securityRedirect"></sp-widget>
This successfully blocks manual URL manipulation without requiring the User Criteria plugin. Thanks again for the help!
