How to redirect unauthenticated users to login for restricted knowledge articles from the kb_view.do page?

Steve Kelly
Mega Sage

Hello Community,

We have a mix of public and restricted KB articles in our Knowledge Base. We have successfully implemented a redirect to authenticate when an unauthenticated user tries to access a restricted knowledge article on our service portal (the default behavior is an 'Article not found' error which is not user friendly). However, has anyone been able to do this in the native UI by modifying the kb_view.do page?

I haven't used Jelly too much so I'm not very familiar. I see ServiceNow has implemented this for their own Hi portal, so I may end up asking on Hi if I can't find an answer here.

Cheers,

Steve

12 REPLIES 12

Just upvoted. Thanks Steve.

Community Alums
Not applicable

Hi Steve,

If you could post what you did for both widgets, that would be helpful to others who find this thread, depending on which they use. 

 

Thanks Much!

Lee

Sure thing, hope this helps! I am by no means an expert and there may be easier ways to do this, but it works for us...

'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

 

Community Alums
Not applicable

Thanks! This is fantastic!

 

Akash26
Tera Contributor

Hello Steve, 
Were you able to implement this on kb_view?

Can you share what you did?

 

Thanks in advance.