A simple control panel for application admins to manage users and privileges using Firebase — Part 1.

Firebase admin SDK is a server side SDK that allows us to interact with our Firebase project with admin privileges and perform certain actions to monitor and manager our project in our own way without using the Firebase console.

We are going to create a web application through which we will try to perform the actions that the Firebase admin SDK provides us with.

For that purpose we will need a front-end application which will act as the control panel and a back-end where we will integrate the admin SDK.

We will walk-through the front-end in the Part 2, and will be using react-js with Typescript for the same, although we can consume the API from any application.


Create a firebase project and turn on Authentication — email & password authentication, and Realtime Database.

Visit console.firebase.com to create a project and configure as above.

Part 1 — Making the back-end

We will be using node-js as the back-end for making a rest API that our front-end application will consume. We will be using Typescript as it provides us a better and error free way to write Javascript code.

In the first step we are going to set up a node project to use Typescript. We will use express for making the rest API.

After creating a new folder and opening the terminal, let’s run the commands to create the project.

npm init -y

Okay, now we have a package.json file. Let’s install the required dependencies for our project.

npm install express cors dotenv firebase-admin

Also typescript, tslint and the type declarations for cors and express as dev-dependencies.

npm install typescript tslint @types/express @types/cors

Now let’s make a few changes to the package.json to really integrate typescript in our build process. We will add a “start” key to the scripts object as follows.

“start”: “tsc && node dist/index.js”

With this we are making sure that we are running the Typescript compiler (or tsc) to transpile all the .ts files before running the application. We will modify the .tsconfig file to mention the dist directory as the output directory for the typescript compiler later in the article.

Let’s mention the “dist/index.js” as the value of the main property as this file will be the entry point for our application.

With these changes, the package.json file should look similar to this.

Now, let’s add a tsconfig.json file to the project root with the following values. This file is a configuration file for typescript specific to that project. Here we mention the “outDir” as “dist” which makes sure that tsc uses the dist directory as the output directory for the transpiled files.

Now to configure Typescript linting for the project, in a terminal running in the root of the project, run the following command to generate tslint.json.

./node_modules/.bin/tslint --init

Open the generated tslint.json file and the no-console rule accordingly.

Now lets start configuring firebase-admin sdk in our project. For initializing the firebase-admin sdk we need to configure a service account.

Follow this guide to configure service account, download the key and rename it as service-key.json. Place this file in the root of the project directory.

This file should not be pushed to any remote location where it is subject to the risk of getting exposed. This file should be added to the .gitignore file in case of git.

In this project we are using dotenv to simplify the task of setting and using environment variables in multiple environments. So, we will create a .env file at the project root to where we can define the several values that we require as environment variables.

Create a .env file and paste the following values:


Find your DB URL in the firebase console on top of your realtime database.

Now, we will create a directory structure as shown:

— models
— — admin
— — auth
— — users

Create an index.ts file under the src directory.

In the index.ts file, let’s import the required modules.

import express from 'express';
import * as admin from 'firebase-admin';
import * as dotenv from 'dotenv';
import cors from 'cors';

Now, before we initialize the admin sdk, we need to configure dotenv, in order to inject the values mentioned in the .env file as the environment variables.

const dotenvKey = dotenv.config();

Here you can remove the constant assignment as we are not going to use the dotenvKey constant in the project.

Now, to initialize the firebase-admin sdk.

credential: admin.credential.applicationDefault(),
databaseURL: process.env.DB_URL

Here, firebase-admin will use the environment variable mapped by us in the .env file to access the service-key.json file. Also, we provide the databaseURL as our application will access the realtime database.

Now, let’s add the boilerplate code to create an express app.

const port = process.env.PORT || 8080;
const app = express();
app.use(cors({origin: true}));
app.use(express.urlencoded({extended: false}));

We use cors to avoid the CORS error while consuming endpoints from a browser.

A great thing about Typescript is that it allows the use of Interfaces, which we can use in this case to define a schema for our user model. So, under the models directory, we will create a file named UserModel.ts, with the content as:

export interface User {
uid: string,
email: string | undefined,
displayName: string | undefined,
lastSignInTime: string,
creationTime: string,
emailVerified: boolean,
admin: boolean

Before proceeding with creating the routes, we need to secure the endpoints to prevent unauthorized access. For this purpose, we will create and use two middlewares, one for Authentication and another one for Authorization, i.e, to ensure whether the user requesting the operation has sufficient privileges.

Let’s create two files, authenticate.middleware.ts, authorize.middleware.ts.

We will use authenticate to check if user has a valid idToken, and the authorize to check if the user has the required privileges.

Note: The authenticate filter requires an Authorization header with the value in the following form:- Bearer <idToken>

Note: The idToken can be retrieved by signing-in to firebase using the REST API for firebase Authentication for the moment.

Proceeding further, we need to create a UsersController.ts file under modules →users that will contain the methods that our routes for “/users” path will utilize.

Here, “//RA” means the particular function requires admin privileges to perform its functionality.

This name of the methods define its functionality in this case.

getAllUsers() →Returns a list of all the users.
getUser() →Accepts an uid and returns the particular user.
updateUser() →Here we can perform many task, but in the current scope we will only set the displayName property of the user. You can play around with the function and find out all the fields that a user can have in firebase authentication.
createUser() →Creates an user.
createAdminUser() →Creates an user but with Admin privileges.
deleteUser() →Deletes the user whose uid is provided.
deleteUsers() →Deletes multiple users, uid array is fetched from body.
forceSignOut() →Forcibly revoke a users refresh token, so that their login can’t continue.
mapUserFromUserRecord() →An utility function, private to the file, which helps in extracting user from an UserRecord object returned by the admin sdk, returns a User object.

Here, we use customClaims to store the admin role for an user. These customClaims can only be retreived through the admin SDK. (I didn’t find any way to retrieve them from the client sdk, Kindly mention in the feedback if I am wrong.)

We need a router that can map different routes to the functions. For that purpose we create a file routes.ts in the same directory. The file contains the following.

Here, we define a configureRoutes function, which will take our express app and add the routes. We pass true to authorize where the route requires admin privilege to perform the task.

Similarly, we create two files, adminController.ts and routes.ts under modules →admin.

Finally, we add the following import statements to the index.ts file.

import { configureRoutes as configureRoutesForUsers } from './modules/users/routes';
import { configureRoutes as configureRoutesForAdmin } from './modules/admin/routes';

We listen for the endpoints by starting the server using the following piece of code:

app.listen(port, () => {
console.log('Server listening at port '+port);

Finally start the server on localhost using

npm start

We can use Postman to test the endpoints. Ex: http://localhost:8080/users/<uid>.

We can add users to the project by using the firebase console or by using the REST API for firebase. And thereafter we can retrieve the uid from the firebase console.

Note: For the first time, to add an admin, we can normally add an user and call the /admin/:uid/make endpoint by passing false to its authorize filter. After that we can revert the value to true.

Kindly refer to the following Github repository for the complete project files.

Kindly excuse for any mistakes, as this is my first article on Medium.com.

Thank You

A web developer passionate about the emerging new technologies with a strong attraction towards beautiful UIs.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store