This context provides a guide on how to link Firebase Authentication and Laravel Passport users using FirebaseUI for the web.
Abstract
The guide assumes that the user has already created a PHP API using Laravel 7.x and has installed and configured Laravel Passport, and uses FirebaseUI to register and sign-in users. The guide explains how Firebase and Laravel users will be linked by using the Firebase UID, which will never change even if the user signs in with another provider. The sign-in/sign-up workflow involves retrieving the Firebase Authentication credential token and sending it to the Laravel API to verify it and generate a Passport token. The guide also provides instructions on how to install and configure Laravel Firebase by Kreait to verify the credential's token with Google servers.
Opinions
The guide assumes that the user has a good knowledge of how to use their frontend framework to send API requests and react to data received asynchronously.
The guide suggests adding a specific column to the user's table such as FirebaseUID or whatever suits the user's nomenclature.
The guide recommends using HTTPS to request the API and implementing Cross-origin resource sharing (CORS) to allow only the API requests made from allowed URLs.
The guide suggests implementing scopes to limit which routes the user can access and linking the scope to the user's roles to easily add or remove user access rights from the API backend.
The guide recommends storing the Passport token in Vuex (if using Vuejs), local storage, or cookies and looking for it every time a protected API request is made.
The guide suggests that the implementation provided is very simple and lacks important functions such as scopes and more.
The guide recommends that the user leaves feedback in the comments.
FirebaseUI
How to link Firebase Authentication and Laravel Passport users
Learn how to create an authentication flow that links your Firebase Authentication users to your Laravel Passport ones using FirebaseUI for the web.
This may be useful when creating an API with Laravel where your users will sign in your web app using FirebaseUI from Google.
FirebaseUI for the web indeed gives you a very simple and secure way to add a reactive Javascript sign-in/sign-up interface with multiple providers such as Facebook, Google, GitHub or even good old email/password to your web app.
Built on top of Firebase Authentication, it means that your server will never see your users’ credentials as they are only sent and stored by Google.
One very interesting feature is that as long as they use the same email, your users will always have only one account no matter which provider they use.
Laravel Passport is a very powerful add-on to the Laravel Framework which provides a full OAuth2 server implementation. This will give you the ability to use secured tokens in your API requests with a lot of possibilities such as scopes for your routes, lifetime for your tokens ...
This guide assumes …
That you have already created a PHP API using Laravel 7.x and have installed and configured Laravel Passport and that you use FirebaseUI to register and sign-in your users.
That you have a good knowledge of how to use your frontend Framework to send API requests and react on data received asynchronously.
I personally looked at this problem with a web frontend using Vuejs in mind but Firebase Authentication also works with iOS, Android, C++ and more. So it is a very good choice for a authentication workflow.
If you are not using Laravel Passport yet
I suggest you to read their documentation and follow this great tutorial to get yourself a clear starting point.
If you are not using FirebaseUI yet
FirebaseUI is very simple and powerful to implement authentication flow. Check this official documentation to use it.
How will Firebase and Laravel users be linked ?
As described above, with Firebase Authentication, whatever login provider your users choose, you will always receive the same kind of data from Google and your users will always have only one account per email in your Firebase Authentication database.
All this logic is provided by Google, which is very convenient. On our side, we can access the users’ email, displayName, Avatar and .. UID (User ID).
Link your Laravel users with their respective Firebase UID
So, the simplest way to link your Laravel users with your Firebase users is to use their UID which will never change even if the user sign-in with another provider (assuming they use the same email for all providers).
I suggest you to add a specific column to your user’s table such as FirebaseUID or whatever suits your nomenclature.
Later, all we will have to do is check if the retrieved UID already exist in our Laravel users table and if not, create a new user with this UID.
The sign-in/sign-up workflow
To begin, let’s have a look at the desired workflow for our Web-App and API.
Authentication flow using FirebaseUI and Laravel Passport
As you can see, the first step is to request a Firebase credential’s token. Again, the good thing with Firebase Authentication is that, whatever supported provider your user will choose (Facebook, Google ..) you will always end up using a Firebase ID token. Which is what we need.
Retrieve the Firebase Authentication credential token
A Firebase’s token is just a JWT (JSON Web Tokens). As such you can inspect them using jwt.io and use third party library to handle them.
In case you wonder, to request a Firebase ID token when signing in your user using FirebaseUI for the web, use the Javascript getIdToken() function.
In theSignInSuccessWithAuthResult callback:
In the onAuthStateChanged function:
Send the Firebase Authentication credential to your API
The next step is to send this credential’s token to our Laravel API in order to verify it and generate a Passport token that we can use to authenticate our futures API requests.
I assume that you already know how to send a request to your Laravel API (I personally use Axios). You should also already have Laravel Passport setup and working with your own email and password.
For this tutorial we will only send our Firebase credential’s token as a request payload to our API as this is already enough to have a secured bridge between Firebase Auth and Laravel Passport.
Now, we need to use this token to create or sign-in your user and send back a Passport token that we can use in future API requests.
To verify a Firebase Authentication credential’s token in our API, we need to check with Google’s server if the token is valid (has the right format, exist in Google’s DB and is not expired).
To do that we can use a very good implementation of the Firebase Authentication SDK for Laravel: Laravel Firebase by Kreait.
To install it using composer, run:
composer require Kreait/laravel-firebase
If you do not use Laravel’s package auto-discovery you have to add the following service provider to your config/app.php:
Once that’s done, you need to configure the package to use your Firebase Auth service account which is needed to authenticate your requests to Firebase’s servers.
To do so, you can add the following in your Laravel’s .env file:
Please, make sure to not store this file in your repository as it is a very sensitive file, giving access to your Firebase’s account.
If you don’t have a service account for your Firebase Auth project, follow the instructions given by Google. You will end up with a credential JSON file that you have to place somewhere in your Laravel install.
You may also want to change some other options. If so, just copy the package’s config using:
For more details about the installation and configuration of kreait/laravel-firebase, check their documentation.
Verify the credential’s token with Google servers
So, now we are ready to verify the Firebase Auth credential’s token with Google’s servers.
In our authentication flow, to simplify the process, we will only use the login route and check whether a Laravel’s user exist with the specific Firebase UID.
If it does exist we return a Personal Access Token (and additional data if needed). If not, we create the user and return the user’s PAT and additional data.
Remember: We use the Firebase Authentication UID to link our Firebase users with our Laravel users.
So, with that in mind, let’s have a look at our loginController.php.
First, we need to add the Exception Handler provided by Firebase, add this to your loginController.php:
use Firebase\Auth\Token\Exception\InvalidToken;
Then, let’s look at our login function:
From reading the comments you should be able to understand the logic behind this process. But to make it clear:
We receive the Firebasetoken and use verifyIdToken() to check if the token is valid. If not, InvalidToken handle the errors.
We use getClaim('sub') to extract the Firebase Authentication UID.
We retrieve the User model which has the same UID. If there is none, we create a new user with this UID.
We use createToken('Personal Access Token') to create a new Passport token linked to our Laravel’s user with the desired lifetime.
We return to our frontend a JSON object containing the Passport’s token and additional infos.
Please note that this implementation is very simple and lacks important functions such as scopes (to limit which routes your user can access) and more.
If you want (and Istrongly suggest you to) to add scopes to your Passport’s tokens, have a look at this documentation. Personally I link my scope to my users’ roles, so Ican easily add or remove user access rights from my API backend.
Makes API requests using your Passport token
Et voila! You can now use your Passport token to authenticate every future API requests and limit which routes your users can access using scopes and other methods.
In your frontend, I suggest you to store this token in Vuex (if you use Vuejs), localstorage or cookies and then look for it every time you make a protected API request.
Now, even if someone use the public datas available to them (generated token will, of course, be easily available in the local datas of your users) to request your API they will be limited to the scopes given for the token or will be unauthorized if the token is invalid.
Additional security checks
There are a few additional security checks that I suggest implementing:
Make sure to use HTTPS to request your API, to prevent man-in-the-middle attacks.
Thanks for following this guide. It covers only the basics of integrating Firebase Authentication with Laravel Passport but I hope it was useful for you.