Sono d'accordo con te. Le classi di supporto OAuth open source disponibili per le app .NET sono difficili da capire, eccessivamente complicate (quanti metodi sono esposti da DotNetOpenAuth?), Mal progettate (guarda i metodi con 10 parametri di stringa nel modulo OAuthBase.cs di quel google link che hai fornito - non esiste alcuna gestione statale) o altrimenti insoddisfacente.
Non è necessario che sia così complicato.
Non sono un esperto di OAuth, ma ho prodotto una classe di gestione lato client OAuth, che utilizzo con successo con Twitter e TwitPic. È relativamente semplice da usare. È open source e disponibile qui: Oauth.cs
Per la revisione, in OAuth 1.0a ... abbastanza divertente, c'è un nome speciale e sembra uno "standard" ma per quanto ne so l'unico servizio che implementa "OAuth 1.0a" è Twitter. Immagino sia abbastanza standard . ok, comunque in OAuth 1.0a, il modo in cui funziona per le app desktop è questo:
Tu, lo sviluppatore dell'app, registra l'app e ottieni una "chiave utente" e un "segreto utente". Su Arstechnica, c'è un'analisi ben scritta del perché questo modello non è il migliore , ma come si suol dire, è quello che è .
La tua app viene eseguita. La prima volta che viene eseguito, deve convincere l'utente a concedere esplicitamente l'approvazione affinché l'app effettui richieste REST autenticate da oauth a Twitter e ai suoi servizi gemelli (come TwitPic). Per fare ciò è necessario eseguire un processo di approvazione, che implica l'approvazione esplicita da parte dell'utente. Ciò accade solo la prima volta che l'app viene eseguita. Come questo:
- richiedere un "token di richiesta". Token temporaneo Aka.
- pop una pagina web, passando quel token di richiesta come parametro di query. Questa pagina web presenta l'interfaccia utente all'utente, chiedendo "vuoi concedere l'accesso a questa app?"
- l'utente accede alla pagina web di Twitter e concede o nega l'accesso.
- viene visualizzata la pagina html di risposta. Se l'utente ha concesso l'accesso, viene visualizzato un PIN con un carattere di 48 punti
- l'utente ora deve tagliare / incollare quel pin in una casella di Windows form e fare clic su "Avanti" o qualcosa di simile.
- l'app desktop quindi esegue una richiesta autenticata da oauth per un "token di accesso". Un'altra richiesta REST.
- l'app desktop riceve il "token di accesso" e il "segreto di accesso".
Dopo il ballo di approvazione, l'app desktop può semplicemente utilizzare il "token di accesso" e il "segreto di accesso" specifici per l'app (insieme alla "chiave utente" e al "segreto consumatore" specifici dell'app) per eseguire richieste autenticate per conto dell'utente a Twitter. Questi non scadono, anche se se l'utente revoca l'autorizzazione dell'app, o se Twitter per qualche motivo revoca l'autorizzazione della tua app, o se perdi il token di accesso e / o il segreto, dovrai ripetere la danza di approvazione .
Se non sei intelligente, il flusso dell'interfaccia utente può in qualche modo rispecchiare il flusso di messaggi OAuth in più passaggi. C'è un modo migliore.
Utilizzare un controllo WebBrowser e aprire la pagina Web di autorizzazione all'interno dell'app desktop. Quando l'utente fa clic su "Consenti", prendi il testo della risposta da quel controllo WebBrowser, estrai il PIN automaticamente, quindi ottieni i token di accesso. Si inviano 5 o 6 richieste HTTP ma l'utente deve vedere solo una singola finestra di dialogo Consenti / Nega. Semplice.
Come questo:
Se hai ordinato l'interfaccia utente, l'unica sfida che rimane è produrre richieste firmate oauth. Questo fa inciampare molte persone perché i requisiti per la firma di oauth sono un po 'particolari. Questo è ciò che fa la classe OAuth Manager semplificata.
Codice di esempio per richiedere un token:
var oauth = new OAuth.Manager();
// the URL to obtain a temporary "request token"
var rtUrl = "https://api.twitter.com/oauth/request_token";
oauth["consumer_key"] = MY_APP_SPECIFIC_KEY;
oauth["consumer_secret"] = MY_APP_SPECIFIC_SECRET;
oauth.AcquireRequestToken(rtUrl, "POST");
QUESTO È . Semplice. Come puoi vedere dal codice, il modo per accedere ai parametri oauth è tramite un indicizzatore basato su stringhe, qualcosa come un dizionario. Il metodo AcquireRequestToken invia una richiesta firmata oauth all'URL del servizio che concede i token di richiesta, ovvero i token temporanei. Per Twitter, questo URL è " https://api.twitter.com/oauth/request_token ". La specifica oauth dice che è necessario impacchettare il set di parametri oauth (token, token_secret, nonce, timestamp, consumer_key, version e callback), in un certo modo (URL-codificato e unito da e commerciale) e in un lessicograficamente- ordinato, genera una firma su quel risultato, quindi impacchetta gli stessi parametri insieme alla firma, memorizzati nel nuovo parametro oauth_signature, in un modo diverso (uniti da virgole). La classe del gestore OAuth lo fa automaticamente. Genera automaticamente nonc e timestamp, versioni e firme : la tua app non ha bisogno di preoccuparsi o di essere a conoscenza di queste cose. Basta impostare i valori del parametro oauth ed effettuare una semplice chiamata al metodo. la classe manager invia la richiesta e analizza la risposta per te.
Ok, allora cosa? Una volta ottenuto il token di richiesta, si apre l'interfaccia utente del browser Web in cui l'utente concederà esplicitamente l'approvazione. Se lo fai bene, lo inserirai in un browser incorporato. Per Twitter, l'URL per questo è " https://api.twitter.com/oauth/authorize?oauth_token= " con oauth_token aggiunto. Fallo in codice in questo modo:
var url = SERVICE_SPECIFIC_AUTHORIZE_URL_STUB + oauth["token"];
webBrowser1.Url = new Uri(url);
(Se lo facessi in un browser esterno, useresti System.Diagnostics.Process.Start(url)
.)
L'impostazione della proprietà Url fa sì che il controllo WebBrowser passi automaticamente a quella pagina.
Quando l'utente fa clic sul pulsante "Consenti", verrà caricata una nuova pagina. È un modulo HTML e funziona come in un browser completo. Nel tuo codice, registra un gestore per l'evento DocumentedCompleted del controllo WebBrowser e in quel gestore, prendi il pin:
var divMarker = "<div id=\"oauth_pin\">"; // the div for twitter's oauth pin
var index = webBrowser1.DocumentText.LastIndexOf(divMarker) + divMarker.Length;
var snip = web1.DocumentText.Substring(index);
var pin = RE.Regex.Replace(snip,"(?s)[^0-9]*([0-9]+).*", "$1").Trim();
È un po 'di scraping dello schermo HTML.
Dopo aver afferrato il segnaposto, non è più necessario il browser web, quindi:
webBrowser1.Visible = false; // all done with the web UI
... e potresti anche chiamare Dispose () su di esso.
Il passaggio successivo è ottenere il token di accesso, inviando un altro messaggio HTTP insieme a quel pin. Questa è un'altra chiamata oauth firmata, costruita con l'ordine e la formattazione oauth che ho descritto sopra. Ma ancora una volta questo è davvero semplice con la classe OAuth.Manager:
oauth.AcquireAccessToken(URL_ACCESS_TOKEN,
"POST",
pin);
Per Twitter, tale URL è " https://api.twitter.com/oauth/access_token ".
Ora hai i token di accesso e puoi usarli nelle richieste HTTP firmate. Come questo:
var authzHeader = oauth.GenerateAuthzHeader(url, "POST");
... dov'è url
l'endpoint della risorsa. Per aggiornare lo stato dell'utente, sarebbe " http://api.twitter.com/1/statuses/update.xml?status=Hello ".
Quindi imposta quella stringa nell'intestazione HTTP denominata Autorizzazione .
Per interagire con servizi di terze parti, come TwitPic, è necessario creare un'intestazione OAuth leggermente diversa , come questa:
var authzHeader = oauth.GenerateCredsHeader(URL_VERIFY_CREDS,
"GET",
AUTHENTICATION_REALM);
Per Twitter, i valori per l'URL di verifica delle credenziali e l'ambito sono rispettivamente " https://api.twitter.com/1/account/verify_credentials.json " e " http://api.twitter.com/ ".
... e inserisci quella stringa di autorizzazione in un'intestazione HTTP chiamata X-Verify-Credentials-Authorization . Quindi invialo al tuo servizio, come TwitPic, insieme a qualsiasi richiesta stai inviando.
Questo è tutto.
Tutto sommato, il codice per aggiornare lo stato di Twitter potrebbe essere qualcosa del genere:
// the URL to obtain a temporary "request token"
var rtUrl = "https://api.twitter.com/oauth/request_token";
var oauth = new OAuth.Manager();
// The consumer_{key,secret} are obtained via registration
oauth["consumer_key"] = "~~~CONSUMER_KEY~~~~";
oauth["consumer_secret"] = "~~~CONSUMER_SECRET~~~";
oauth.AcquireRequestToken(rtUrl, "POST");
var authzUrl = "https://api.twitter.com/oauth/authorize?oauth_token=" + oauth["token"];
// here, should use a WebBrowser control.
System.Diagnostics.Process.Start(authzUrl); // example only!
// instruct the user to type in the PIN from that browser window
var pin = "...";
var atUrl = "https://api.twitter.com/oauth/access_token";
oauth.AcquireAccessToken(atUrl, "POST", pin);
// now, update twitter status using that access token
var appUrl = "http://api.twitter.com/1/statuses/update.xml?status=Hello";
var authzHeader = oauth.GenerateAuthzHeader(appUrl, "POST");
var request = (HttpWebRequest)WebRequest.Create(appUrl);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK)
MessageBox.Show("There's been a problem trying to tweet:" +
Environment.NewLine +
response.StatusDescription);
}
OAuth 1.0a è un po 'complicato sotto le coperte, ma non è necessario che lo sia. OAuth.Manager gestisce la generazione di richieste oauth in uscita e la ricezione e l'elaborazione del contenuto oauth nelle risposte. Quando la richiesta Request_token ti fornisce un oauth_token, la tua app non ha bisogno di memorizzarlo. Oauth.Manager è abbastanza intelligente da farlo automaticamente. Allo stesso modo, quando la richiesta access_token ottiene un token di accesso e un segreto, non è necessario archiviarli esplicitamente. OAuth.Manager gestisce quello stato per te.
Nelle esecuzioni successive, quando si dispone già del token di accesso e del segreto, è possibile creare un'istanza di OAuth.Manager in questo modo:
var oauth = new OAuth.Manager();
oauth["consumer_key"] = CONSUMER_KEY;
oauth["consumer_secret"] = CONSUMER_SECRET;
oauth["token"] = your_stored_access_token;
oauth["token_secret"] = your_stored_access_secret;
... e quindi genera le intestazioni di autorizzazione come sopra.
// now, update twitter status using that access token
var appUrl = "http://api.twitter.com/1/statuses/update.xml?status=Hello";
var authzHeader = oauth.GenerateAuthzHeader(appUrl, "POST");
var request = (HttpWebRequest)WebRequest.Create(appUrl);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK)
MessageBox.Show("There's been a problem trying to tweet:" +
Environment.NewLine +
response.StatusDescription);
}
Puoi scaricare una DLL contenente la classe OAuth.Manager qui . C'è anche un file della guida in quel download. Oppure puoi visualizzare il file della guida in linea .
Vedi un esempio di un Windows Form che utilizza questo gestore qui .
ESEMPIO DI FUNZIONAMENTO
Scarica un esempio funzionante di uno strumento da riga di comando che utilizza la classe e la tecnica descritte qui: