Search code examples
pythonfirebaseoauthgoogle-oauthjwt

Fail to authorize using ServiceAccountCredentials for calls to Firebase (REST API / python)


I always get 401 error trying to fetch Firebase resource and passing access token. I cannot get what am I doing wrong.

So I follow this manual: I created service account, then create ServiceAccountCredentials object, passing scope https://www.googleapis.com/auth/firebase. Then I get token from created object and pass it as access_token query parameter, as stated in docs, trying fetch data from my Firebase DB. But I keep getting 401 error (unauthorized). Token, by the way, seems to be invalid if check in tool like jsonwebtoken (probably I do something wrong there / provide incorrect secret?).

So, my code is like this:

import httplib2
from oauth2client.service_account import ServiceAccountCredentials

credentials = ServiceAccountCredentials.from_json_keyfile_name('/path/auth.json', scopes=['https://www.googleapis.com/auth/firebase'])
token = credentials.get_access_token().access_token
http = httplib2.Http()
result = http.request('https://my-project.firebaseio.com/srv.json?access_token=%s' % token)

And result body always is {"error" : "Unauthorized request."} along with 401 HTTP status code.


Solution

  • I think your scopes were not sufficient. Here is a end to end example I got working using credentials and the credentials.authorize http wrapper

    from oauth2client.service_account import ServiceAccountCredentials
    from httplib2 import Http
    import json
    
    _BASE_URL = 'https://my-app-id.firebaseio.com'
    _SCOPES = [
        'https://www.googleapis.com/auth/userinfo.email',
        'https://www.googleapis.com/auth/firebase.database'
    ] 
    
    # Get the credentials to make an authorized call to firebase    
    credentials = ServiceAccountCredentials.from_json_keyfile_name(
        _KEY_FILE_PATH, scopes=_SCOPES)
    
    # Wrap the http in the credentials.  All subsequent calls are authenticated
    http_auth = credentials.authorize(Http())
    
    def post_object(path, objectToSave):
      url = _BASE_URL + path
    
      resp, content = http_auth.request(
          uri=url,
          method='POST',
          headers={'Content-Type': 'application/json'},
          body=json.dumps(objectToSave),
      )
    
      return content
    
    objectToPost = {
      'title': "title",
      'message': "alert"
    }
    
    print post_object('/path/to/write/to.json', objectToPost)