6

I'm learning how to implement Facebook Fulfillment flow. I can't make sense of using request_id (steps 1 & 2). The idea is that my server generates request_id and later when the app get encoded response from Facebook, compare details in that response with the stored details on my server (using request_id as a key).

What is the purpose for this validation?

It says:

The most secure way to verify an order is to use the signed_request parameter from the JavaScript callback, as this has been encoded using the App Secret and can't be manipulated by the client.

So, if we trust this data and it can't be manipulated, why we need for the additional check? If, in other hand, it can be manipulated, how this measure prevents from simple passing the same request to my server and use returned request_id as part of creating manipulated signed_request.

Mike Keskinov
  • 11,614
  • 6
  • 59
  • 87

2 Answers2

1

There are tow reasons of using request_id

This information can then be used later in the payment flow to verify that the purchase wasn't manipulated in between the client and server, or to retrieve a payment via a call to the Graph API in instances where the Payment ID isn't known.

  1. Although data can't be manipulated, It ensures extra security.
  2. It makes possible to retrieve a payment without using Payment ID.

Note: request_id is optional and you can definitely serve the purpose using alternative ways.

  1. The Developer Server verifies the payment by decoding the signed request from the Client and using the payment verification payload in one of the following 2 ways:

    1. Using the request_id parameter to compare the purchase details against the persisted data from step1.
    2. Making a call to Facebook Graph API to confirm that the payment details are as expected

By using signed_requestthere are 2 ways to verify the payment.

  1. If you generate the request_id you can verify without having any further request to FB server because of the request_id is reserved in your database. So it is one of the advantages of using request_id that you can avoid extra request like calling Graph API.

  2. If you have not any request_id then you have to use the Payment ID and make a request to FB again.

See more on the Verification via Graph API section.

Rowf Abd
  • 734
  • 10
  • 21
  • To be honest, I still don't see any extra security at all. Nothing stops anyone to read my client javascript and request my server for request_id the same way as JS does. So, I assume it's not a problem at all to notify my server about "upcoming purchase" and get request_id as response. I don't worry about Facebook security. I just don't understand what they said in step 10 about "verification payload". The trusted response don't need to be verified in the first place. And secondly, this verification doesn't help at all. – Mike Keskinov Feb 21 '19 at 02:10
  • @MikeKeskinov Hi, I have added some more details about why you should use the request_id. Please see and let me know if it makes sense. – Rowf Abd Feb 21 '19 at 04:42
  • Making a call to FB API (see 10.2 above) makes sense, because it insures that the payment actually was made. The server to server call is safe way to ask Facebook: "did you really get the money?". Using `request_id` is different story. In this case, no call to Facebook even made. After using `request_id` method we still don't know if the money was received or if Facebook even aware of transaction. We simple check our own server database. But the record in this database is not secure. It can be easily manipulated by anyone, because interface to our server is public (it reveled in javascript). – Mike Keskinov Feb 21 '19 at 16:07
  • @MikeKeskinov The most secure way to verify an order is to use the signed_request parameter from the JavaScript callback, as this has been encoded using the App Secret and can't be manipulated by the client. By passing this to your Server, and parsing it server-side, you get trusted information about the details of the payment in a synchronous manner, which you can use to verify the payment before fulfilling. This step is shown in step 9 in the payment flow diagram. – Rowf Abd Feb 21 '19 at 16:21
  • Correct, the fact that we actually don't need any "additional security" articulated in my initial question. But, pretend for a second that for some strange reason we want an additional check. In this case we may ask FB API. Using `request_id` doesn't seems help us verify or secure anything because of the reason stated in my previous comment. – Mike Keskinov Feb 21 '19 at 16:33
1

Let's break it down and try to understand the use the use of signed_request.

It says, The most secure way to verify an order is to use the signed_request parameter from the JavaScript callback, as this has been encoded using the App Secret and can't be manipulated by the client.

The signed_request is encoded by Facebook servers using app secret that only Facebook & the App Developer knows. No other client will be able to generate signed_request without the secret key. Hence this is the most secure way to verify an order.

How can a client manipulate signed_request?

If your site is vulnerable to XSS, an attacker can inject javascript code into your application.

How will the app server knows that the signed_request is not generated by Facebook?

When the app server receives the signed_request, it must verify the signature of the singed_request. The signature verification will only succeed if it was generated by Facebook because only Facebook have your secret key.

The method of verifying the authenticity of digital data is known as Digital Signature.

sun_jara
  • 1,736
  • 12
  • 20
  • Assuming XSS possible, even if javascript injected, this still will be impossible to manipulate signed_request. Verification happens on server side. What I missing? – Mike Keskinov Feb 21 '19 at 02:14