'How to use Firebase REST API(Python) for authentication of a user?

I am using Firebase as backend for my Internet of Things app. Using python on my Raspberry Pi, I am storing data on Firebase. As of currently my database is public for r/w. I have created an dummy account using Console>Auth>Users. I want to use this account to sign in to my Firebase App through my Raspberry Pi using Python with REST or any lib.

Upon login, I will use "Database>Rule" to restrict user to r/w his data only. I am new completely new to Firebase! Also Old docs are deprecated at Firebase. I would like to know how to proceed with my app. I am unable to find any information on how to do this on Python or REST API.

https://firebase.google.com/docs/auth/ This is the new documentation I have found for authentication which contains no information for using REST API.

Is there anyway to achieve what I desire? Any help is appreciated.



Solution 1:[1]

Alfonso from the Firebase Auth team.

We currently do not have a supported or documented REST API for auth.

You can still create a project through the legacy console and use the old docs to learn how to mint your own custom auth tokens, and send them over to the database REST API for authentication.

Solution 2:[2]

I ran into this problem recently and for my purposes ended up making a monkey patch for firebase_admin, which adds a verify_user method to the main library. (I also put it on pypi, https://pypi.org/project/firebase_fave/, pip install firebase_fave)

# import several different ways to make the code read like it would as part of the package it belongs in
import firebase_admin
from firebase_admin._user_mgt import *
from firebase_admin.auth import _get_auth_service, AuthError
from firebase_admin import firestore


# helper to add methods
def _add_method(cls):
    def cls_decorator(func):
        @wraps(func)
        def copied(self, *args, **kwargs): # wrap so we don't bind the func
            return func(self, *args, **kwargs)
        setattr(cls, func.__name__, copied)
        return func
    return cls_decorator


# add password verify to user manager
@_add_method(firebase_admin._user_mgt.UserManager)
def verify_user(self, **kwargs):
    """Gets the user data corresponding to the provided data and verifies"""
    key, key_type = self.get_user(**kwargs)['email'], 'email'

    if 'password' in kwargs:
        password = kwargs.pop('password')
    else:
        password = ''

    payload = {key_type:key, 'password':password, "returnSecureToken": True}

    try:
        response = self._client.request('post', 'verifyPassword', json=payload)
    except requests.exceptions.RequestException as error:
        msg = 'Failed to get user by {0}: {1}.'.format(key_type, key)
        self._handle_http_error(INTERNAL_ERROR, msg, error)
    else:
        if not response:
            raise ApiCallError(
                USER_NOT_FOUND_ERROR,
                'No user record found for the provided {0}: {1}.'.format(key_type, key))
        return response


# as in firebase_admin, we want a convenience method as well
def _outer_verify_user(password, **kwargs):
    """Verifies a user given password and one of uid or email.
    Args:
        uid: A user ID string.
        email: user e-mail address.
        app: An App instance (optional).

    Returns:
        UserRecord: A UserRecord instance.

    Raises:
        ValueError: if both user ID and email are None, empty, or malformed
        AuthError: If an error occurs while deleting the user account.
    """
    app = kwargs.pop('app', None)
    user_manager = _get_auth_service(app).user_manager
    kwargs['password'] = password
    try:
        return user_manager.verify_user(**kwargs)
    except firebase_admin._user_mgt.ApiCallError as error:
        raise AuthError(error.code, str(error), error.detail)


# finally, apply this convenience method to the class.
firebase_admin.verify_user = _outer_verify_user

Solution 3:[3]

You can connect to Firebase using the REST API from Python like this.

Assuming you have the email and password for your user you can auth as follows:

url = 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=' + API_KEY
headers = {"Content-Type": "application/json"}
data = '{"email":"' + email+ '","password":"' + password + '","returnSecureToken":true}'
response = requests.post(url, data=data, headers=headers)

This will give you an auth token (amongst other things):

rjson = response.json()
idToken = rjson['idToken']

that you can then use in further API calls e.g. list documents in a Firestore collection (replacing {projectID} and {collectionName}):

headers = {"Authorization": "Bearer " + idToken}   
url = 'https://firestore.googleapis.com/v1/projects/{projectID}/databases/(default)/documents/{collectionName}'    
response = requests.get(url, headers=headers)

Access can then be controlled using your data access rules and users don't have scary access levels like the Admin SDK

The Google Docs explain how to get a token using the REST API here

And generally how to use the REST API here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alfonso Gomez Jordana Manas
Solution 2 Andrew Manion
Solution 3 leafcutter