Configure SSO using remote authentication (log in readers via a 3rd party website or application)

Remote authentication allows you to authenticate readers using your existing systems. This option is best for companies that want to eliminate the need for their readers to manage multiple passwords but do not have the ability to use SAML.

Here's how it works:

  • A reader tries to access your knowledge base.
  • If they are not already authenticated, the reader is redirected to your specified remote authentication landing page URL.
  • Your landing page authenticates the user in your system. 
  • After authentication by your system, an API call is made to KnowledgeOwl's remote authentication token request endpoint. If you are utilizing readers and reader groups, that information is passed during this token request. 
  • Once the login token is received by your system, the user is redirected to the KnowledgeOwl remote authentication endpoint with this single use token which completes the handshake and the reader gains access.

To enable remote authentication, you must be an editor on the knowledge base. To do so...

  1. Go to Settings > Security.
  2. Choose Remote Authentication.
  3. Input the URL of your authentication landing page (your Knowledge Base ID will be pre-populated below).
  4. Click Save.

To set up an API key, you must be an account administrator. To do so...

  1. Go to Your Account > API.
  2. Click on Add New API Key.

NOTE: We recommend creating a new API key that is restricted to GET calls for this type of authentication.

Example cURL Access Token Request


//basic authentication without reader information
curl -G -X GET -u {API KEY}:X https://app.knowledgeowl.com/api/head/remotelogin.json -d 'project={Knowledge Base ID}'

//authentication with reader information passed
curl -G -X GET -u {API KEY}:X https://app.knowledgeowl.com/api/head/remotelogin.json -d 'project={Knowledge Base ID}&reader[ssoid]={Unique Reader ID}&reader[username]={Reader Email or Name}'

//example response
{"valid":true,"data":[{"status":"success","token":"12345678"}]}

Reader fields can be found here https://support.knowledgeowl.com/help/reader-object


Example PHP Script to Run After Authentication

function remoteAuth()
{
    //shared vars
    /* if a non logged in user attempts to go directly to an article,
       our system will redirect them back to your landing page with the
       URL variable "r" that equals the original request URI. After
       authentication in your system, use this variable to send them
       to the originally requested page. */
    //grab the value of r
    $redirect 	= $this->_request->getParam('r'); //original request uri
    $callurl 	= "https://app.knowledgeowl.com/api/head/remotelogin.json"; //KnowledgeOwl auth endpoint
    $data 	= array(
                    'project' => '{KB ID}', //knowledge base ID
                );
    
    //optional data for creating / asserting reader object
    $data['reader'] = array(
                       'ssoid' => {READER UNIQUE ID} //optional, if not passed in username will be used as ssoid
                       'username' => {READER EMAIL OR NAME}, //required
                       //'groups' => {KNOWLEDGEOWL GROUP NAMES}, //optional - comma separated list ie - "Group1,Group2" 
                       //'first_name' => {READER FIRST NAME}, //optional
                       //'last_name' => {READER LAST NAME}, //optional
                       //'custom1' => {STRING}, //optional
                       //'custom2' => {STRING}, //optional
                       //'custom3' => {STRING}, //optional
                       //'custom4' => {STRING}, //optional
                       //'custom5' => {STRING}, //optional
                  );

    //set curl options
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $callurl);
    curl_setopt($ch, CURLOPT_USERPWD,'{API Key}':X);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
    curl_setopt($ch, CURLOPT_VERBOSE, 0);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    curl_setopt($ch, CURLOPT_NOPROGRESS, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    
    $buffer = curl_exec($ch);
        
    //verify return
    if(curl_errno($ch))
    {
        //handle curl errors
        print_r("Error: " . curl_error($ch));
    } 
    else 
    {
        //decode and verify
        $data = json_decode($buffer);
        curl_close($ch);

        //validate response
        if($data->valid && $data->data[0]->status == 'success')
        {
            //grab the token and redirect
            $token = $data->data[0]->token;

            $authData = array(
                            'n' => $token,
                            'r' => $redirect
            );
  
            header("Location: {Your KO Site URL}/help/remote-auth?" . http_build_query($authData));
            exit();
        }
        else
        {
            //handle api errors
        }
    }
}

Example vb.net logic to get the token and  open the default web browser passing the auth token 

This example uses the NewtonSoft package in dot net to deserialize the json response.  It was installed in Visual Studio using NuGet.

Imports System.Net
Imports Newtonsoft.Json
 
Private Sub GoToHelp()
 
        Dim request As HttpWebRequest
        Dim response As HttpWebResponse
        Dim strAUTH As String = "123abcd123:X"   ‘ replace 123abcd123 with your API key
        Dim strKBProjectKey As String = "99999"  ‘ replace 99999 with actual value
        Dim strDomainUsername As String = ""
 
‘Reader Groups to assign (optional)
        Dim strGroups As String = "Group 1,Group 2"
 
        strDomainUsername = Environment.UserDomainName & "\" & Environment.UserName
 
        If strDomainUsername <> "" Then
            request = DirectCast(HttpWebRequest.Create("https://app.knowledgeowl.com/api/head/remotelogin.json?project=" & strKBProjectKey & "&reader[ssoid]=" &
     strDomainUsername & "&reader[username]=" & strDomainUsername & "&reader[groups]=" & strGroups & "&reader[first_name]=" & strDomainUsername), HttpWebRequest)
 
            request.Method = "GET"
            request.ContentType = "application/json; charset=utf-8"
            request.Headers.Add("Authorization", "Basic " & Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(strAUTH)))
 
 
            response = DirectCast(request.GetResponse, HttpWebResponse)
 
            Dim myreader As New IO.StreamReader(response.GetResponseStream)
            Dim strResponse As String = myreader.ReadToEnd
            Dim strToken As String = ""
 
            Dim resp As AuthTokenResponseObj = JsonConvert.DeserializeObject(Of AuthTokenResponseObj)(strResponse)
 
            For Each atrObj As AuthData In resp.data
                strToken = atrObj.token
            Next
 
     myreader.Close()
           
     Dim strURl As String = "http://{yourknowledgeowldomain.com}/help/remote-auth?n=" & strToken
            System.Diagnostics.Process.Start(strURl)
 
           
        End If
 
    End Sub
 
    Public Class AuthTokenResponseObj
 
        Public Property valid As String
        Public Property data As List(Of AuthData)
 
    End Class
 
    Public Class AuthData
 
        Public Property status As String
        Public Property token As String
 
    End Class

If you have trouble with NewtonSoft json deserializer you can always parse the token out of the response manually i.e.; strToken = strResponse.Substring(strResponse.IndexOf("token") + 8, 8)

Javascript Example Script


//only need this if you do not already have jquery loaded
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script> 
 /**
 * This example assumes that you have already authenticated
 * the end user in your system
 */

 /* if a non logged in user attempts to go directly to an article,
 our system will redirect them back to your landing page with the
 URL variable "r" that equals the original request URI. After
 authentication in your system, use this variable to send them
 to the originally requested page. */
 //grab the value of r
 var redirect = "/help"; //default homepage
 var pageURL = window.location.search.substring(1);
 var urlVariables = pageURL.split('?');
 for (var i = 0; i < urlVariables.length; i++) 
 {
 var parameterName = urlVariables[i].split('=');
 if (parameterName[0] == 'r') 
 {
 redirect = parameterName[1];
 }
 }
 
 //static vars
 var token;
 var kbEndpoint	= "https://{YOUR KNOWLEDGEOWL KB URL}/help/remote-auth"; //where we will be sending them back -- eg https://yoursite.knowledgeowl.com/help/remote-auth
 var callURL 	= "https://app.knowledgeowl.com/api/head/remotelogin.jsonp"; //knowledgeowl auth endpoint
 var data 		= {
 _authbykey: '{API KEY}', //KnowledgeOwl API key
 project : '{KB ID}' //knowledge base ID
 }

 //request the token and redirect to desired page
 $.ajax({
 type: 'GET',
 url: callURL,
 dataType: 'jsonp',
 data: data
 }).success(function(data) {
 //check for valid response
 if(data && data.valid === true) {
 //grab the token
 token = data.data[0].token;
 
 kbEndpoint += "?n=" + token;
 kbEndpoint += "&r=" + redirect;
 
 //optional reader object creation / assertion
 kbEndpoint += "&reader[ssoid]=" + {READER UNIQUE ID}; //optional, if no ssoid is passed username will be used
 kbEndpoint += "&reader[username]=" + {READER NAME OR EMAIL}; //required
 kbEndpoint += "&reader[icon]=" + {READER PICTURE}; //optional
 kbEndpoint += "&reader[first_name]=" + {READER FIRST NAME}; //optional
 kbEndpoint += "&reader[last_name]=" + {READER LAST NAME}; //optional
 kbEndpoint += "&reader[groups]=" + {KNOWLEDGEOWL GROUP NAMES}; //optional, comma seperated list
 kbEndpoint += "&reader[custom1]=" + {STRING}; //optional
 kbEndpoint += "&reader[custom2]=" + {STRING}; //optional
 kbEndpoint += "&reader[custom3]=" + {STRING}; //optional
 kbEndpoint += "&reader[custom4]=" + {STRING}; //optional
 kbEndpoint += "&reader[custom5]=" + {STRING}; //optional

 //redirect user back with the aquired token and initial page request URI
 window.location.replace(kbEndpoint);
 } else {
 //handle empty return error
 }
 }).error(function(data){
 //handle ajax errors
 });
</script>