Home » Php » Setting up firebase v3 custom auth with php

Setting up firebase v3 custom auth with php

Posted by: admin July 12, 2020 Leave a comment

Questions:

I’m trying to set up custom auth with the new firebase sdk from google following those guidelines : https://firebase.google.com/docs/auth/server#use_a_jwt_library
In the samble code it says :

Get your service account’s email address and private key from the JSON key file

Unfortunately I have not idea where to get this json file. If I go to my firebase console (https://console.firebase.google.com/) I manage to donwload a json file but it does not contain any email adress and private key.

I managed to find a json file that contains an email adress and a private key in my google cloud platform console (http://console.cloud.google.com) by goind into the “API Manager > Credentials” menu. Surprisingly my firebase app was showed there. I copy and pasted the email and key into the sample code, then I got this error :

Warning: openssl_sign(): supplied key param cannot be coerced into a private key in /volume1/web/yeti/vendor/firebase/php-jwt/src/JWT.php on line 183 Fatal error: Uncaught exception ‘DomainException’ with message ‘OpenSSL unable to sign data’ in /volume1/web/yeti/vendor/firebase/php-jwt/src/JWT.php:185 Stack trace: #0 /volume1/web/yeti/vendor/firebase/php-jwt/src/JWT.php(154): Firebase\JWT\JWT::sign(‘eyJ0eXAiOiJKV1Q…’, NULL, ‘RS256’) #1 /volume1/web/yeti/jwt.php(21): Firebase\JWT\JWT::encode(Array, NULL, ‘RS256’) #2 /volume1/web/yeti/jwt.php(24): create_custom_token(‘1234’, false) #3 {main} thrown in /volume1/web/yeti/vendor/firebase/php-jwt/src/JWT.php on line 185

Does someone has an idea of what I’m doing wrong ?

Thanks

How to&Answers:

Did you find the solution ? Still experiencing the same issue ! Works with HS256 and doesn’t with RS256. Is it google cloud kind of limitation ?


Thank you so much ! @dbburgess

Problem: Was using the wrong key and email. These should be generated in the Google Cloud credentials section that corresponds to the Firebase project.

Solution:

  • Go to ‘console.cloud.google.com’.
  • Select the related Firebase project.
  • Then ‘API Manager’ -> ‘Credentials’.
  • ‘Create Credentials’ -> ‘Service Account Key’ -> Choose JSON.
  • The created file will contain the needed ‘private_key’ & ‘client_email’.

Fill the values:

$service_account_email = “[email protected]”;
$private_key = “—–BEGIN PRIVATE KEY—–\nSoneVeryVeryLongKey=\n—–END PRIVATE KEY—–\n”;
$uid = ‘UserToUseInFirebaseRules’;
$is_premium_account = $uid;

You shouldn’t need to change anything in the “create_custom_token” function, maybe the expiration date/time according to your needs.

Then call the function:

create_custom_token($uid, $is_premium_account);

Answer:

This is what I’m doing, and it works fine. What you provide in the claims array is what shows up on auth in the security rules. The email and key come from the json file you get when you create a service account (see: Before you begin section).

$userId = '1234';
$email = '[email protected]';
$key = 'giant_key_goes_here';

$payload = [
    'iss' => $email,
    'sub' => $email,
    'aud' => 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit',
    'iat' => time(),
    'exp' => time() + 60 * 60,
    'uid' => $userId,
    'claims' => [
        'uid' => $userId,
    ],
];

$token = JWT::encode($payload, $key, 'RS256');

It’s worth noting, the format on the keys is a little tricky…Your key will look something like this (just an example key):

-----BEGIN PRIVATE KEY-----
MIICXAIBAAKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUp
wmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ5
1s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQABAoGAFijko56+qGyN8M0RVyaRAXz++xTqHBLh
3tx4VgMtrQ+WEgCjhoTwo23KMBAuJGSYnRmoBZM3lMfTKevIkAidPExvYCdm5dYq3XToLkkLv5L2
pIIVOFMDG+KESnAFV7l2c+cnzRMW0+b6f8mR1CJzZuxVLL6Q02fvLi55/mbSYxECQQDeAw6fiIQX
GukBI4eMZZt4nscy2o12KyYner3VpoeE+Np2q+Z3pvAMd/aNzQ/W9WaI+NRfcxUJrmfPwIGm63il
AkEAxCL5HQb2bQr4ByorcMWm/hEP2MZzROV73yF41hPsRC9m66KrheO9HPTJuo3/9s5p+sqGxOlF
L0NDt4SkosjgGwJAFklyR1uZ/wPJjj611cdBcztlPdqoxssQGnh85BzCj/u3WqBpE2vjvyyvyI5k
X6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl
U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ
37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=
-----END PRIVATE KEY-----

You may need to do a little fancy formatting, this is essentially what I did:

$key = "-----BEGIN PRIVATE KEY-----\nMIICXAIBAAKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUp\nwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ5\n1s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQABAoGAFijko56+qGyN8M0RVyaRAXz++xTqHBLh\n3tx4VgMtrQ+WEgCjhoTwo23KMBAuJGSYnRmoBZM3lMfTKevIkAidPExvYCdm5dYq3XToLkkLv5L2\npIIVOFMDG+KESnAFV7l2c+cnzRMW0+b6f8mR1CJzZuxVLL6Q02fvLi55/mbSYxECQQDeAw6fiIQX\nGukBI4eMZZt4nscy2o12KyYner3VpoeE+Np2q+Z3pvAMd/aNzQ/W9WaI+NRfcxUJrmfPwIGm63il\nAkEAxCL5HQb2bQr4ByorcMWm/hEP2MZzROV73yF41hPsRC9m66KrheO9HPTJuo3/9s5p+sqGxOlF\nL0NDt4SkosjgGwJAFklyR1uZ/wPJjj611cdBcztlPdqoxssQGnh85BzCj/u3WqBpE2vjvyyvyI5k\nX6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl\nU9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ\n37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0=\n-----END PRIVATE KEY-----\n";

Note the line breaks are turned into \n, and it is all smushed onto one line. There are various ways of accomplishing it, but…Based on the error you got, something like this may be the problem.

Answer:

Found my self what was wrong !
The sample php code from the documentation is buggy. Instead of

return JWT::encode($payload, $private_key, "RS256");

use

return JWT::encode($payload, $private_key, "HS256");

Edit :
Actually, it was just the sample php code from google firebase doc that was completely buggy. it was passing an empty key to php-jwt. Looks like they updated it today and it’s working fine 🙂

Answer:

instead of

$key = 'giant_key_goes_here';
token = JWT::encode($payload, $key, 'RS256');

use

define("FIREBASE_PRIVATE_KEY","giant_key_goes_here");
token = JWT::encode($payload, FIREBASE_PRIVATE_KEY, 'RS256');