Подтвердить что ты не робот

Как декодировать OAuth 2.0 для Canvas signed_request в С#?

Я могу успешно проверить подписанный запрос на приложение для холста Facebook, используя пример здесь, но я не могу декодировать полезную нагрузку. В документации на Facebook указано, что второй параметр в signed_request является объектом JSON с кодировкой base64url. В PHP полезная нагрузка декодируется с помощью json_decode:

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

Что такое эквивалент в С#?

4b9b3361

Ответ 1

Следующее должно помочь вам.

(Примечание: ссылка JObject - это JSON.NET, доступная через http://james.newtonking.com/projects/json-net.aspx и http://json.codeplex.com/)

Используемые пространства имен:

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

код:

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;
    }

Это то, что я использую в FaceSharp.. надеюсь, что это поможет

Ответ 2

Извините, бит StackOverflow noob, но для тех, кто пытается использовать метод JohnK для декодирования, он отлично работает, всего несколько советов по внедрению для таких, как я и другие, с проблемой кодирования base64....

Ссылка Json также доступна из nuGet

Install-Package Newtonsoft.Json

http://developers.facebook.com/docs/guides/canvas/#auth более подробно объясняет элемент [ "signed_request" ], но просто добавляет, когда Facebook отправляется назад (в моем случае после запрос регистрации пользователя), вы можете получить данные из сообщения, но строка находится в ДВЕ ЧАСТИХ, разделенных символом '.' - Таким образом, попытка декодирования [ "signed_request" ] завершится неудачей как "." не является базовым 64 char. Первая часть - это подпись, позволяющая подтвердить, что сообщение пришло из Facebook (только мы и они знаем, что сиг для декодирования), а вторая - полезная нагрузка.

Итак, я получил это для работы со следующим кодом (в контроллере MVC), источником является кнопка регистрации Facebook....

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

а затем код контроллера отвечает на запрос регистрации

   [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();
    }

надеюсь, что это поможет кому-то, и извините, если это должно было быть редактирование/обратная связь или что-то еще...

Ответ 3

Тот же код, но без зависимости от Json.NET:

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);
}

Вы можете использовать его следующим образом:

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

Ответ 4

Посмотрите на .Net SDK на Codeplex http://facebooksdk.codeplex.com. Он будет обрабатывать всю "грязную работу" для вас. Например, я мог бы вызвать следующий код либо из действия контроллера, либо из Page_Load.

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

Вот оно. Вам не нужно беспокоиться о том, как facebook возвращает вам данные или расшифровывает их. SDK обрабатывает все, что для вас.

Ответ 5

Я меняю DecodePayload на это, и он отлично работает для меня:

    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; 
    }

Ответ 6

Здесь, как это сделать, используя Facebook SDK

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