Mimic / Test Facebook деавторизовать POST - PullRequest
0 голосов
/ 19 марта 2012

Facebook требуется публичный URL для POST, чтобы деавторизовать ваше приложение для пользователя.

Я нахожусь за брандмауэром и не хочу тестировать это в своей производственной среде, поэтому кто-нибудь сумел имитировать этот POST в интеграционном тесте c # (или другом)?

Это будет включать создание формы с полем Sign_request и зашифрованным в base64 и размещение его в моем локальном веб-приложении для обработки ...

Ответы [ 2 ]

0 голосов
/ 19 марта 2012

Мне удалось найти что-то похожее для построения полезной нагрузки в Ruby, который я конвертировал, вот он с интеграционным тестом:

Этот класс строит строку, которую вы отправите POST как request.form ["signature_request "]

public class SignedRequest
  {
    public static string SignedRequestFor(string applicationSecret, string json)
    {
      // encode payload
      var payload = ToUrlBase64String(json);

      // create sig
      var Hmac = SignWithHmac(UTF8Encoding.UTF8.GetBytes(payload), UTF8Encoding.UTF8.GetBytes(applicationSecret));
      var HmacBase64 = ToUrlBase64String(Hmac);

      // concat and return
      return HmacBase64.Concatenate(".", payload);
    }

    private static byte[] SignWithHmac(byte[] dataToSign, byte[] keyBody)
    {
      using (var hmacAlgorithm = new HMACSHA256(keyBody))
      {
        hmacAlgorithm.ComputeHash(dataToSign);
        return hmacAlgorithm.Hash;
      }
    }

    private static string ToUrlBase64String(string input)
    {
      byte[] encodedBytes = Encoding.UTF8.GetBytes(input);
      return ToUrlBase64String(encodedBytes);
    }

    private static string ToUrlBase64String(byte[] input)
    {
        return Convert.ToBase64String(input).Replace("=", String.Empty)
                                            .Replace('+', '-')
                                            .Replace('/', '_');
    }
  }

Объект малого значения, используемый тестом:

public class RequestEnvelope
  {
    public long user_id { get; set; }

    public string algorithm = "HMAC-SHA256";
  }

Тест:

[Test]
public void CanDeauthorizeUser()
{
  var appSecret = ConfigurationManager.AppSettings["NewsletterSubscriptionFacebookAppSecret"];

  var envelope = new RequestEnvelope { user_id = 123456 };

  var signedRequest = SignedRequest.SignedRequestFor(appSecret, JsonConvert.SerializeObject(envelope));

  var postData = "signed_request=" + signedRequest;
  byte[] postBytes = Encoding.UTF8.GetBytes(postData);

  var request = WebRequest.Create(ConfigurationManager.AppSettings["AppWebUrl"] + "/SubscriptionHandler.ashx?a=deactivate");
  request.Method = "POST";
  request.ContentType = "application/x-www-form-urlencoded";
  request.ContentLength = postBytes.Length;
  using (var newStream = request.GetRequestStream())
  {
    // Send the data.
    newStream.Write(postBytes, 0, postBytes.Length);
    newStream.Close();
  }

  // Get the response.
  using (var response = request.GetResponse())
  {
    var status = ((HttpWebResponse) response).StatusDescription;

    // Get the stream containing all content returned by the requested server.
    using (var dataStream = response.GetResponseStream())
    {

      // Open the stream using a StreamReader for easy access.
      using (var reader = new StreamReader(dataStream))
      {

        // Read the content fully up to the end.
        string responseFromServer = reader.ReadToEnd();

        Console.WriteLine(responseFromServer);
        Console.WriteLine("status: " + status);
      }
    }
  }
}

Фрагмент из обработчика, который я публикую в:

string signedRequestValue = HttpContext.Current.Request.Form["signed_request"];
var items = SignedRequestParser.Parse(ConfigurationManager.AppSettings["NewsletterSubscriptionFacebookAppSecret"], signedRequestValue);

И код для разбора (взятый / измененный из codeplex facebook API):

public class SignedRequestParser
  {
    /// <summary>
    /// Parses the signed request string.
    /// </summary>
    /// <param name="appSecret">The unique app hash known the provider and the developer</param>
    /// <param name="signedRequestValue">The encoded signed request value.</param>
    /// <returns>The valid signed request.</returns>
    public static Dictionary<string, string> Parse(string appSecret, string signedRequestValue)
    {
      Check.Require(!String.IsNullOrEmpty(signedRequestValue));
      Check.Require(signedRequestValue.Contains("."), "Invalid Signed Request");

      string[] parts = signedRequestValue.Split('.');
      var encodedValue = parts[0];
      if (String.IsNullOrEmpty(encodedValue))
      {
        throw new InvalidOperationException("Invalid Signed Request");
      }

      var sig = Base64UrlDecode(encodedValue);
      var payload = parts[1];

      using (var cryto = new System.Security.Cryptography.HMACSHA256(Encoding.UTF8.GetBytes(appSecret)))
      {
        var hash = Convert.ToBase64String(cryto.ComputeHash(Encoding.UTF8.GetBytes(payload)));
        var hashDecoded = Base64UrlDecode(hash);
        if (hashDecoded != sig)
        {
          throw new InvalidOperationException("Invalid Signed Request.");
        }
      }

      var payloadJson = Encoding.UTF8.GetString(Convert.FromBase64String(Base64UrlDecode(payload)));
      var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(payloadJson);
      return data;
    }

    /// <summary>
    /// Converts the base 64 url encoded string to standard base 64 encoding.
    /// </summary>
    /// <param name="encodedValue">The encoded value.</param>
    /// <returns>The base 64 string.</returns>
    private static string Base64UrlDecode(string encodedValue)
    {
      Check.Require(!String.IsNullOrEmpty(encodedValue));

      encodedValue = encodedValue.Replace('+', '-').Replace('/', '_').Trim();
      int pad = encodedValue.Length % 4;
      if (pad > 0)
      {
        pad = 4 - pad;
      }

      encodedValue = encodedValue.PadRight(encodedValue.Length + pad, '=');
      return encodedValue;
    }
  }
0 голосов
/ 19 марта 2012

Вот как я делаю это в PHP:

<?php

function generateSignedRequest($data, $secret) {

    $payload = base64UrlEncode(json_encode($data));
    $signature = base64UrlEncode(hash_hmac('sha256', $payload, $secret, $raw = true));

    return "$signature.$payload";
}

function base64UrlEncode($input) {
    $input = rtrim(base64_encode($input), '=');
    return strtr($input, '+/', '-_');
}

$app_secret = "YOUR_APP_SECRET_HERE";

$data = array(
    'algorithm' => 'HMAC-SHA256',
    'issued_at' => 1332162396,
    'user' => array(
        'country' => 'bg',
        'locale' => 'en_US'
    ),
    'user_id' => '100003387159594'
);

$signed_request = generateSignedRequest($data, $app_secret);

?>

<form action="deauthorize_callback.php" method="post">
    <input type="text" name="signed_request" value="<?php echo $signed_request?>" size="255" />
    <input type="submit" value="Send Request" />
</form>

Если у вас есть PHP в вашей локальной среде, вы можете попробовать отправить форму в бэкэнд и посмотреть, работает ли он. Вам просто нужно заменить секретный ключ вашего приложения и идентификатор пользователя в массиве данных.

Надеюсь, это поможет, у меня это сработало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...