2015-01-07 2 views
1

Я пытаюсь построить заголовок авторизации для Docebo, но я не могу заставить его работать, поскольку документация недостаточно описательна, и их пример кода (только пример кода) очень запутан.Docebo - построение заголовка авторизации

Это в основном все Docebo documentation:

enter image description here

То, что я пытаюсь сделать, чтобы получить список всех пользователей.

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 я получаю "{ "успех": ложь, "сообщение": "Значение заголовка Authorization не соответствует", "код": 104 }".

Было бы здорово получить отклик на этот или понятный перевод их документации по API.

ответ

3

После долгой борьбы (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' 
)); 
+0

Привет, Якуб, я также борюсь с API Docebo. Могу ли я узнать, являются ли параметры «abc»: «1», def: «2»}, а ваш ключ «JUSTAKEY», токен маркера SHA1 должен быть SHA1 («1,2, JUSTAKEY») или SHA1 («abc , 1, Защита, 2, JUSTAKEY ")? Заранее спасибо. – qcam

+1

Эй, @huynhquancam, это должно быть «String.Format (« {0}, {1} », String.Join (", ", listKeyValuePair.Select (n => n.Value)), apiSecret);" Это означает значения сначала, а затем ключ. В вашем примере это будет «1,2, YOURSERCRET». –

+0

привет, Якуб, спасибо. Я действительно пытался реализовать его в Ruby. :) Теперь можно подключиться. – qcam

0

Я нашел следующее решение для того, чтобы ссылаться на интерфейсы API Docebo, используя аутентификацию oauth2; он также не зарегистрирован на сайте Docebo. Этот пример C# вызывает API пользователя/счетчика; его можно легко адаптировать к другим API. Он использует 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; 
    } 

} 
+0

Я пытаюсь это сделать сейчас, хотя я просто использовал Fiddler для отправки запроса для меня, но я получаю '{" error ":" unsupported_grant_type "," error_description ":" Пароль типа гранта "не поддерживается"} 'каждый раз, хотя в Docebo у меня есть учетные данные владельца ресурса, проверенные в моем приложении oauth2. Есть идеи? Их документы не очень полезны. – lhan

+0

Единственное, на что я не был на 100% уверен, был значение URL-адреса портала, которое, как я полагаю, является «https: // .docebosaas.com /»? Я предполагаю, что это правильно, так как я получил ошибку, связанную с oauth, но не смог найти что-либо в Интернете, чтобы подтвердить это. – lhan

Смежные вопросы