Как использовать OAuth аутентификацию с REST API через CURL команды?

27 дек. 2015 г., 23:13:22
Просмотры: 71.7K
Голосов: 23

Я пытаюсь использовать WordPress Rest Api с аутентификацией для получения дополнительных данных через API. Я установил плагин OAuth, плагин rest-api и получил учетные данные API через WP-CLI.

Я разобрался, как получить доступ к данным без авторизации. Это работает:

// установка конечной точки
$domain = "http://localhost/wp-api";
$endpoint = $domain."/wp-json/wp/v2/posts/";


$curl = curl_init($endpoint);

curl_setopt_array($curl, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_URL            => $endpoint,
]);
$response = curl_exec($curl);
$decoderesponse = json_decode($response, true);

?>

<pre>
  <?php print_r($decoderesponse); ?>
</pre>

Но я не могу разобраться, как пройти аутентификацию с учетными данными. Вот моя попытка. Я не уверен, правильно ли использую "key" и "secret".

// Учетные данные OAuth из wp-cli
$ID = "4";
$Key = "l8XZD9lX89kb";
$Secret = "UUbcc8vjUkGjuDyvK1gRTts9sZp2N8k9tbIQaGjZ6SNOyR4d";

// установка конечной точки
$domain = "http://localhost/wp-api";
$endpoint = $domain."/wp-json/wp/v2/posts/1/revisions";

$headers[] = "key=$Key";
$headers[] = "secret=$Secret";

$curl = curl_init($endpoint);

curl_setopt_array($curl, [
  CURLOPT_HTTPHEADER     => $headers,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_URL            => $endpoint,
]);
$response = curl_exec($curl);
$decoderesponse = json_decode($response, true);

?>

<pre>
  <?php print_r($decoderesponse); ?>
</pre>

Вывод следующий:

Array
(
    [code] => rest_cannot_read
    [message] => Извините, вы не можете просматривать ревизии этой записи.
    [data] => Array
        (
            [status] => 401
        )
)

Как можно это исправить? Спасибо.

1
Комментарии

Не все так просто. Я пытался написать ответ, но он получился довольно длинным. Вы можете начать с чтения документации, особенно раздела Процесс авторизации. Также в этом посте есть отличный учебник.

cybmeta cybmeta
1 янв. 2016 г. 22:01:39
Все ответы на вопрос 4
6
16

Давайте разберёмся пошагово. Похоже, вы пытаетесь использовать OAuth только для аутентификации, но прежде чем это сделать, вам нужно получить Access Token, который будет использоваться для аутентификации при вызовах API.

Поскольку здесь используется OAuth версии 1, чтобы получить Access Token, необходимо выполнить следующие шаги:

  1. Сначала настройте приложение, выполните запрос к сайту для получения Request Token (временных учётных данных), используя Client ID и Secret для приложения.
  2. Затем выполните запрос к сайту для авторизации приложения с Request Token, полученным на первом шаге (этот шаг требует взаимодействия с пользователем, см. ниже).
  3. После завершения авторизации выполните запрос к сайту для получения Access Token (теперь, когда приложение авторизовано).

Я рекомендую использовать Postman для первых шагов, так как их нужно выполнить всего один раз. Postman также автоматически сгенерирует timestamp, nonce и oauth signature, поэтому если вы не используете библиотеку OAuth, Postman будет идеальным выбором. Как только у вас будет Access Token, вы сможете делать запросы через CURL без дополнительных библиотек.

https://www.getpostman.com/

Первый шаг (настройка приложения)

Установите плагин WP OAuth 1, активируйте его, затем перейдите в меню Пользователи > Приложения. Добавьте новое приложение, укажите имя и описание. Для callback укажите URL для перенаправления пользователя после авторизации или используйте oop для Out-of-Band потока, который перенаправит на внутреннюю страницу с отображением верификационного токена (вместо перенаправления).

https://github.com/WP-API/OAuth1/blob/master/docs/basics/Registering.md

Для перехода ко второму шагу необходимо выполнить запрос к вашему сайту, используя Client ID и Client Secret из созданного приложения, чтобы получить временные учётные данные (Request Token).

