Firebase Auth Emulator with Python

Last year, Google released Firebase Auth Emulator as a new component in Firebase Emulator. In case you haven’t heard, Firebase Emulator allows you to run/test a bunch of Firebase services in your local machine, namely:

  • Auth
  • Firestore
  • Realtime Database
  • Functions
  • Hosting
  • PubSub

⚠️ Now before you get too hyped, I need to remind you that despite of its awesomeness, Firebase Emulator is still in beta. So you need to expect some limitations and changes. There are some fair amount of documentation on how to use it but I still find some issues. I’m trying to share some of them and the solution/workaround that I found.

My use case is to build an emulator for a system that consist of a Python API server and a web client (email/password authentication). To be specific, I need to:

  • Validate & extract user ID from Firebase Auth Token sent in each secure request
  • Create user programatically so tester can initialize the system easily
  • Delete users programatically to reset the system easily before starting new test

Validate token

One of the limitation that I faced recently is: Python Firebase Admin SDK hasn’t supported Auth Emulator yet. So even if you can generate the firebase token quite easily from the client, it’s a bit tricky to validate it.

The workaround that I found is to let our Python server locally “validate” the Firebase Auth Token with PyJWT. Since we assume Firebase Auth is trusworthy, we just need the validation to just extract the UID from the token (and some other details if available). Finally, we create a mock user to allow the existing code works.

import jwt
from unittest import mock

# get token from request header
payload = jwt.decode(token, options={"verify_signature": False})
user = mock.Mock()
user.uid = payload['user_id']
if 'phone_number' in payload:
	user.phone_number = payload['phone_number']
if 'email' in payload:
	user.email = payload['email']

There is actually an endpoint that we supposed to be able to use to get the user data from the emulator. But for some reason, it doesn’t work. It keeps returning {'kind': 'identitytoolkit#GetAccountInfoResponse'}, even if we pass an invalid code.

Create user programmatically

While you can use the web portal to add new user, sometimes you need to do it programatically. For example when you want to create script that initialize users and maybe some data that refers to their ID. Luckily, it can be easily done using the REST APIs. The only trick is to know what you should put in the authorization header {'Authorization': 'Bearer owner'}. I couldn’t find it anywhere in the doc, but luckily I found it in a Github issue.

import requests

signup_url = 'http://localhost:9099/identitytoolkit.googleapis.com/v1/accounts:signUp'
signup_data = {
    "email": "yohanes@gultom.id",
    "password": "yohanes",
    "phoneNumber": "+6280989999", 
    "displayName": "Yohanes"
}
r = requests.post(signup_url, json=signup_data, headers={'Authorization': 'Bearer owner'})
user_data = r.json()
print(user_data)
# {'kind': 'identitytoolkit#SignupNewUserResponse', 'localId': 'mfSYLlDWhtTzIumnk9iUi4YSbjci', 'displayName': 'Yohanes', 'email': 'yohanes@gultom.id'}

While we are at it, the API to sign in with email/password is working in the same manner too. You can use it to generate auth token programatically

import requests

signin_url = 'http://localhost:9099/identitytoolkit.googleapis.com/v1/accounts:signInWithPassword'
signin_data = {
    "email": "yohanes@gultom.id",
    "password": "yohanes",
}
r = requests.post(signin_url, json=signin_data, headers={'Authorization': 'Bearer owner'})
res = r.json()
token = res['idToken']
print(token)

Delete all users

Delete users API is not available as the part of the actual Firebase Auth server. It is one of the exclusive APIs for emulator. This API itself may not be too useful except when you are creating script for cleaning up data or automated test.

import requests

FIRESTORE_PROJECT_ID = 'firebase-emulator-demo'
delete_users_url = 'http://localhost:9099/emulator/v1/projects/' + FIRESTORE_PROJECT_ID + '/accounts'
r = requests.delete(delete_users_url, headers={'Authorization': 'Bearer owner'})
print(r.json())
# {}

That’s all I have for now. Hopefully it can help anyone dealing with the Firebase Emulator Auth.

Cheers! 🍻

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments