Mischa
Mischa

Reputation: 53

How to verify facebook id_token received by android app on server side with php and get user profile

To login with facebook on my android app I request the public_profile and email of the user:

LoginManager.getInstance().logInWithReadPermissions(LoginFragment.this,
                                                    Arrays.asList("public_profile", "email"));

Then I send the id_token Profile.getCurrentProfile().getId() to the backend server.

On server side I try to verify the token as follows:

$id_token = $_POST['idToken'];
$app_access_token = FB_APP_ID . "|" . FB_APP_SECRET;
$fb = new \Facebook\Facebook(['app_id' => FB_APP_ID, 
                              'app_secret' => FB_APP_SECRET, 
                              'default_graph_version' => 'v2.8', 
                              'default_access_token' => $app_access_token]);
$response = $fb->get('/debug_token?input_token=' . $id_token, $app_access_token);

But $response just contains an empty json {}.

UPDATE 1:

With

$oauth = $fb->getOAuth2Client();
$meta = $oauth->debugToken($app_access_token);

I eventually managed to validate the id_token. $meta contains then:

["metadata":protected]=>
    array(4) {
        ["app_id"]=>string(16) "123456"
        ["application"]=>string(10) "abcdef"
        ["is_valid"]=>bool(true)
        ["scopes"]=>array(0) {}
    }

What it also shows is that the scopes-array is empty although I called logInWithReadPermissions with public_profile and email permissions. I even checked the Permissions again in the onSuccess()-method of the FacebookCallback. But before I store the data to the DB I would like to read the user_id, user_name and email on server side to ensure that they match the id_token.

UPDATE 2:

When I call $oauth->debugToken() with $id_token instead of $app_access_token I now get what I expected. It also shows the pemissions I set before. But still I have the problem that I don't know how to access the granted information (user_name, user_profile_picture, email, etc.).

Upvotes: 0

Views: 1192

Answers (1)

Mischa
Mischa

Reputation: 53

Finally I managed to solve the whole problem. I guess my main problem was that I wasn't aware of when to use user access token and when app access token. In many discussions and even documentations one is just talking about access token without specifying whether he means the user or the app access token. That said, here my final solution:

$id_token = $_POST['idToken'];
$app_access_token = FB_APP_ID . "|" . FB_APP_SECRET;
$fb = new \Facebook\Facebook(['app_id' => FB_APP_ID, 
                          'app_secret' => FB_APP_SECRET, 
                          'default_graph_version' => 'v2.8', 
                          'default_access_token' => $app_access_token]);
$oauth = $fb->getOAuth2Client();
$meta = $oauth->debugToken($app_access_token);

try {
    $meta->validateAppId(FB_APP_ID);
    $idTokenIsValid = true;
} catch(FacebookSDKException $e) {
    $idTokenIsValid = false;
    exit;
}

if($idTokenIsValid){

    $resp = $fb->get('/me?fields=id,name,email,first_name,last_name,locale,gender', $id_token);

    $user = $resp->getGraphUser();

    if($user->getId() != null){
        $facebook_id = $user->getId();
        $picture = "graph.facebook.com/" . $facebook_id . "/picture";
    }

    if($user->getName() != null){
        $name = $user->getName();
    }

    $emailIsVerified = false;
    if($user->getEmail() != null){
        $email = $user->getEmail();
        $emailIsVerified = true;
    }

    if($user->getFirstName() != null){
        $given_name = $user->getFirstName();
    }

    if($user->getLastName() != null){
        $family_name = $user->getLastName();
    }

    if($user->getProperty('locale') != null){
        $locale = $user->getProperty('locale');
    }

    if($user->getProperty('gender') != null){
        $gender = $user->getProperty('gender');
    }

    if($emailIsVerified){
        //update db or/and request data from db
    }
}

Upvotes: 1

Related Questions