Docebo - 构建授权 header

Docebo - constructing authorisation header

我一直在尝试为 Docebo 构建授权 header,但我无法让它工作,因为文档描述不够,而且他们的代码示例(仅代码示例)非常混乱。

基本就这些了Docebo documentation:

我想做的是获取所有用户的列表。

public JsonResult GetCoursesCount()
        {
            const string apiKey = "[API KEY FROM MY DOCEBO PORTAL]";
            const string apiSecret = "[API SECRET FROM MY DOCEBO PORTAL]";
            const string doceboUrl = "[URL OF MY DOCEBO PORTAL]";

            using (var httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                var toEncodeWithSha1 = String.Format("{0},{1}", String.Join(",", new[] {"0", "null"}), apiSecret); // should the values be values or parameters??

                var code = GetSHA1HashData(toEncodeWithSha1);

                var toEncodeWithBase64 = String.Format("{0}:{1}", apiKey, code);

                code = Base64Encode(toEncodeWithBase64);

                var xAuthorisation = String.Format("Docebo {0}", code);

                httpClient.DefaultRequestHeaders.Add("X-Authorization", xAuthorisation);

                var stringContent = JsonConvert.SerializeObject("{ \"from\": \"0\", \"count\": \"null\" }");

                var userResult = httpClient.PostAsync(String.Format("{0}/api/user/listUsers", doceboUrl),
                    new StringContent(stringContent)).Result;

                var userData = JsonConvert.DeserializeObject<dynamic>(userResult.Content.ReadAsStringAsync().Result);

                return new JsonResult { Data = userData, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            }
        }

private string GetSHA1HashData(string data)
        {
            //create new instance of md5
            var sha1 = SHA1.Create();

            //convert the input text to array of bytes
            byte[] hashData = sha1.ComputeHash(Encoding.Default.GetBytes(data));

            //create new instance of StringBuilder to save hashed data
            var returnValue = new StringBuilder();

            //loop for each byte and add it to StringBuilder
            foreach (byte @byte in hashData)
            {
                returnValue.Append(@byte.ToString());
            }

            // return hexadecimal string
            return returnValue.ToString();
        }

        private string Base64Encode(string plainText)
        {
            var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
            return Convert.ToBase64String(plainTextBytes);
        }

每当我联系他们 API 时,我都会收到“{ "success":错误, "message": "Authorization header value doesn't match", "code": 104 }".

如果能得到对此的反馈或他们 API 文档的可理解翻译,那就太好了。

经过长时间的奋斗(8 小时)我解决了正确的代码。

public JsonResult GetCoursesCount()
        {
            const string apiKey = "[API KEY FROM MY DOCEBO PORTAL]";
            const string apiSecret = "[API SECRET FROM MY DOCEBO PORTAL]";
            const string doceboUrl = "[URL OF MY DOCEBO PORTAL]";

            using (var httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                var listKeyValuePair = new List<KeyValuePair<string,string>>
                {
                    new KeyValuePair<string, string>("from", "0"), 
                    new KeyValuePair<string, string>("count", "10")
                };

                var toEncodeWithSha1 = String.Format("{0},{1}", String.Join(",", listKeyValuePair.Select(n => n.Value)), apiSecret); // should the values be values or parameters??

                var code = Sha1Hash(toEncodeWithSha1);

                var toEncodeWithBase64 = String.Format("{0}:{1}", apiKey, code);

                code = Base64Encode(toEncodeWithBase64);

                var xAuthorisation = String.Format("Docebo {0}", code);

                httpClient.DefaultRequestHeaders.Add("X-Authorization", xAuthorisation);

                var content = new FormUrlEncodedContent(listKeyValuePair);

                var userResult = httpClient.PostAsync(String.Format("{0}/api/user/listUsers", doceboUrl),
                    content).Result;

                var responseByteArray = userResult.Content.ReadAsByteArrayAsync().Result;

                var convertedResult = Encoding.UTF8.GetString(responseByteArray, 0, responseByteArray.Length);

                var userData = JsonConvert.DeserializeObject<UserListResult>(convertedResult);

                return new JsonResult { Data = userData, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
            }
        }

        public class UserListResult
        {
            public List<dynamic> Users { get; set; }
            public bool Success { get; set; }
        }

        private string Sha1Hash(string input)
        {
            return string.Join(string.Empty, SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(input)).Select(x => x.ToString("x2")));
        }

        private string Base64Encode(string plainText)
        {
            var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
            return Convert.ToBase64String(plainTextBytes);
        }

包括PHP例子供参考:

<?php
/**
* DOCEBO, e-learning SAAS
*
* @link http://www.docebo.com/
* @copyright Copyright &copy; 2004-2013 Docebo
*/
class Api {
static public $url = 'yoursite.docebosaas.com';
static public $key = 'your_key_from_api_app';
static public $secret_key = 'your_secret_from_api_app';
static public $sso = 'your_toekn_from_api_app';
static public function getHash($params) {
$res =array('sha1'=>'', 'x_auth'=>'');
$res['sha1']=sha1(implode(',', $params) . ',' . self::$secret_key);
$res['x_auth']=base64_encode(self::$key . ':' . $res['sha1']);
return $res;
}
static private function getDefaultHeader($x_auth) {
return array(
"Host: " . self::$url,
"Content-Type: multipart/form-data",
'X-Authorization: Docebo '.$x_auth,
);
}
static public function call($action, $data_params) {
$curl = curl_init();
$hash_info = self::getHash($data_params);
$http_header =self::getDefaultHeader($hash_info['x_auth']);
$opt = array(
CURLOPT_URL=>self::$url . '/api/' . $action,
CURLOPT_RETURNTRANSFER=>1,
CURLOPT_HTTPHEADER=>$http_header,
CURLOPT_POST=>1,
CURLOPT_POSTFIELDS=>$data_params,
CURLOPT_CONNECTTIMEOUT=>5, // Timeout to 5 seconds
);
curl_setopt_array($curl, $opt);
// $output contains the output string
$output = curl_exec($curl);
// it closes the session
curl_close($curl);
return $output;}
static public function sso($user) {
$time = time();
$token = md5($user.','.$time.','.self::$sso);
return 'http://' . self::$url .
'/doceboLms/index.php?modname=login&op=confirm&login_user=' . strtolower($user) . '&time=' .
$time . '&token=' . $token;
}
}
// sample call
$res = API::call('user/checkUsername', array(
'userid' => 'username_to_chek'
));

我找到了以下解决方案,以便使用 OAUTH2 身份验证调用 Docebo APIs;它也没有记录在 Docebo 网站上。此 C# 示例调用 "user/count" API;它可以很容易地适应其他 APIs。它使用 Json.Net 来解析答案。

using Newtonsoft.Json; //see http://www.newtonsoft.com/json
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace DoceboClient
{
    class CallDoceboAPI
    {
        static void Main(string[] args)
        {
            string url = "https://YOUR_DOCEBO_PORTAL_URL"; //https is mandatory!
            System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();

            //Obtain token
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + "/oauth2/token");
            string postParametersForToken = "client_id=YOUR_DOCEBO_CLIENT_ID&client_secret=YOUR_DOCEBO_CLIENT_SECRET&grant_type=password&username=YOUR_DOCEBO_USERNAME&password=YOUR_DOCEBO_PASSWORD&scope=api";
            request.ContentType = @"application/x-www-form-urlencoded";
            Byte[] byteArray = encoding.GetBytes(postParametersForToken);
            request.ContentLength = byteArray.Length;
            request.Method = "POST";
            using (Stream dataStream = request.GetRequestStream())
            {
                dataStream.Write(byteArray, 0, byteArray.Length);
            }
            string token = "";
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                using (Stream responseStream = response.GetResponseStream())
                {
                    StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
                    string result = reader.ReadToEnd();
                    DoceboToken dt = JsonConvert.DeserializeObject<DoceboToken>(result);
                    token = dt.access_token;
                }
            }

            //invoke API, e.g. "/user/count" 
            string api = "/api/user/count";
            string postParametersForAPI = "status=all"; //if more than 1 parameter, concat them as &parmName=parmValue
            request = (HttpWebRequest)WebRequest.Create(url + api);
            byteArray = encoding.GetBytes(postParametersForAPI + "&access_token=" + token);
            request.ContentLength = byteArray.Length;
            request.ContentType = @"application/x-www-form-urlencoded";
            request.Method = "POST";
            using (Stream dataStream = request.GetRequestStream())
            {
                dataStream.Write(byteArray, 0, byteArray.Length);
            }
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                using (Stream responseStream = response.GetResponseStream())
                {
                    StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
                    string result = reader.ReadToEnd();
                    UserCountResponse ucr = JsonConvert.DeserializeObject<UserCountResponse>(result);
                    //get the result
                    int count = ucr.count;
                }
            }
        }
    }

    class UserCountResponse
    {
        public bool success;
        public int count;
    }

    class DoceboToken
    {
        public string access_token;
    }

}