Thread Context

This API allows the bot to get additional information about the user and where the webview was invoked.

It's useful in creating interactive group experiences and games as well to restrict any content that was intended to be shared only to a certain thread.

  1. Using getContext()
  2. Validating the signed_request
  3. Using Thread IDs with Global Pages

Using getContext()

Availability

This API is available only in Messenger on v113 on Android and v114 on iOS.

To check for its availability on a given client, call getSupportedFeatures() and check for the "context" key in the response.

Call this function to get the user ID, thread ID, and thread type.

MessengerExtensions.getContext('YOUR_APP_ID', 
  function success(result){
    ...
  },
  function error(result){
    ...
  }
);

Parameters

Parameter Description Type Required

app ID

Your bot's app ID

String

Yes

success callback

This function will be called and pass an object containing tid (thread ID) and thread_type.

Function

Yes

error callback

This function will be called if Messenger was unable to provide the context info.

Function

Yes

The response passed to the success callback will be a JavaScript object in the following format:

Response Format

{
  "thread_type": "GROUP",
  "tid": "1411911565550430",
  "psid": "1293479104029354",
  "signed_request": "YOUR_SIGNED_REQUEST"
}

Fields

Field Description Type

tid

The thread ID that the webview was invoked in.

String

thread_type

One of the following values:

"USER_TO_PAGE" - a conversation between a user and a page.

"USER_TO_USER" - a conversation between two users.

"GROUP" - a conversation between multiple users. Number of participants for such conversations can change from 1 to maximum supported by Messenger group capabilities.

String

psid

A page-scoped user ID for the user viewing the page.

String

signed_request

A signed request containing the above information.

String

Validating the signed_request

There are situations where you may wish to transmit the information obtained from getContext() to your backend and validate it before performing some action like a login or purchase. This allows you to ensure that the information really did come from Messenger and was not spoofed.

The signed_request is base64url encoded and signed with an HMAC version of your App Secret, based on the OAuth 2.0 spec.

You can validate it with the following 4 steps:

  1. Split the signed request into two parts delimited by a '.' character (e.g. 238fsdfsd.oijdoifjsidf899)
  2. Decode the first part — the encoded signature — from base64url encoding.
  3. Decode the second part — the payload — from base64url encoding. This can be used on the server side if needed.
  4. Hash the original payload using HMAC SHA-256 and your app secret and confirm that it is equal to the encoded signature originally passed.
  5. You may also wish to validate the issued_at timestamp in the payload to ensure the recency of the request.

This can be done in any modern programming language. Below is an example in PHP:

function parse_signed_request($signed_request) {
  list($encoded_sig, $payload) = explode('.', $signed_request, 2); 

  $secret = "appsecret"; // Use your app secret here

  // Decode the data
  $sig = base64_url_decode($encoded_sig);
  $data = json_decode(base64_url_decode($payload), true);

  // Confirm the signature
  $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
  if ($sig !== $expected_sig) {
    error_log('Bad Signed JSON signature!');
    return null;
  }

  return $data;
}

function base64_url_decode($input) {
  return base64_decode(strtr($input, '-_', '+/'));
}

Decoding the payload will yield an object with the same information as originally returned by getContext(), but with the addition of algorithm, issued_at, and page_id fields:

{
  "psid": "1293479104029354", 
  "algorithm": "HMAC-SHA256", 
  "thread_type": "GROUP", 
  "tid": "1411911565550430", 
  "issued_at": 1491351619, 
  "page_id": 167938560376726
}

Remember, to avoid accidentally divulging your app secret, this validation should happen on your server and never in client-side code.

Using Thread IDs with Global Pages

Some businesses use a global page structure with multiple pages associated with one app ID or bot. In this situation, the thread IDs returned by getContext() in the chat extension will be different for people in different countries. This

Use the following API to resolve the country page-specific thread ID to a global thread ID, and use that global thread ID to maintain state among users accessing the chat extension from their respective regional pages.

Retrieve global thread ID:

curl -X GET "https://graph.facebook.com/v2.6/{thread-id}?access_token=PAGE_ACCESS_TOKEN"
    

Example response:

    {"tid":1577059318985661,"global_tid":1577059318985661}
  

If there's no global page, global_tid will not be present.