Откройте Postman, создайте новый запрос на http://website.com/oauth1/request, перейдите на вкладку Authorization, выберите OAuth 1.0 из выпадающего списка, введите Client Key, Client Secret, установите метод подписи HMAC-SHA1, включите "add params to header", encode oauth signature, затем нажмите Update Request.

Postman OAuth1 Request

Postman автоматически сгенерирует подпись, nonce и timestamp, добавив их в заголовки (их можно просмотреть на вкладке Headers).

Нажмите Send, и вы должны получить ответ, содержащий oauth_token и oauth_token_secret: Postman OAuth1 Request Response

Эти значения будут использоваться на следующем шаге для авторизации приложения под вашей учётной записью WordPress.

Второй шаг (авторизация приложения)

Шаг авторизации нужно выполнить только один раз. Этот шаг требует взаимодействия с пользователем и знаком всем, кто когда-либо авторизовывал приложения. Он необходим, потому что вы используете OAuth1, и приложение должно быть связано с учётной записью WordPress. Представьте, как сайты предлагают войти через Facebook — вас перенаправляют на Facebook, где вы входите и нажимаете "Авторизовать". То же самое нужно сделать, но через ваш сайт WordPress.

Я рекомендую использовать веб-браузер для этого шага, так как вы можете легко задать переменные в URL, и это отобразит страницу "Авторизовать" для подтверждения приложения.

Откройте браузер и введите URL вашего сайта, например: http://website.com/oauth1/authorize

Теперь добавьте к этому URL параметры oauth_consumer_key (Client ID), oauth_token и oauth_token_secret (из предыдущего шага). В моём примере полный URL выглядит так:

http://website.com/oauth1/authorize?oauth_consumer_key=TUPFNj1ZTd8u&oauth_token=J98cN81p01aqSdFd9rjkHZWI&oauth_token_secret=RkrMhw8YzXQljyh99BrNHmP7phryUvZgVObpmJtos3QExG1O

OAuth1 Authorize Application

После нажатия на "Авторизовать" вы увидите экран с верификационным токеном. В моём примере возвращённый токен — E0JnxjjYxc32fMr2AF0uWsZm.

Третий шаг (получение Access Token)

Теперь, когда приложение авторизовано, нужно выполнить последний запрос для получения Access Token, который будет использоваться для всех вызовов API. Как и в первом шаге, я буду использовать Postman (так как требуется подпись HMAC-SHA1), что значительно упрощает процесс.

Снова откройте Postman и измените URL на http://website.com/oauth1/access.

Убедитесь, что добавлены Token и Token Secret (значения из первого шага), затем нажмите Params, чтобы отобразить поля под URL. Слева введите oauth_verifier, а справа — код из второго шага, Verification Token.

Postman OAuth1 Access Step

Обязательно нажмите Update Request, затем Send, и вы получите ответ с oauth_token и oauth_token_secret... это именно то, что нужно для вызовов API! Отбросьте значения из первого шага и сохраните эти в коде или в безопасном месте.

Postman OAuth1 Access Response

Теперь вы можете делать API-запросы к вашему сайту, передавая в заголовках полученные токен и секрет.

Вы можете передавать их разными способами: через заголовок Authorization, в GET-параметрах или POST (если закодировано как application/x-www-form-urlencoded). Учтите, что вы ДОЛЖНЫ передавать подпись, timestamp и nonce. Я не осознавал, насколько длинным получится этот ответ, поэтому завтра добавлю примеры кода.

Настоятельно рекомендую установить Rest API log, чтобы просматривать журнал API-вызовов и анализировать отправленные и полученные данные. Это очень поможет в отладке.

https://github.com/petenelson/wp-rest-api-log

20 сент. 2016 г. 05:46:53
Комментарии

Я знаю, что есть много туториалов с Postman и подобными инструментами, но я не могу найти ни одного руководства, которое бы полностью описывало процесс с использованием функций CURL, то есть на чистом PHP-коде. Именно это мне и нужно.

James Vu James Vu
20 сент. 2016 г. 11:30:50

@Dan9 Честно говоря, это не совсем возможно... по крайней мере, не с OAuth1, в основном потому, что вам необходимо АВТОРИЗОВАТЬ приложение под учетной записью пользователя. Все остальные шаги легко выполнить с помощью CURL, проблема заключается в использовании CURL для входа в систему как пользователь WordPress (что означает необходимость хранить учетные данные в вашем PHP-файле, что НЕ является хорошей идеей), А ТАКЖЕ для авторизации приложения. Вы могли бы модифицировать код OAuth1, но, честно говоря, если вы хотите использовать CURL для ВСЕГО... вы мыслите неправильно и вам следует придумать другое решение или метод.

sMyles sMyles
20 сент. 2016 г. 18:01:12

@Dan9 Для того, что вы пытаетесь сделать, вам следует использовать OAuth2 сервер вместо OAuth1, в основном потому, что OAuth2 имеет новые функции, включая тип предоставления Client Credential, который позволяет избежать необходимости проходить все эти шаги http://bshaffer.github.io/oauth2-server-php-docs/grant-types/client-credentials/

sMyles sMyles
20 сент. 2016 г. 18:14:59

@Dan9 если ты твёрдо решил получить помощь по реализации этого через OAuth1 с использованием CURL, я думаю, что это возможно с несколькими хакерами кода, но, как я уже упоминал, это означает, что тебе придётся сохранять ИМЯ ПОЛЬЗОВАТЕЛЯ и ПАРОЛЬ пользователя в PHP-файле. Если тебя это устраивает, дай знать, и я напишу руководство по реализации с помощью CURL, не хочу тратить время на написание туториала, если ты собираешься использовать OAuth2 или больше не нуждаешься в этом

sMyles sMyles
20 сент. 2016 г. 18:16:21

@Dan9 ну... в этом-то и дело... если ты собираешься использовать OAuth1, тебе придётся привязать учётную запись пользователя WordPress. По сути, считай Access Token как API-ключ... этот "API-ключ" должен быть связан с учётной записью пользователя... теперь, будешь ли ты использовать какой-то стандартный аккаунт, который ты настроил, решать тебе... но в любом случае при использовании OAuth1 он ДОЛЖЕН быть связан с учётной записью пользователя, отсюда и длительный процесс получения токена доступа.

sMyles sMyles
20 сент. 2016 г. 18:57:53

Вот почему я рекомендовал использовать OAuth2, потому что ты можешь использовать тип предоставления client credentials, и тогда ты просто делаешь CURL-запрос с этими учётными данными, и он возвращает токен доступа (не нужно проходить длительный процесс авторизации). Вот все типы предоставления OAuth2: http://bshaffer.github.io/oauth2-server-php-docs/overview/grant-types/

sMyles sMyles
20 сент. 2016 г. 19:00:01
Показать остальные 1 комментариев
2

Добавляю этот ответ, чтобы помочь вам разобраться, как это сделать. Как уже упоминалось в моих комментариях, если вы используете OAuth1, вы ДОЛЖНЫ связать его с учетной записью пользователя — обойти это невозможно.

Сначала вам нужно использовать CURL для входа на сайт с именем пользователя и паролем WordPress, сохранить cookie, чтобы использовать её в запросе CURL к OAuth (убедитесь, что ваш CURL-запрос включает cookie):

https://stackoverflow.com/questions/724107/wordpress-autologin-using-curl-or-fsockopen-in-php

Затем сделайте запрос к OAuth с помощью CURL, используя Client ID и Client Secret, чтобы получить временный oauth token и secret (Request Token).

Для этого запроса (и запроса на получение access token) необходимо правильно настроить CURL. Смотрите код и ссылки в конце этого ответа.

После получения временного oauth token и secret (Request Token) сделайте CURL POST-запрос на URL вашего сайта:

http://website.com/oauth1/authorize

Затем вам нужно извлечь все значения из возвращённого HTML-кода страницы авторизации и отправить свой POST на URL формы.

https://stackoverflow.com/questions/35363815/how-to-get-a-value-input-from-html-returned-of-curl

В частности, эти данные должны быть включены в POST для завершения "авторизации" при отправке на http://domain.com/wp-login.php?action=oauth1_authorize:

  • _wpnonce — Это nonce-значение для формы, оно ДОЛЖНО быть извлечено из HTML-ввода и отправлено с POST.

    consumer — Это скрытое поле в HTML (это ссылка на ID записи, поэтому его нужно извлечь из HTML-ввода).

    oauth_token — Это скрытое поле в HTML (но у вас оно уже должно быть).

    wp-submit — Это должно быть установлено в значение authorize.

Пример HTML, сгенерированного для страницы авторизации:

<form name="oauth1_authorize_form" id="oauth1_authorize_form" action="http://website.com/wp-login.php?action=oauth1_authorize" method="post">

    <h2 class="login-title">Подключение My Auth</h2>

    <div class="login-info">
        <p>Привет, <strong>admin</strong>,<br/> "My OAuth Demo" хочет подключиться к Example Site.</p>

    </div>

    <input type="hidden" name="consumer" value="5428" /><input type="hidden" name="oauth_token" value="i1scugFXyPENniCP4kABKtGb" /><input type="hidden" id="_wpnonce" name="_wpnonce" value="ca9b267b4f" /><input type="hidden" name="_wp_http_referer" value="/wp-login.php?action=oauth1_authorize&amp;oauth_consumer_key=TUPFNj1ZTd8u&amp;oauth_token=i1scugFXyPENniCP4kABKtGb&amp;oauth_token_secret=gzqW47pHG0tilFm9WT7lUgLoqN2YqS6tFFjUEiQoMgcmG2ic" />   <p class="submit">
        <button type="submit" name="wp-submit" value="authorize" class="button button-primary button-large">Авторизовать</button>
        <button type="submit" name="wp-submit" value="cancel" class="button button-large">Отмена</button>
    </p>

</form>

После отправки POST со всеми этими значениями/данными возвращается HTML с кодом авторизации (его нужно извлечь из блока <code>):

<div id="login">
    <h1><a href="https://wordpress.org/" title="Работает на WordPress" tabindex="-1">Example Site</a></h1>
    <p>Ваш токен верификации: <code>yGOYFpyawe8iZmmcizqVIw3f</code></p> <p id="backtoblog"><a href="http://website.com/">&larr; Вернуться на Example Site</a></p>
</div>

Получив verification token, вы можете сделать запрос на /oauth1/access, используя verification token, oauth token и oauth token secret. Verification token должен быть указан в POST-данных как oauth_verifier.

Это вернёт ваш новый и постоянный Access Token, и ВУАЛЯ!

Пример кода CURL

Ниже приведён пример кода для CURL-запроса, где самое важное — генерация oauth_signature:

https://oauth1.wp-api.org/docs/basics/Signing.html

function buildBaseString($baseURI, $method, $params){
    $r = array();
    ksort($params);
    foreach($params as $key=>$value){
        $r[] = "$key=" . rawurlencode($value);
    }

    return $method."&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));
}

function buildAuthorizationHeader($oauth){
    $r = 'Authorization: OAuth ';
    $values = array();
    foreach($oauth as $key=>$value)
        $values[] = "$key=\"" . rawurlencode($value) . "\"";

    $r .= implode(', ', $values);
    return $r;
}

// Добавьте request, authorize и т.д. в конец URL в зависимости от запроса
$url = "http://domain.com/oauth/";

$consumer_key = "CLIENT ID HERE";
$consumer_secret = "CLIENT SECRET HERE";

$oauth = array( 'oauth_consumer_key' => $consumer_key,
                'oauth_nonce' => time(),
                'oauth_signature_method' => 'HMAC-SHA1',
                'oauth_callback' => 'oob',
                'oauth_timestamp' => time(),
                'oauth_version' => '1.0');

$base_info = buildBaseString($url, 'GET', $oauth);
$composite_key = rawurlencode($consumer_secret) . '&' . rawurlencode($oauth_access_token_secret);
$oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
$oauth['oauth_signature'] = $oauth_signature;


