Knowledge article link is not redirecting to SSO login

vinod18
Tera Contributor

We have SSO set up on our instance.  When clicking a link to a KB article, we get the "You do not have sufficient privileges to access this knowledge item" page if not already logged in to ServiceNow.  It does not redirect to the SSO sign in page.  When already logged in, the link works and displays the article.

1 ACCEPTED SOLUTION

Mike_R
Kilo Patron
Kilo Patron

Is the KB link a portal link?

If so, make sure that portal page is not public.

View solution in original post

4 REPLIES 4

Mike_R
Kilo Patron
Kilo Patron

Is the KB link a portal link?

If so, make sure that portal page is not public.

Hi @Mike_R ,

 

Yes, the KB link is a portal link and making the portal page "KB_article_view" as not public works to redirect to portal login page......

But the challenge is, we have few KB's that needs to be accessed publicly... so we can't change the portal page as not public.

Kindly advise if there is any other way to redirect the non-logged in user to portal login page. 

 

Note: We have multiple knowledge bases that also have "Can read" user criteria's defined, so some KB's are accessible only after they Login and hence the user needs to be redirected to SSO / portal login page.   

 

This could be very tricky and I don't think there is a solution OOTB.

 

A user posted a solution/customization here (go to Steve Kelly's response)

https://www.servicenow.com/community/developer-forum/how-to-redirect-unauthenticated-users-to-login-...

'KB Article Page' widget

Add the following code to the server and client sides. FYI we use external SSO for authentication.

Server

We added this code from lines 25 - 38 but this may vary depending on widget versioning.

// Adding server side code to determine if login to view article is needed - START
data.article_exists = recordIsValid;
data.can_read_article = canReadArticle;
data.url_suffix = $sp.getPortalRecord().getDisplayValue("url_suffix");
data.default_idp = GlideProperties.get("glide.authenticate.sso.redirect.idp");
data.is_logged_in = gs.getSession().isLoggedIn();

if(input && input.action === "set_sso_destination") {
	
	gs.getSession().putProperty("login_redirect_url",'/' + data.url_suffix + '?id=kb_article&sys_id=' + articlesysid);

}

// Adding server side code to determine if login to view article is needed - END

Client

We added this code from lines 12 - 30 but this may vary depending on widget versioning.

// Adding client side code to determine if login to view article is needed - START
	
	c.data.url = $window.location.href;
	
	if (!c.data.isvalid && c.data.article_exists && !c.data.is_logged_in) {
		
		c.server.get({
			
			action: "set_sso_destination"
			
		}).then(function() {
			
			var url = "login_with_sso.do?glide_sso_id=" + c.data.default_idp;
			$window.location.href = url;
			
		});
	}
	
	// Adding client side code to determine if login to view article is needed - END

'Knowledge Article Content' widget

This was way more involved. The following steps had to be done:

  1. Clone the widget in the Global scope (this is needed as gs.getSession().putProperty() is not available in the Knowledge Management Service Portal scope.
  2. You will also need to associate the three Angular ng-templates associated with the OOB widget to your new custom widget.
  3. Create a script include in the Global scope to mimic the existing 'KBPortalService' script include which is in the Knowledge Management Service Portal scope. You can call it 'KBPortalServiceGlobal' or something like that. It will just point to the 'KBPortalServiceImpl' script include, same as the 'KBPortalService' script include. This needs to be done as the 'KBPortalService' script include cannot be called from Global; I tried configuring cross scope access but could not get it to work.

Now for the widget itself. The code could definitely be a bit more graceful with the error messages that are displayed to the end user, but it works for the authentication redirect. This widget is pretty complex and I didn't have enough time to really dig into it. But here is what I did.

Server

Added the following code at line 5

// Adding server side code to determine if login to view article is needed - START
data.url_suffix = $sp.getPortalRecord().getDisplayValue("url_suffix");
data.is_logged_in = gs.getSession().isLoggedIn();

if ($sp.getParameter('sysparm_article')) {

	data.kbNumAU = $sp.getParameter('sysparm_article');
	
	data.kbExistsAU = false;
	
	var getsys = new GlideRecord('kb_knowledge');
	getsys.addQuery('number',data.kbNumAU);
	getsys.addQuery('workflow_state','published');
	getsys.setLimit(1);
	getsys.query();
	while(getsys.next()) {
		data.kbExistsAU = true;
		}
	}
// Adding server side code to determine if login to view article is needed - END

Modified the following line to the new Global script include created earlier:

var kbPortal = new KBPortalServiceGlobal();

Added the following code before the line that starts with if(input) {

// Adding server side code to determine if login to view article is needed - START
    if (input && input.action === "set_sso_destination") {
			
			if (data.kbNumAU)
				gs.getSession().putProperty("login_redirect_url", '/' + data.url_suffix + '?id=kb_article_view&sysparm_article=' + data.kbNumAU);
			else
				gs.getSession().putProperty("login_redirect_url", '/' + data.url_suffix + '?id=kb_article_view&sys_kb_id=' + ($sp.getParameter('sys_kb_id') || $sp.getParameter('sys_id')));

    }
// Adding server side code to determine if login to view article is needed - END

Client

Added the following code at the end of the client script code (around line 399

// Adding client side code to determine if login to view article is needed - START
	
	c.data.url = $window.location.href;
	if ((!c.data.isValid && c.data.knowledgeExists && !c.data.is_logged_in) || (!c.data.isValid && !c.data.knowledgeExists && c.data.kbExistsAU && !c.data.is_logged_in)) {
		c.server.get({
			
			action: "set_sso_destination"
			
		}).then(function() {
			
			var url = "login_with_sso.do";
			$window.location.href = url;
			
		});
	}
	
// Adding client side code to determine if login to view article is needed - END

Anusha dandu1
Tera Contributor

Thanks @Mike_R ...... much appreciated, very helpful.....