2

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.

Ryan Cyrus
  • 309
  • 5
  • 14

3 Answers3

2

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.

  • Thanks! :) As i need Firebase Cloud Messaging, I am opting for newer Firebase :) Is REST API is being written/updated for new Firebase? If you are allowed to comment on that. :) – Ryan Cyrus Jun 02 '16 at 16:35
  • 3
    Boo! Please make a supported REST API for auth in Firebase. – Praxiteles Jun 02 '16 at 20:11
  • I am passing all this feedback to the team :) @Ryan: for cloud messaging there is a REST API for triggering notifications; is that what you need? – Alfonso Gomez Jordana Manas Jun 02 '16 at 20:18
  • 1
    See http://stackoverflow.com/questions/37408684/is-it-still-possible-to-do-server-side-verification-of-tokens-in-firebase-3/37492640#37492640 for a way to make authenticated REST calls to the Firebase Database – Frank van Puffelen Jun 16 '16 at 14:20
  • @AlfonsoGomezJordanaManas Are you allowed to say how long the legacy custom auth tokens will be supported for? The current console says that they're deprecated. – Keith Aylwin Dec 28 '16 at 19:25
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
0

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

leafcutter
  • 747
  • 7
  • 14