Securely verify Facebook user from backend

byGinkSat, 02 Feb 2019

With mobile applications or SPA websites, the client was separated from backend server and both working independently. Just communicate via Rest API or some other protocols.

But in any way, the data (user ID and auth token) which were taken from Facebook/Google on client side, can be easily manipulated by the user before sending to backend server. So we can't silly trust that data always correct.

Google has pointed out clearly on the developer docs and provide libraries to work with it also. The document from Facebook, on the other hand, is hidden deeply inside. Even when you found it, still quite unclear to understand. So I'll try to make it clearly.

At first, there are three types of tokens when working with Facebook api. Check it here.

  • User access token

  • App access token

  • Pages access token

User access token is actually the token we'll get from client side after it was granted login by Facebook SDK.

App access token is the token belongs to our Facebook app. It can only be generated by server to server call and can't get from client side.

Pages access token is the token type for Facebook page only.

For the scope of the problem, we can skip the Pages access token and just have to care about the 2 above. All we need is checking if the User access token we received from client side is valid, and it belongs to the user ID received with.

To verify it, we have to call to Graph debug token api:

curl -i -X GET "https://graph.facebook.com/debug_token?
  input_token={user-access-token}&
  access_token={app-access-token}

But before that, we need the App access token as the input for that api first. Let's use Graph access token api to get it:

curl -X GET "https://graph.facebook.com/oauth/access_token
  ?client_id={your-app-id}
  &client_secret={your-app-secret}
  &grant_type=client_credentials"

App ID and App secret are the one you can get from your Facebook management dashboard ⤏ Settings

FB app

Okay, quite clear now.

So from backend server, first we get the App ID and App secret to take the App access token. Keep it somewhere to reuse and refresh it periodically if needed.

When the client side provides us User access token, we'll combine with App access token via Graph debug token api to verify it. The result from this api will be something like this.

{
  "data":{
    "app_id":"{app-id}",
    "type":"USER", 
    "application":"{app-name}",
    "data_access_expires_at":1576687825, 
    "expires_at":1570820400,             
    "is_valid":true,
    "scopes":[
      "pages_show_list",
      "public_profile"
    ],
    "granular_scopes":[
      {
        "scope":"pages_show_list",
        "target_ids":[
          "{page-1-app-can-access-id}",
          "{page-2-app-can-access-id}"
        ]
      }
    ],
    "user_id":"10215241773831025"
  }
}

Make sure the user_id we received from client side and the one from this api are identical. Mission completed!


© 2016-2024  GinkCode.com