Omar Shamali

idToken of Firebase Server Side Verification PHP via JWT and solve: cannot be coerced into a public key

Author: Omar Shamali
Last Modification:
Writing Date:

In this proposed solution, I assume you already have knowledge in:

  1. PHP coding.
  2. Composer PHP dependencies manager.

So you have implemented Firebase Auth in your project, it could be Android app or iOS app or web or other, and you actually got it working successfully by getting auth data back from Firebase carrying payload of many information such as username, email, photo of profile..etc, each auth method has different return data, but Firebase tries to unify them in many ways.

After the successful return of data from Firebase auth, you probably need to send user data to your server in order to get him in your database, lets say account creation or if the account is already in the database to allow him to login later or connect to social account, whatever the usage, you can not simply use the data sent from your mobile app (or whatever platform you are using) directly to be inserted in your database, you know why of course, but in case you are new this as we all were in your shoes, it is because the data could be manipulated by someone in the middle, or by a hacker or anyone wants to mess with your system and data, so what is to be done?

To make sure that this data coming from your app is correct, valid and truly came from Google Firebase, before you insert it in your database. To do so, as you have successfully retrieved data in your app, you will get something called idToken, this token carries a lot of information, but the most important thing is that its encrypted by Firebase, and to make sure it is encrypted by Firebase before inserting it in your database in PHP, do the following:

First, you need to install Firebase/php-jwt, this is the command:

composer require firebase/php-jwt

If you follow the examples in that library's page on GitHub, you would probably will get stuck for hours, as I got stuck, with different errors, the very annoying one was:

openssl_verify(): Supplied key param cannot be coerced into a public key

This error appears because the public keys provided by Google can not be read simply with file_get_contents, as tens of solutions online suggest. To overcome this issue, we need to make PHP read those public Google keys via openssl_get_publickey() PHP function.

Long story short, make a PHP file, and put the following code in it:

<?php 
require_once("vendor/autoload.php"); 
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$token='the_token_you_got_from_firebase_auth_called_idToken';

//get the public keys of Google
$publicKeysOfGoogleRAW = file_get_contents('https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com');
$publicKeysOfGoogleArr = json_decode($publicKeysOfGoogleRAW, true);

foreach($publicKeysOfGoogleArr as $publicKey){
    $tmp_openssl_publickey=openssl_get_publickey($publicKey);
    $jwtPublicKeysArr=new key ($tmp_openssl_publickey,'RS256');

    try{
        $decoded = JWT::decode($token, $jwtPublicKeysArr);
        echo json_encode($decoded);
        die();
    }catch (\Exception $e) {
        $error=$e->getMessage();
    }
}

    echo json_encode(['error'=>$error]);
    die();

 

This is tested on PHP 8.1.