Аутентификация Oauth для доступа к REST API в переполнении стека

Я работаю над REST API в PHP (Codeigniter) и пытаюсь реализовать двухстороннюю аутентификацию oauth для доступа к API. Доступ к API должен осуществляться с использованием пары учетных данных, которые разработчик будет использовать в коде при интеграции нашего API с веб-сайтом или мобильным приложением (поэтому конечный пользователь не авторизует веб-сайт или мобильное приложение).

То, что я реализовал до сих пор, выглядит как 0-ножка. Я просто подписываю (HMAC_SHA1) запрос, используя секрет клиента и пустой маркер доступа. Но согласно некоторым ответам, которые я читал в другом месте, подписание запроса и проверка подписи — это все, что нужно сделать для реализации oauth 2-leg. https://www.quora.com/What-are-the-specific-differences-between-a-two-legged-and-three-legged-OAuth-provider-implementation )

Вот клиентская часть реализации в PHP, которая у меня есть на данный момент;

    <?php
// Just a demo for the client side implementation of oauth signed requests.

require_once ("oauth/oauth.php"); // Google oauth library

function send_request($method = '', $api_endpoint = '',$request_params = array()){
$consumer = new OAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
$sig_method = new OAuthSignatureMethod_HMAC_SHA1;

//use oauth lib to sign request
$req = OAuthRequest::from_consumer_and_token($consumer, null, $method, $api_endpoint, $request_params);
$sig_method = new OAuthSignatureMethod_HMAC_SHA1();
$req->sign_request($sig_method, $consumer, null);//note: double entry of token

if($method == 'GET'){
echo "<br />".$req->to_url();
$ch = curl_init($req->to_url());
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);

$result = curl_exec($ch);
$curl_info = curl_getinfo($ch);
//print_r($curl_info);
$error = curl_error($ch);
//print_r($error);
curl_close($ch);

return $result;

}elseif($method == 'POST'){

$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$api_endpoint);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HEADER,'Content-Type: application/x-www-form-urlencoded');
//echo "<br />".$req->to_url();
//echo "<br />Post data: ".$req->to_postdata();
//curl_setopt($ch, CURLOPT_POSTFIELDS, $req->to_postdata());
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($request_params));

$result = curl_exec($ch);
$curl_info = curl_getinfo($ch);
print_r($curl_info);
$error = curl_error($ch);
//print_r($error);
curl_close($ch);

return $result;
}
}

// API consumer key and secret
define('CONSUMER_KEY', 'd4hkilp1z0pqj7158y0j');
define('CONSUMER_SECRET', 'rqhzan3mdx7wov3gvh4u');

// Authorize
// Get products from odw api
$api_endpoint = 'http://testgapi.local/api/product/search'; // search/format/json , search/format/xml
$request_params = array();
$request_params['category_type'] = 'Tour';
$request_params['location'] = 'Las Vegas';
$request_params['start_date'] = '09/22/2015';
$request_params['end_date'] = '12/31/2015';

$result = send_request('GET', $api_endpoint, $request_params); // Call REST service with GET method
//$result = send_request('POST', $api_endpoint, $request_params);

print_r($result);
//echo $result;
?>

Проверка запроса на стороне сервера (в Codeigniter).
Контроллеры / API / product.php;

<?php
defined('BASEPATH') or exit('No direct script access allowed');

require APPPATH . '/libraries/REST_Controller.php';

class Product extends REST_Controller
{

var $valid_request;

function __construct()
{
// Construct the parent class
parent::__construct();

$this->load->library('Oauth_server');
}

public function search_get()
{
$this->valid_request = $this->oauth_server->validate_request();

if (!$this->valid_request)
{
$response = array(
'status' => "Failed",
'error_message' => "Access Denied.",
);
return $this->response($response, 201); // NO_CONTENT (204) being the HTTP response code
} else
{
// Do something
}
}
} // End of class
?>

библиотеки / Oauth_server.php;

<?php
require_once (APPPATH . "libraries/oauth/oauth.php"); // Google oauth library

class Oauth_server {

var $CI;
function __construct(){
// Nothing to do yet.
$this->CI = &get_instance();
}

function validate_request(){
//echo "<br />".
$consumer_key = !empty($_REQUEST['oauth_consumer_key'])? $_REQUEST['oauth_consumer_key'] : "";
// Use the oauth_consumer_key in the client request to find the secret in our system.
$secret = $this->get_consumer_secret($consumer_key);

$consumer = new OAuthConsumer($consumer_key, $secret);
$sig_method = new OAuthSignatureMethod_HMAC_SHA1;

//echo "<br />Method: ".
$method = $_SERVER['REQUEST_METHOD'];
//echo "<br />URI: ".
$uri = 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
$sig = $_REQUEST['oauth_signature'];
$req = new OAuthRequest($method, $uri);

//token is null because we're doing 2-leg
return $sig_method->check_signature( $req, $consumer, null, $sig );
}

function get_consumer_secret($consumer_key){
// Fetch the associated consumer secret from the db using the consumer key.
$query = $this->CI->db->query("SELECT consumer_secret FROM gapi_users WHERE consumer_key = ?", array($consumer_key));
$result = $query->row_array();

if(!empty($result)){
return $result['consumer_secret'];
}
else{
return false;
}
}
}
?>

Я мог бы также заставить запрос быть выполнен через https для дополнительной безопасности.

Предполагая, что я придерживаюсь oauth, я хотел бы знать, является ли моя текущая реализация вообще двухсторонней? Если это не так, будет ли двухногая, безусловно, более безопасным способом для моего сценария?

Буду очень признателен за любую помощь.

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …