Come utilizzare l'autenticazione OAuth con le API REST tramite comandi CURL?

27 dic 2015, 23:13:22
Visualizzazioni: 71.7K
Voti: 23

Sto cercando di utilizzare la WordPress REST API con autenticazione per ottenere più dati dall'API. Ho installato il plugin OAuth, il plugin rest-api e ho ottenuto le credenziali API da WP-CLI.

Ho capito come accedere ai dati senza autorizzazione. Questo funziona:

// imposta il nostro endpoint
$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>

Ma non riesco a capire come autenticarmi con le credenziali. Questo è il mio tentativo. Non sono sicuro se "key" e "secret" siano corretti.

// Credenziali OAuth da wp-cli
$ID = "4";
$Key = "l8XZD9lX89kb";
$Secret = "UUbcc8vjUkGjuDyvK1gRTts9sZp2N8k9tbIQaGjZ6SNOyR4d";

// imposta il nostro endpoint
$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>

L'output è

Array
(
    [code] => rest_cannot_read
    [message] => Spiacenti, non puoi visualizzare le revisioni di questo post.
    [data] => Array
        (
            [status] => 401
        )
)

Come posso farlo funzionare? Grazie.

1
Commenti

Le cose non sono così semplici. Ho cercato di scrivere una risposta ma è piuttosto lunga. Potresti iniziare leggendo la documentazione, in particolare Il Flusso di Autorizzazione. Questo post contiene anche un ottimo tutorial.

cybmeta cybmeta
1 gen 2016 22:01:39
Tutte le risposte alla domanda 4
6
16

Procediamo passo dopo passo qui. Sembra che tu stia cercando di utilizzare OAuth solo per l'autenticazione, ma prima di poterlo fare è necessario ottenere il Token di Accesso che verrà utilizzato per autenticarti quando effettuerai le chiamate API.

Poiché si utilizza OAuth versione 1, per ottenere il Token di Accesso devi seguire questi passaggi:

  1. Primo, configura un'applicazione, effettua una chiamata al sito per ottenere il Token di Richiesta (credenziali temporanee) utilizzando l'ID Client e il Secret dell'applicazione
  2. Secondo, effettua una chiamata al sito per Autorizzare l'applicazione con il Token di Richiesta ottenuto nel primo passaggio (interfaccia utente, vedi sotto).
  3. Terzo, dopo che l'autorizzazione è stata completata, effettua una chiamata al sito per ottenere il Token di Accesso (ora che l'applicazione è stata autorizzata)

Consiglio di utilizzare Postman per i primi passaggi, poiché devono essere completati solo una volta. Postman gestirà anche la generazione del timestamp, nonce e oauth signature, quindi se non stai utilizzando una libreria OAuth, dovresti assolutamente usare Postman. Una volta ottenuto il Token di Accesso puoi effettuare le chiamate via CURL senza alcuna libreria.

https://www.getpostman.com/

Primo Passo (configurazione applicazione)

