Firebase Auth with PHP and Google Identity Toolkit

When tasked with authentication against a google firebase system I was presented a weird drop-in JavaScript solution, that was useless, since I needed to use php to access Google Cloud Functions.

I ended up on Stack Overflow and got some indirect help,that pushed me into the right direction.

For the record, I will document the solution below.


I have to admit, the complexity of the firebase docs and examples and different services, got me so confused, that I thought, authentication for the web is only possible via JavaScript. That was wrong. At least for my case, where I just login with email and password to retrieve a Json Web Token (JWT), to sign all calls to the Firebase cloud functions. Instead of juggling with weird Ajax requests or set the token cookie via JavaScript, I just needed to call the Firebase Auth REST API

Here is a minimal case using the Fat-Free Framework:

Login form

<form action="/auth" method="post">
    <input name="email">
    <input name="password">
    <input type="submit">
</form>

Route

$f3->route('POST /auth', 'App->auth');

Controller

class App
{
  function auth()
  {
    $email = $this->f3->get('POST.email');
    $password = $this->f3->get('POST.password');

        $apiKey = 'API_KEY'; // see https://firebase.google.com/docs/web/setup

    $auth = new Auth($apiKey);
    $result = $auth->login($email,$password);

    if($result['success']){
      $this->f3->set('COOKIE.token',$result['idToken']);
      $this->f3->reroute('/dashboard');
    }else{
      $this->f3->clear('COOKIE.token');
      $this->f3->reroute('/');
    }
  }
}

Class

use GuzzleHttp\Client;

class Auth
{

  protected $apiKey;

  public function __construct($apiKey){
    $this->apiKey = $apiKey;
  }

  public function login($email,$password)
  {

    $client = new Client();
    // Create a POST request using google api
    $key = $this->apiKey;
    $response = $client->request(
      'POST',
      'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=' . $key,
      [
        'headers' => [
          'content-type' => 'application/json',
          'Accept' => 'application/json'
        ],
        'body' => json_encode([
          'email' => $email,
          'password' => $password,
          'returnSecureToken' => true
        ]),
        'exceptions' => false
      ]
    );

    $body = $response->getBody();
    $js = json_decode($body);

    if (isset($js->error)) {
      return [
        'success' => false,
        'message' => $js->error->message
      ];
    } else {
      return [
        'success' => true,
        'localId' => $js->localId,
        'idToken' => $js->idToken,
        'email' => $js->email,
        'refreshToken' => $js->refreshToken,
        'expiresIn' => $js->expiresIn,
      ];

    }

  }

}

Credits: