2016-03-31 11 views
11

Ho controllato un paio di domande correlate per trovare una risposta alla mia domanda, ma tutto inutilmente. Questa domanda Can we get email ID from Twitter oauth API? mi ha fatto fino ad ottenere il sostegno Twitter per consentire l'autorizzazione per il mio app di seguito: Additional permissions Usando questo doc come guida e code (modificandola un po ') la risposta è marcatoOttieni l'e-mail dell'utente dall'API di Twitter per l'autenticazione di accesso esterno ASP.NET MVC C#

var resource_url = "https://api.twitter.com/1.1/account/verify_credentials.json"; 
var postBody = "include_email=true";// 
resource_url += "?" + postBody; 

a generare una firma ed effettuare una richiesta per ottenere i dettagli dell'utente dai risultati di twitter in non autorizzato nella mia app MVC.

Tuttavia, quando si utilizza lo strumento Twitter generatore di firma per generare l'intestazione di autorizzazione e utilizzare Fiddler per fare una richiesta GET a https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true, ho anche l'email solo una volta e devo rigenerare le mie chiavi app twitter per ottenere di nuovo .

Esiste un documento su come generare una firma valida ed effettuare una richiesta valida per recuperare l'e-mail dell'utente Twitter tramite. Netto TwitterAuthentication?

risposta

15

Dopo essermi quasi completamente calvo dal strapparmi tutti i capelli dalla testa, finalmente l'ho fatto funzionare. Ho scoperto che la stringa base Signature era leggermente diversa da quella generata con il mio codice. Dopo piccole modifiche, sono stato in grado di generare una stringa di base della firma valida.

In Startup.cs, ho aggiunto access_token e access_secret come attestazioni. Non ho usato quello trovato sulla mia app perché gli utenti hanno bisogno di invocare una nuova nel tentativo di effettuare il login o registrarsi:

var twitterOptions = new Microsoft.Owin.Security.Twitter.TwitterAuthenticationOptions() 
{ 
    ConsumerKey = ConfigurationManager.AppSettings["consumer_key"], 
    ConsumerSecret = ConfigurationManager.AppSettings["consumer_secret"], 
    Provider = new Microsoft.Owin.Security.Twitter.TwitterAuthenticationProvider 
    { 
     OnAuthenticated = (context) => 
     { 
     context.Identity.AddClaim(new System.Security.Claims.Claim("urn:twitter:access_token", context.AccessToken)); 
     context.Identity.AddClaim(new System.Security.Claims.Claim("urn:twitter:access_secret", context.AccessTokenSecret)); 
     return Task.FromResult(0); 
     } 
    }, 
    BackchannelCertificateValidator = new Microsoft.Owin.Security.CertificateSubjectKeyIdentifierValidator(new[] 
    { 
     "A5EF0B11CEC04103A34A659048B21CE0572D7D47", // VeriSign Class 3 Secure Server CA - G2 
     "0D445C165344C1827E1D20AB25F40163D8BE79A5", // VeriSign Class 3 Secure Server CA - G3 
     "7FD365A7C2DDECBBF03009F34339FA02AF333133", // VeriSign Class 3 Public Primary Certification Authority - G5 
     "39A55D933676616E73A761DFA16A7E59CDE66FAD", // Symantec Class 3 Secure Server CA - G4 
     "‎add53f6680fe66e383cbac3e60922e3b4c412bed", // Symantec Class 3 EV SSL CA - G3 
     "4eb6d578499b1ccf5f581ead56be3d9b6744a5e5", // VeriSign Class 3 Primary CA - G5 
     "5168FF90AF0207753CCCD9656462A212B859723B", // DigiCert SHA2 High Assurance Server C‎A 
     "B13EC36903F8BF4701D498261A0802EF63642BC3" // DigiCert High Assurance EV Root CA 
    }), 
    CallbackPath = new PathString("/twitter/account/ExternalLoginCallback") 
}; 

app.UseTwitterAuthentication(twitterOptions); 

E infine, nel mio controller, ho appena chiamato il mio classe di supporto per ottenere il nome e-mail da Twitter:

if (loginInfo.Login.LoginProvider.ToLower() == "twitter") 
    { 
     string access_token = loginInfo.ExternalIdentity.Claims.Where(x => x.Type == "urn:twitter:access_token").Select(x => x.Value).FirstOrDefault(); 
     string access_secret = loginInfo.ExternalIdentity.Claims.Where(x => x.Type == "urn:twitter:access_secret").Select(x => x.Value).FirstOrDefault(); 
     TwitterDto response = MyHelper.TwitterLogin(access_token, access_secret, ConfigurationManager.AppSettings["consumer_key"], ConfigurationManager.AppSettings["consumer_secret"]); 
     // by now response.email should possess the email value you need 
    } 

Helper metodo di una classe:

Questa era la sezione ho ottimizzato al fine di rendere una richiesta valida:

basestring = String.Concat ("GET &", Uri.EscapeDataString (resource_url) + "&" + Uri.EscapeDataString (request_query), "% 26", Uri.EscapeDataString (basestring));

public static TwitterDto TwitterLogin(string oauth_token, string oauth_token_secret, string oauth_consumer_key, string oauth_consumer_secret) 
     { 
      // oauth implementation details 
      var oauth_version = "1.0"; 
      var oauth_signature_method = "HMAC-SHA1"; 

      // unique request details 
      var oauth_nonce = Convert.ToBase64String(
       new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString())); 
      var timeSpan = DateTime.UtcNow 
       - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 
      var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString(); 

      var resource_url = "https://api.twitter.com/1.1/account/verify_credentials.json"; 
      var request_query = "include_email=true"; 
      // create oauth signature 
      var baseFormat = "oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" + 
          "&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}"; 

      var baseString = string.Format(baseFormat, 
             oauth_consumer_key, 
             oauth_nonce, 
             oauth_signature_method, 
             oauth_timestamp, 
             oauth_token, 
             oauth_version 
             ); 

      baseString = string.Concat("GET&", Uri.EscapeDataString(resource_url) + "&" + Uri.EscapeDataString(request_query), "%26", Uri.EscapeDataString(baseString)); 

      var compositeKey = string.Concat(Uri.EscapeDataString(oauth_consumer_secret), 
            "&", Uri.EscapeDataString(oauth_token_secret)); 

      string oauth_signature; 
      using (HMACSHA1 hasher = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(compositeKey))) 
      { 
       oauth_signature = Convert.ToBase64String(
        hasher.ComputeHash(ASCIIEncoding.ASCII.GetBytes(baseString))); 
      } 

      // create the request header 
      var headerFormat = "OAuth oauth_consumer_key=\"{0}\", oauth_nonce=\"{1}\", oauth_signature=\"{2}\", oauth_signature_method=\"{3}\", oauth_timestamp=\"{4}\", oauth_token=\"{5}\", oauth_version=\"{6}\""; 

      var authHeader = string.Format(headerFormat, 
            Uri.EscapeDataString(oauth_consumer_key), 
            Uri.EscapeDataString(oauth_nonce), 
            Uri.EscapeDataString(oauth_signature), 
            Uri.EscapeDataString(oauth_signature_method), 
            Uri.EscapeDataString(oauth_timestamp), 
            Uri.EscapeDataString(oauth_token), 
            Uri.EscapeDataString(oauth_version) 
          ); 


      // make the request 

      ServicePointManager.Expect100Continue = false; 
      resource_url += "?include_email=true"; 
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(resource_url); 
      request.Headers.Add("Authorization", authHeader); 
      request.Method = "GET"; 

      WebResponse response = request.GetResponse(); 
      return JsonConvert.DeserializeObject<TwitterDto>(new StreamReader(response.GetResponseStream()).ReadToEnd()); 
     } 
    } 

    public class TwitterDto 
    { 
     public string name { get; set; } 
     public string email { get; set; } 
    } 

Questo è tutto ciò che serve per ottenere e-mail dell'utente Twitter. Spero che aiuti qualcuno a lottare con questo. Si prega di notare che i passaggi citati nella domanda è anche molto importante.

+2

questo è stato lo sforzo di nyc e grazie per aver condiviso – Webruster

+0

Ciao Oluwafemi, questo codice funziona ancora per te? Sto affrontando questo problema dove sto ottenendo un 401 ogni volta che provo a richiedere https://api.twitter.com/1.1/account/verify_credentials.json per l'email .. Ho il permesso da Twitter, e quando uso il generatore di firme da Twitter (https://dev.twitter.com/oauth/tools/signature-generator/[APPID]) tutto funziona correttamente. L'intestazione di autorizzazione creata dal tuo codice sembra molto simile, ma non funziona per me. Hai forse un esempio funzionante? –

+0

@Guido Il metodo di supporto sopra utilizzato come dovrebbe dovrebbe funzionare. Attualmente sta lavorando su tutti i miei siti live. – Oluwafemi

0

è necessario modificare il codice per chiamare il metodo GET account/verify_credentials dopo che l'utente ha effettuato l'accesso con Twitter. Ed è importante impostare il parametro include_email su true. Quando questo è impostato su true, l'email verrà restituita negli oggetti utente sotto forma di stringa. sto usando questa libreria https://www.nuget.org/packages/linqtotwitter in modo che non devo scrivere il codice per la gestione di Twitter API richiede

var twitterCtx = new TwitterContext(authTwitter); 
var verifyResponse = await 
    (from acct in twitterCtx.Account 
    where (acct.Type == AccountType.VerifyCredentials) && (acct.IncludeEmail == true) 
    select acct) 
    .SingleOrDefaultAsync(); 

vedere come ho fatto qui http://www.bigbrainintelligence.com/Post/get-users-email-address-from-twitter-oauth-ap

si tratta di una soluzione semplice e pulita

Problemi correlati