Installa il plugin WP OAuth 1, attivalo, poi vai alla voce di menu Utenti > Applicazioni. Aggiungi una nuova applicazione, compila nome e descrizione. Per il callback inserisci l'URL a cui reindirizzare l'utente (dopo l'autorizzazione), oppure oop per il flusso Out-of-Band che reindirizzerà a una pagina interna che mostra il token di verifica (invece di reindirizzare).

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

Per procedere al secondo passaggio, è necessario effettuare una chiamata al tuo sito, utilizzando l'ID Client e il Secret Client dell'applicazione creata, per ottenere le credenziali temporanee (Token di Richiesta).

Apri Postman, crea una nuova chiamata a http://website.com/oauth1/request, clicca sulla scheda Autorizzazione, seleziona OAuth 1.0 dal menu a discesa, inserisci la Client Key, Client Secret, imposta il metodo di firma su HMAC-SHA1, abilita l'aggiunta dei parametri all'header, codifica la firma oauth, poi clicca su Aggiorna Richiesta

Postman OAuth1 Richiesta

Postman genererà automaticamente la firma, il nonce e il timestamp per te, e li aggiungerà all'header (puoi visualizzarli sotto la scheda Headers).

Clicca Invia e dovresti ottenere una risposta che include oauth_token e oauth_token_secret: Risposta Postman OAuth1 Richiesta

Questi valori verranno utilizzati nel prossimo passaggio per autorizzare l'applicazione sotto il tuo account utente WordPress.

Secondo Passo (autorizzazione applicazione)

Il passaggio di autorizzazione deve essere completato solo una volta, questo passaggio è rivolto all'utente, ed è quello che tutti conoscono. Questo passaggio è obbligatorio perché stai utilizzando OAuth1, e l'applicazione deve essere associata a un account utente WordPress. Pensa a quando un sito ti permette di accedere con Facebook... ti reindirizzano a Facebook dove effettui il login e clicchi "Autorizza"... questo deve essere fatto, ma attraverso il tuo sito WordPress.

Consiglio di utilizzare il tuo browser web per questo passaggio, poiché puoi facilmente impostare le variabili nell'URL, e questo mostra la pagina "Autorizza" per autorizzare l'applicazione.

Apri il tuo browser web e digita l'URL del tuo sito, in questo modo: http://website.com/oauth1/authorize

Ora aggiungi a questo URL, oauth_consumer_key (ID Client), oauth_token e oauth_token_secret (dal passaggio precedente). Nel mio esempio questo è l'URL completo:

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

Autorizzazione Applicazione OAuth1

Una volta cliccato su Autorizza, otterrai un'altra schermata con il token di verifica. Nel mio esempio questo è il token di verifica restituito E0JnxjjYxc32fMr2AF0uWsZm

Terzo Passo (ottenere token di accesso)

Ora che abbiamo autorizzato l'applicazione, dobbiamo effettuare un'ultima chiamata per ottenere il Token di Autorizzazione che verrà utilizzato per effettuare tutte le tue chiamate API. Come nel primo passaggio utilizzerò Postman (perché la firma deve essere HMAC-SHA1), e rende questi passaggi 100 volte più semplici da completare.

Apri nuovamente Postman e cambia l'URL in http://website.com/oauth1/access

Assicurati di aggiungere il Token e il Token Secret (valori ottenuti nel primo passaggio), poi clicca su Params per mostrare le caselle sotto l'URL. A sinistra digita oauth_verifier e a destra inserisci il codice ottenuto nel secondo passaggio, il Token di Verifica

Passaggio Accesso OAuth1 in Postman

Assicurati di cliccare su Aggiorna Richiesta, poi clicca su Invia, e dovresti ottenere una risposta con oauth_token e oauth_token_secret... questo è ciò che ti serve per effettuare le tue chiamate API! Scarta quelli originali ottenuti nel passaggio 1, salva questi nel tuo codice o in un posto sicuro.

Risposta Accesso OAuth1 in Postman

Puoi quindi effettuare una chiamata API al tuo sito, impostando gli header con il token e il token secret restituiti.

Puoi passarli in diversi modi, tramite header di Autorizzazione, nei parametri GET, o POST (se codificato come application/x-www-form-urlencoded). Tieni presente che DEVI passare la firma, il timestamp e il nonce. Non mi ero reso conto di quanto tempo mi avrebbe richiesto questa risposta, quindi aggiornerò domani con un esempio su come farlo con il tuo codice.

Consiglio vivamente di installare Rest API log per poter visualizzare il log delle chiamate API, e vedere cosa è stato inviato, restituito, ecc. Questo aiuterà tantissimo nel debug.

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

20 set 2016 05:46:53
Commenti

Lo so, ci sono molti tutorial con Postman o strumenti simili ma non riesco a trovare tutorial che mostrino l'intero processo con le funzionalità CURL, intendo codice PHP puro. Questo è quello che voglio.

James Vu James Vu
20 set 2016 11:30:50

@Dan9 Ad essere sinceri non è davvero possibile... almeno non con OAuth1, principalmente perché devi AUTORIZZARE l'applicazione sotto un account utente. Tutti gli altri passaggi sono facili da fare con CURL, il problema è usare CURL per accedere come utente WordPress (il che significa che devi memorizzare le credenziali nel tuo file PHP e NON è una buona idea), E per autorizzare l'applicazione, per cui potresti modificare il codice sorgente di OAuth1, ma sinceramente se vuoi usare CURL per fare TUTTO... stai pensando a questo nel modo sbagliato, e dovresti trovare un'altra soluzione o metodo.

sMyles sMyles
20 set 2016 18:01:12

@Dan9 con quello che stai cercando di fare, dovresti usare OAuth2 server invece di OAuth1, principalmente perché OAuth2 ha nuove funzionalità incluso il tipo di concessione Client Credential, che evita di dover passare attraverso tutti questi passaggi http://bshaffer.github.io/oauth2-server-php-docs/grant-types/client-credentials/

sMyles sMyles
20 set 2016 18:14:59

@Dan9 se sei assolutamente determinato a ottenere aiuto per farlo tramite OAuth1, usando CURL, penso sia possibile con qualche modifica al codice, ma come ho detto, questo significa che devi salvare USERNAME e PASSWORD di un utente nel file PHP. Se per te va bene, fammelo sapere e scriverò un tutorial per farlo usando CURL, non voglio perdere tempo a scrivere il tutorial se poi opterai per OAuth2 o non ne avrai più bisogno

sMyles sMyles
20 set 2016 18:16:21

@Dan9 beh... è proprio questo il punto... se vuoi usare OAuth1, devi associare un Account Utente WordPress. Fondamentalmente pensa al Token di Accesso come a una chiave API... la "Chiave API" deve essere associata a un account utente... ora sta a te decidere se usare qualche account standard che hai configurato.. ma in ogni caso quando usi OAuth1 DEVE essere associato a un account utente, da qui il lungo processo per ottenere il token di accesso.

sMyles sMyles
20 set 2016 18:57:53

Ecco perché ho consigliato di usare OAuth2 perché puoi utilizzare il tipo di concessione client credentials, dove poi fai semplicemente una chiamata CURL con quelle credenziali, e ti restituisce un token di accesso (senza bisogno di passare attraverso il lungo processo di autorizzazione). Ecco tutti i tipi di concessione di OAuth2: http://bshaffer.github.io/oauth2-server-php-docs/overview/grant-types/

sMyles sMyles
20 set 2016 19:00:01
Mostra i restanti 1 commenti
2

Aggiungo questa come un'altra risposta per aiutarti a capire come fare questo. Fondamentalmente, come menzionato nei miei commenti, se intendi usare OAuth1 DEVI associarlo a un account utente, non c'è modo di aggirare questo.

Per prima cosa devi usare CURL per accedere al sito con un nome utente e password per WordPress, memorizzare il cookie in modo da poterlo usare nella tua chiamata CURL a OAuth (assicurati di aggiornare la tua chiamata CURL per includere il cookie):

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

Poi fai la chiamata a OAuth usando CURL con il Client ID e il Client Secret, per ottenere il token oauth temporaneo e il segreto (Request Token)

Per fare questa chiamata (e la chiamata per ottenere il token di accesso), devi configurare correttamente la tua chiamata CURL. Vedi alla fine di questa risposta per il codice e i riferimenti.

Dopo aver ottenuto il token oauth temporaneo e il segreto (Request Token), fai una chiamata CURL POST a questo URL del tuo sito:

http://website.com/oauth1/authorize

Dovrai quindi estrarre tutti i valori dall'HTML restituito per la pagina di autorizzazione, e poi inviare il tuo POST all'URL dell'azione del form.

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

In particolare, questi devono essere inclusi nei tuoi dati POST per completare l'"autorizzazione" POSTando a http://domain.com/wp-login.php?action=oauth1_authorize

  • _wpnonce -- Questo è il valore nonce per il form da inviare, questo DEVE essere estratto dall'input HTML e inviato con il tuo POST

    consumer -- Questo è un input nascosto nell'HTML (questo è un riferimento a un Post ID quindi devi estrarlo dall'input HTML

    oauth_token -- Questo è un input nascosto nell'HTML (ma dovresti già averlo)

    wp-submit -- Questo deve essere impostato al valore authorize

Ecco un esempio di HTML generato per la pagina di autenticazione:

<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">Connetti My Auth</h2>

    <div class="login-info">
        <p>Ciao <strong>admin</strong>,<br/> "My OAuth Demo" vorrebbe connettersi a 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">Autorizza</button>
        <button type="submit" name="wp-submit" value="cancel" class="button button-large">Annulla</button>
    </p>

</form>

Dopo aver fatto il POST con tutti quei valori/dati, questo è l'HTML che verrà restituito con il codice di autorizzazione (quindi devi estrarre il valore dal blocco <code>:

<div id="login">
    <h1><a href="https://wordpress.org/" title="Powered by WordPress" tabindex="-1">Example Site</a></h1>
    <p>Il tuo token di verifica è <code>yGOYFpyawe8iZmmcizqVIw3f</code></p> <p id="backtoblog"><a href="http://website.com/">&larr; Torna a Example Site</a></p>
</div>

Una volta che hai il token di verifica, puoi fare una chiamata a /oauth1/access usando il token di verifica, il token oauth e il segreto del token oauth. Il token di verifica deve essere inserito nei dati POST come oauth_verifier

Questo restituirà il tuo nuovo e permanente Access Token, e VOILÀ!

Esempio di Codice CURL

Di seguito è riportato un esempio di codice per fare la chiamata CURL, la parte più importante è come viene generata la 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;
}

