2010-08-08 4 views
17

Sono in grado di convalidare correttamente la richiesta firmata per un'app di tela Facebook utilizzando l'esempio here, ma non sono in grado di decodificare il carico utile. La documentazione di Facebook afferma che il secondo parametro in firm_request è un oggetto JSON con codifica base64url. In PHP il carico utile viene decodificato utilizzando json_decode:Come decodificare OAuth 2.0 per Canvas firm_request in C#?

$data = json_decode(base64_url_decode($payload), true); 

Qual è l'equivalente in C#?

+0

Hai trovato su? – cdpnet

+0

Hai provato a utilizzare Facebook C# SDK: http://github.com/facebook/csharp-sdk? – Romhein

+1

L'SDK C# di Facebook su github non gestisce nulla con l'autenticazione, fa solo richieste API. –

risposta

24

Il seguente dovrebbe aiutare fuori ..

(Nota: Il riferimento è jobject da JSON.NET disponibile tramite http://james.newtonking.com/projects/json-net.aspx e http://json.codeplex.com/)

spazi dei nomi utilizzati:

using System; 
using System.Collections.Generic; 
using System.Text; 
using Newtonsoft.Json.Linq; // JSON.NET project 

Codice :

public Dictionary<string,string> DecodePayload(string payload) 
    { 
     var encoding = new UTF8Encoding(); 
     var decodedJson = payload.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/'); 
     var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '=')); 
     var json = encoding.GetString(base64JsonArray); 
     var jObject = JObject.Parse(json); 

     var parameters = new Dictionary<string, string>(); 
     parameters.Add("user_id", (string)jObject["user_id"] ?? ""); 
     parameters.Add("oauth_token", (string)jObject["oauth_token"] ?? ""); 
     var expires = ((long?) jObject["expires"] ?? 0); 
     parameters.Add("expires", expires > 0 ? expires.ToString() : "") ; 
     parameters.Add("profile_id", (string)jObject["profile_id"] ?? ""); 

     return parameters; 
    } 

È quello che sto usando in FaceSharp .. spero che aiuti

+0

Grazie, ha funzionato alla grande! –

+1

+1 Molto utile. Ho aggiornato la risposta con gli spazi dei nomi e ho fatto riferimento alla libreria JSON utilizzata (nel caso in cui il software FaceSharp non sia installato - probabilmente fornisce la libreria JSON.NET come parte di se stessa.) –

+0

Ma questo non funziona perché il codice non funziona . – Moons

2

Controlla l'SDK di Facebook su Codeplex http://facebooksdk.codeplex.com. Gestirà tutto il "lavoro sporco" per te. Ad esempio, potrei chiamare il codice seguente sia da un'azione del controller che da Page_Load.

FacebookApp app = new FacebookApp(); 
string accessToken = app.Session.AccessToken; 
long userId = app.UserId; 

Questo è tutto. Non devi davvero preoccuparti di come Facebook ti restituisce i dati o decodificarli. L'SDK gestisce tutto ciò che per te.

+0

App FacebookApp = nuova FacebookApp(); è ora l'app FacebookApp = nuova FacebookApp(); Non vedo comunque l'ID utente senza chiamare app.Get ("me") .. – AyKarsi

+0

Non hai spiegato come l'SDK decodifica la richiesta firmata :(Sto configurando un'azione Deauthorize() per gestire la richiesta firmata che è un POST di Facebook per la mia azione con il parametro "signed_request" come stringa. Voglio decodificarlo per ottenere l'user_id – Korayem

2

ho cambiare il DecodePayload da questo e funziona bene per me:

public Dictionary<string, string> DecodePayload(string payload) 
    { 
     //Remove the bad part of signed_request 
     //Begin 
     string[] sB64String = payload.Split('.'); 
     payload = payload.Replace((sB64String[0] + "."), string.Empty); 
     //End 
     var encoding = new UTF8Encoding(); 
     var decodedJson = payload.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/'); 
     var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '=')); 
     var json = encoding.GetString(base64JsonArray); 
     var jObject = JObject.Parse(json); 
     var parameters = new Dictionary<string, string>(); 
     parameters.Add("user_id", (string)jObject["user_id"] ?? ""); 
     parameters.Add("oauth_token", (string)jObject["oauth_token"] ?? ""); 
     var expires = ((long?)jObject["expires"] ?? 0); 
     parameters.Add("expires", expires > 0 ? expires.ToString() : ""); 
     parameters.Add("profile_id", (string)jObject["profile_id"] ?? ""); 
     return parameters; 
    } 
+2

Perché non fare payload = sB64String [1], invece di payload = payload.Replace ((sB64String [0 ] + "."), string.Empty); –

9

Siamo spiacenti, po 'di un noob StackOverflow, ma per chi cerca di utilizzare il metodo di Jöhnk per decodificare, funziona brillantemente, solo un paio di suggerimenti di implementazione per una persona come me e gli altri con la questione codifica Base64 ....

il riferimento JSON è disponibili anche da Nuget

Install-Package Newtonsoft.Json 

http://developers.facebook.com/docs/guides/canvas/#auth spiega l'elemento ["signed_request"] in maggiore dettaglio, ma in parole semplici, quando Facebook postback (nel mio caso dopo una richiesta di registrazione dell'utente), è possibile ottenere i dati dal post, ma la stringa è in DUE PARTI, separati da un '.' - Come tale, provare a decodificare ["signed_request"] fallirà come '.' non è un carattere Base64. La prima parte è la firma per consentire di convalidare che il post proviene da Facebook (solo noi e loro conoscono il sig per decodificare) e il secondo è il payload.

Così, ho ottenuto questo per lavorare con il seguente codice (in un controller MVC), fonte di un pulsante di registrazione Facebook ....

<fb:registration fields="name,email" redirect-uri="http://dev.devurlgoeshere.co.uk/Account/Register" width="530"> 
</fb:registration> 

e quindi il codice di controllo risponde alla richiesta di registrazione

[HttpPost] 
    public ActionResult Register(object postData) 
    { 
     string requestData = Request.Form["signed_request"]; 
     string[] splitPayload = requestData.Split('.'); 
     string sig = splitPayload[0]; 
     string payload = splitPayload[1]; 
     var decodedObj = DecodePayload(payload); 
     // get the items from the decodedObject 
     string userFacebookID = decodedObj["user_id"]; 
     // now do what you want with their FacebookID 
     return View(); 
    } 

spero che questo aiuti qualcuno, e mi dispiace se questo avrebbe dovuto essere modifica/feedback o qualsiasi altra cosa ...

2

Ecco come farlo utilizzando Facebook SDK

var parsedSignedRequest = FacebookSignedRequest.Parse(FacebookApplication.Current, signed_request); 
9

Stesso codice ma senza Json.NET dipendenza:

public IDictionary<string, object> DecodePayload(string payload) 
{ 
    string base64 = payload.PadRight(payload.Length + (4 - payload.Length % 4) % 4, '=') 
     .Replace('-', '+').Replace('_', '/'); 
    string json = Encoding.UTF8.GetString(Convert.FromBase64String(base64)); 
    return (IDictionary<string, object>)new JavaScriptSerializer().DeserializeObject(json); 
} 

è possibile utilizzarlo in questo modo:

public ActionResult Index() 
{ 
    var dict = DecodePayload(Request["signed_request"].Split('.')[1]); 
    return Content("Access Token: " + (string)dict["oauth_token"]); 
} 
+0

dict ["oauth_token"] - non è più una chiave: c'è 'codice' uno, è questo che dovrei usare? –

+0

La prima funzione ha funzionato per me ottimo lavoro – Moons