from flask import abortfrom firebase_admin import authdef test_firebase_auth(request): authorization = request.headers.get('Authorization') # authorization = request.headers['Authorization'] id_token = None if authorization and authorization.startswith('Bearer '): id_token = authorization.split('Bearer ')[1] else: abort(401) try: decoded_token = auth.verify_id_token(id_token) uid = decoded_token['uid'] # log.info(decoded_token) return uid except Exception as e: # ValueError or auth.AuthError abort(401)
requirements.txt
# https://pypi.org/project/firebase-admin/
firebase-admin==2.16.0
Test Firebase Auth from Web/Javascript
Create another cloud functions to serve html/javascript to perform testing.
from flask import render_templatedef test_firebase_auth_ui(request): return render_template('test_firebase_auth_ui.html')
Content of templates/test_firebase_auth_ui.html
.
- Make sure
test_firebase_auth_ui.html
is intemplates
directory. - We shall use Firebase Auth Web/Javascript client with Email/Password authentication for testing.
- Enable Email/Password Authentication at Firebase Console
-> Authentication -> Sign-in method -> Email/Password (Provider)
. - Get
firebaseConfig
fromFirebae Console -> Project Overview -> Add app -> Web
. - Deploy both
test_firebase_auth
andtest_firebase_auth_ui
as cloud functions to perform the testing. - Access
[SERVER]/test_firebase_auth_ui
. ClickCreate User
for first time, then clickSign In
buton for subsequent testing. Observe Chrome Console for the messages.
<!doctype html><html lang="en"> <head> <meta charset="utf-8"> <title>Test Firebase Auth</title> </head> <body> <h1>Test Firebase Auth</h1> <button id="create-user-button">Create User</button> <button id="signin-button">Sign In</button> <script src="https://www.gstatic.com/firebasejs/5.10.0/firebase-app.js"></script> <script src="https://www.gstatic.com/firebasejs/5.10.0/firebase-auth.js"></script> <script> var firebaseConfig = { apiKey: "AIza...", authDomain: "[PROJECT_ID].firebaseapp.com", databaseURL: "https://[PROJECT_ID].firebaseio.com", projectId: "[PROJECT_ID]", storageBucket: "[PROJECT_ID].appspot.com", messagingSenderId: "2401..." }; firebase.initializeApp(firebaseConfig); document.addEventListener('DOMContentLoaded', function() { console.log('init'); var EMAIL = "[email protected]" var PASSWORD = "test1234" var TEST_AUTH_URL = '/test_firebase_auth' var testCloudFunctionAuth = function(credential) { credential.user.getIdToken().then(function(token) { var req = new XMLHttpRequest(); req.onreadystatechange = function() { if (this.readyState == XMLHttpRequest.DONE) { if (this.status == 200) console.log(`done: ${this.responseText}`); else console.log(`error: ${this.status}`); } } req.open('GET', TEST_AUTH_URL, true); req.setRequestHeader('Authorization', 'Bearer ' + token); req.send(); }) } var createUserButton = document.getElementById('create-user-button'); createUserButton.addEventListener('click', function() { console.log('createUserButton.click') firebase.auth().createUserWithEmailAndPassword(EMAIL, PASSWORD).then(function(credential) { console.log('create user success'); testCloudFunctionAuth(credential); }).catch(function(error) { console.error(`${error.code}: ${error.message}`) }); }); var signInButton = document.getElementById('signin-button'); signInButton.addEventListener('click', function() { console.log('signInButton.click') firebase.auth().signInWithEmailAndPassword(EMAIL, PASSWORD).then(function(credential) { console.log('signin success'); testCloudFunctionAuth(credential); }).catch(function(error) { console.error(`${error.code}: ${error.message}`) }); }); }); </script> </body></html>
Wrap Firebase Authentication as Python Decorators
from functools import wrapsfrom flask import abortfrom firebase_admin import authinit_firebase()def firebase_auth_required(f): @wraps(f) def wrapper(request): authorization = request.headers.get('Authorization') id_token = None if authorization and authorization.startswith('Bearer '): id_token = authorization.split('Bearer ')[1] else: abort(401) try: decoded_token = auth.verify_id_token(id_token) except Exception as e: # ValueError or auth.AuthError abort(401) return f(request, decoded_token) return wrapper@firebase_auth_requireddef test_firebase_auth(request, decoded_token): return decoded_token['uid']
NOTE: For init_firebase
, refer Initialize firebase-admin.
References:
- https://firebase.google.com/docs/auth/admin/verify-id-tokens
- https://firebase.google.com/docs/reference/admin/python/firebase_admin.auth
- https://github.com/firebase/functions-samples/tree/master/authorized-https-endpoint
- https://firebase.google.com/docs/auth/web/password-auth
- https://firebase.google.com/docs/reference/js/firebase.auth.Auth.html