// Aggiungi request, authorize, ecc. alla fine dell'URL in base alla chiamata che stai facendo
$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);

Questo sito spiega esattamente come codificare la firma OAuth e come inviarla usando CURL (consiglio di leggere l'intera pagina): https://hannah.wf/twitter-oauth-simple-curl-requests-for-your-own-data/

Altre risorse sulla generazione della firma OAuth1: https://stackoverflow.com/questions/24613277/oauth-signature-generation-using-hmac-sha1

Altre Risorse: http://collaboradev.com/2011/04/01/twitter-oauth-php-tutorial/

20 set 2016 20:47:25
Commenti

Come posso ottenere Client ID e Client secret e associarli a un utente valido? Attualmente solo gli amministratori possono creare una nuova app e ciò avviene esclusivamente tramite la dashboard di amministrazione. A proposito, ho provato a generare oauth_signature come mi hai detto ma, in qualche modo, la risposta è sempre json_oauth1_signature_mismatch.

James Vu James Vu
21 set 2016 06:49:14

@Dan9 sì è corretto, gli amministratori devono creare l'app, altrimenti sarebbe un enorme problema di sicurezza consentire la creazione di app da parte di utenti anonimi. Ecco alcuni siti riguardanti la firma 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 set 2016 20:55:22
0

So che mi sto unendo un po' in ritardo, ma puoi usare wp_remote_get e _post?

Sto recuperando e inviando contenuti con la mia installazione WordPress utilizzandoli:

Questa è l'idea generale dal codex di WordPress:

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

Ecco un esempio più specifico:

$url='http://WWW.ESEMPIOQUI.';
$response = wp_remote_post( $url, array(
    'method' => 'POST',
    'timeout' => 45,
    'redirection' => 5,
    'httpversion' => '1.0', //necessario per ottenere una risposta
    'blocking' => true,
    'headers' => array('Authorization' => 'Basic ' . base64_encode( 'ILMIO TOKENID' . ':' . '' )),
    'body' => $body // in array
    'cookies' => array()
    )
);

if ( is_wp_error( $response ) ) {
   $error_message = $response->get_error_message();
   echo "Qualcosa è andato storto: $error_message";
} else {
 //  echo 'Risposta:<pre>';
 //  print_r( $response );
 //    echo '</pre>'; 
$responseBody = json_decode($response['body'],true);
echo $responseBody['message'];

    }
    }
}

Il trucco sta nel codificare nome utente e password. Spesso, a seconda dell'API, il nome utente e la password saranno vuoti o saranno i tuoi token.

Ad esempio, nel mio caso specifico sopra, gli header erano

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

e ho lasciato la password vuota. Questo però dipende dal sistema API che stai utilizzando.

20 set 2016 23:44:26
0

Aggiornamento: Da quello che ho letto, è necessario eseguire multiple richieste curl per ottenere l'access_token, che poi utilizzerai per eseguire la query

  • Acquisizione Credenziali Temporanee: Il client ottiene un set di credenziali temporanee dal server.
  • Autorizzazione: L'utente "autorizza" il token di richiesta ad accedere al proprio account.
  • Scambio Token: Il client scambia le credenziali temporanee a breve durata con un token a lunga durata.

flusso server oauth1

15 apr 2016 15:37:22