$header = array(buildAuthorizationHeader($oauth), 'Expect:');
$options = array( CURLOPT_HTTPHEADER => $header,
                  CURLOPT_HEADER => false,
                  CURLOPT_URL => $url,
                  CURLOPT_RETURNTRANSFER => true,
                  CURLOPT_SSL_VERIFYPEER => false);

$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);

$return_data = json_decode($json);

print_r($return_data);

Этот сайт подробно объясняет, как кодировать подпись OAuth и отправлять её через CURL (рекомендую прочитать всю страницу):
https://hannah.wf/twitter-oauth-simple-curl-requests-for-your-own-data/

Дополнительные ресурсы по генерации подписи OAuth1:
https://stackoverflow.com/questions/24613277/oauth-signature-generation-using-hmac-sha1

Другие ресурсы:
http://collaboradev.com/2011/04/01/twitter-oauth-php-tutorial/

20 сент. 2016 г. 20:47:25
Комментарии

Как я могу получить Client ID и Client secret и связать их с действительным пользователем? В настоящее время только администраторы могут создавать новое приложение, и это делается только через панель администратора. Кстати, я попытался сгенерировать oauth_signature, как вы сказали, но, почему-то, ответ всегда json_oauth1_signature_mismatch.

James Vu James Vu
21 сент. 2016 г. 06:49:14

@Dan9 да, это верно, администраторы должны создавать приложение, иначе это создало бы огромную проблему безопасности, позволяя создавать приложения анонимным пользователям. Вот несколько сайтов по теме подписи: http://wordpress.stackexchange.com/questions/185511/oauth-signature-does-not-match https://github.com/WP-API/OAuth1/issues/34 https://github.com/WP-API/OAuth1/issues/27

sMyles sMyles
21 сент. 2016 г. 20:55:22
0

Я знаю, что немного запоздал с этим вопросом, но можно ли использовать wp_remote_get и _post?

Я получаю и отправляю контент с помощью своего WordPress, используя их:

Вот общая идея из WordPress Codex:

$response = wp_remote_post( $url, array(
    'body'    => $data,
    'httpversion' => '1.0',
    'sslverify' => false,
    'headers' => array(
        'Authorization' => 'Basic ' . base64_encode( $username . ':' . $password ),
    ),
) );

Вот более конкретный пример:

$url='http://WWW.EXAMPLE HERE.';
$response = wp_remote_post( $url, array(
    'method' => 'POST',
    'timeout' => 45,
    'redirection' => 5,
    'httpversion' => '1.0', //необходимо для получения ответа
    'blocking' => true,
    'headers' => array('Authorization' => 'Basic ' . base64_encode( 'MY TOKENID' . ':' . '' )),
    'body' => $body // в виде массива
    'cookies' => array()
    )
);

if ( is_wp_error( $response ) ) {
   $error_message = $response->get_error_message();
   echo "Что-то пошло не так: $error_message";
} else {
 //  echo 'Ответ:<pre>';
 //  print_r( $response );
 //    echo '</pre>'; 
$responseBody = json_decode($response['body'],true);
echo $responseBody['message'];

    }
    }
}

Хитрость заключается в кодировании имени пользователя и пароля. В зависимости от API, имя пользователя и пароль могут быть либо пустыми, либо вашими токенами.

Например, в моём конкретном примере выше заголовки были такими:

'headers' => array('Authorization' => 'Basic ' . base64_encode( 'MYTOKENID' . ':' . '' ))

и я оставил пароль пустым. Но это зависит от API-системы, которую вы используете.

20 сент. 2016 г. 23:44:26
0

Обновление: Судя по прочитанному, вам нужно выполнить несколько запросов cURL, чтобы получить access_token, который затем используется для выполнения запроса

  • Получение временных учетных данных: Клиент получает набор временных учетных данных от сервера.
  • Авторизация: Пользователь "авторизует" запрос токена для доступа к своему аккаунту.
  • Обмен токена: Клиент обменивает краткосрочные временные учетные данные на долгосрочный токен.

oauth1 серверный поток

15 апр. 2016 г. 15:37:22