{"id":15521354,"url":"https://github.com/andrewrosss/flask-firebase-admin","last_synced_at":"2025-04-23T03:51:15.995Z","repository":{"id":53611208,"uuid":"301089382","full_name":"andrewrosss/flask-firebase-admin","owner":"andrewrosss","description":"Add Firebase (a Firebase Admin app) to a Flask application","archived":false,"fork":false,"pushed_at":"2021-09-09T18:53:01.000Z","size":135,"stargazers_count":27,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-14T17:48:04.872Z","etag":null,"topics":["authentication","firebase","firebase-admin","firebase-authentication","flask","flask-application","jwt","protected-routes"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andrewrosss.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-10-04T09:30:41.000Z","updated_at":"2024-09-04T12:27:36.000Z","dependencies_parsed_at":"2022-08-26T04:43:09.723Z","dependency_job_id":null,"html_url":"https://github.com/andrewrosss/flask-firebase-admin","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewrosss%2Fflask-firebase-admin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewrosss%2Fflask-firebase-admin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewrosss%2Fflask-firebase-admin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewrosss%2Fflask-firebase-admin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andrewrosss","download_url":"https://codeload.github.com/andrewrosss/flask-firebase-admin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250366685,"owners_count":21418768,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","firebase","firebase-admin","firebase-authentication","flask","flask-application","jwt","protected-routes"],"created_at":"2024-10-02T10:34:03.420Z","updated_at":"2025-04-23T03:51:15.957Z","avatar_url":"https://github.com/andrewrosss.png","language":"Python","readme":"# Flask Firebase Admin\n\nAdd Firebase (a Firebase Admin app) to a Flask application.\n\n[![PyPI Version](https://img.shields.io/pypi/v/flask-firebase-admin.svg)](https://pypi.org/project/flask-firebase-admin/)\n[![Tests](https://github.com/andrewrosss/flask-firebase-admin/actions/workflows/test.yaml/badge.svg)](https://github.com/andrewrosss/flask-firebase-admin/actions/workflows/test.yaml)\n[![codecov](https://codecov.io/gh/andrewrosss/flask-firebase-admin/branch/master/graph/badge.svg?token=JM7PL13H59)](https://codecov.io/gh/andrewrosss/flask-firebase-admin)\n[![Type Check](https://github.com/andrewrosss/flask-firebase-admin/actions/workflows/type-check.yaml/badge.svg)](https://github.com/andrewrosss/flask-firebase-admin/actions/workflows/type-check.yaml)\n[![Code Style](https://github.com/andrewrosss/flask-firebase-admin/actions/workflows/lint.yaml/badge.svg)](https://github.com/andrewrosss/flask-firebase-admin/actions/workflows/lint.yaml)\n\n## Installation\n\n```bash\npip install flask-firebase-admin\n```\n\n## Quickstart\n\nIn the simplest case, let's protect a route, specifically, we'll require a user to provide a firebase jwt to one of our routes:\n\n```python\nfrom flask import Flask, request\nfrom flask_firebase_admin import FirebaseAdmin\n\napp = Flask(__name__)\nfirebase = FirebaseAdmin(app)  # uses GOOGLE_APPLICATION_CREDENTIALS\n\n@app.route(\"/unprotected\")\ndef unprotected():\n    return {\"message\": \"Hello anonymous user!\"}\n\n@app.route(\"/protected\")\n@firebase.jwt_required  # This route now requires authorization via firebase jwt\ndef protected():\n    # By default JWT payload is stored under request.jwt_payload\n    return {\"message\": f\"Hello {request.jwt_payload['email']}!\"}\n\nif __name__ == \"__main__\":\n    app.run(debug=True)\n```\n\nAssuming the code above is located in a module named `app.py`, start the Flask application:\n\n```bash\nGOOGLE_APPLICATION_CREDENTIALS=\"/path/to/service_account.json\" python app.py\n```\n\nAnd in a separate terminal window, ping the unprotected route:\n\n```bash\n$ curl http://127.0.0.1:5000/unprotected\n{\n  \"message\": \"Hello anonymous user!\"\n}\n```\n\nLooks good. Now the protected route:\n\n```bash\n$ curl http://127.0.0.1:5000/protected\n{\n  \"error\": {\n    \"message\": \"No credentials provided\"\n  }\n}\n```\n\nOK, makes sense. Now with some credentials:\n\n```bash\n$ TOKEN=\"your-firebase-token ...\"\n$ curl -H \"Authorization: Bearer ${TOKEN}\" http://127.0.0.1:5000/protected\n{\n  \"message\": \"Hello \u003cyour@email.com\u003e!\"\n}\n```\n\nExcellent. We now have a application with routes (one route) which require the user to provide their Firebase JWT to access!\n\nInternally the `jwt_required` method provided by the `FirebaseAdmin` object calls the `firebase_admin.auth.verify_id_token` function which returns a dictionary of key-value pairs parsed from the decoded JWT. This dictionary is accessible via the `request` object provided by flask, specifically, this information is attached to the `request.jwt_payload` attribute by default.\n\n## Configuration\n\n\u003e **Note:** The following groups of configuration parameters are mutually exclusive:\n\u003e\n\u003e - `FIREBASE_ADMIN_APP` (This config parameter takes precendence and if specified then configuration from the other group is ignored)\n\u003e\n\u003e   ***\n\u003e\n\u003e - `FIREBASE_ADMIN_CREDENTIAL`\n\u003e\n\u003e   `FIREBASE_ADMIN_OPTIONS`\n\u003e\n\u003e   `FIREBASE_ADMIN_NAME`\n\u003e\n\u003e   `FIREBASE_ADMIN_RAISE_IF_APP_EXISTS`\n\nThe `FirebaseAdmin` object can be configured in the following ways:\n\n- `FIREBASE_ADMIN_CREDENTIAL`\n\n  **Defaults to `None`**. This is the credential passed to the call to `firebase_admin.initialize_app`. When this parameter is None the Firebase Admin application tries to initialize using `GOOGLE_APPLICATION_CREDENTIALS`. If initializing the Firebase Admin app with the `GOOGLE_APPLICATION_CREDENTIALS` environment variable is undesirebale, credentials can be created manually, for example:\n\n  ```python\n  app = Flask(__name__)\n  app.config[\"FIREBASE_ADMIN_CREDENTIAL\"] = credentials.Certificate(\"/path/to/key.json\")\n  firebase = FirebaseAdmin(app)  # no longer uses GOOGLE_APPLICATION_CREDENTIALS\n  ```\n\n  Or perhaps something like:\n\n  ```python\n  app = Flask(__name__)\n  cert = {\n      \"type\": \"service_account\",\n      \"project_id\": os.getenv(\"PROJECT_ID\"),\n      \"private_key_id\": os.getenv(\"PRIVATE_KEY_ID\"),\n      \"private_key\": os.getenv(\"PRIVATE_KEY\"),\n      \"client_email\": os.getenv(\"CLIENT_EMAIL\"),\n      \"client_id\": os.getenv(\"CLIENT_ID\"),\n      \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n      \"token_uri\": \"https://oauth2.googleapis.com/token\",\n      \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n      \"client_x509_cert_url\": os.getenv(\"CLIENT_X509_CERT_URL\"),\n  }\n  app.config[\"FIREBASE_ADMIN_CREDENTIAL\"] = credentials.Certificate(cert)\n  firebase = FirebaseAdmin(app)  # no longer uses GOOGLE_APPLICATION_CREDENTIALS\n  ```\n\n- `FIREBASE_ADMIN_OPTIONS`\n\n  **Defaults to `None`**. This config is passed directly to `admin.initialize_app()` as the second `options` argument. From the Firebase Admin SDK docs: _A dictionary of configuration options (optional). Supported options include **databaseURL**, **storageBucket**, **projectId**, **databaseAuthVariableOverride**, **serviceAccountId** and **httpTimeout**. If httpTimeout is not set, the SDK uses a default timeout of 120 seconds._\n\n- `FIREBASE_ADMIN_NAME`\n\n  **Defaults to `'[DEFAULT]'`**. This config is passed directly to `admin.initialize_app()` as the third `name` argument.\n\n- `FIREBASE_ADMIN_AUTHORIZATION_SCHEME`\n\n  **Defaults to `'Bearer'`**. This is the authorization scheme expected by the `FirebaseAdmin` object. Changing this parameter changes the format of the auth header that is required by the client. For example, if we set this to `'JWT'` we would then need to include an authorization header of the form: `Authorization: JWT \u003ctoken\u003e` when making requests to protected routes.\n\n- `FIREBASE_ADMIN_CHECK_REVOKED`\n\n  **Defaults to `True`**. This parameter is passed as the `check_revoked` argument in the call to `firebase_admin.auth.verify_id_token()`.\n\n- `FIREBASE_ADMIN_PAYLOAD_ATTR`\n\n  **Defaults to `'jwt_payload'`**. This is attribute on the flask `request` object from which we can access the JWT payload data. If we were to change this to, say, `'jwt'` we would then access the JWT payload using `request.jwt`\n\n- `FIREBASE_ADMIN_RAISE_IF_APP_EXISTS`\n\n  **Defaults to `True`**. Internally, `flask-firebase-admin` calls `admin.initialize_app()`, if the app with the configured name already exists the Firebase Admin SDK raises a `ValueError` exception. When this config variable is set to `False`, `flask-firebase-admin` will catch this error, get, and subsequently use the existing admin app by the given name.\n\n- `FIREBASE_ADMIN_APP`\n\n  **Defaults to `None`**. This is a way to explicity provided the `FirebaseAdmin` extension with a particular firebase admin app to use. For example:\n\n  ```python\n  import firebase_admin\n  from flask import Flask\n  from flask_firebase_admin import FirebaseAdmin\n\n  # elsewhere ...\n  default_admin_app = firebase_admin.initialize_app()\n  other_admin_app = firebase_admin.initialize_app(other_creds, other_options, other_name)\n\n  # then ...\n  app = Flask(__name__)\n  app.config[\"FIREBASE_ADMIN_APP\"] = other_admin_app\n\n  # now firebase.jwt_required will use other_admin_app for authentication\n  firebase = FirebaseAdmin(app)\n  ```\n\nAn example using more of the available configuration:\n\n```python\nfrom flask import Flask, request\nfrom firebase_admin import credentials\nfrom flask_firebase_admin import FirebaseAdmin\n\napp = Flask(__name__)\napp.config[\"FIREBASE_ADMIN_CREDENTIAL\"] = credentials.Certificate(\"/path/to/key.json\")\napp.config[\"FIREBASE_ADMIN_AUTHORIZATION_SCHEME\"] = \"JWT\"\napp.config[\"FIREBASE_ADMIN_CHECK_REVOKED\"] = False  # don't check for revoked tokens\napp.config[\"FIREBASE_ADMIN_PAYLOAD_ATTR\"] = \"firebase_jwt\"\n\n# initialized with credentials defined above, not GOOGLE_APPLICATION_CREDENTIALS\nfirebase = FirebaseAdmin(app)\n\n@app.route(\"/unprotected\")\ndef unprotected():\n    return {\"message\": \"Hello anonymous user!\"}\n\n@app.route(\"/protected\")\n@firebase.jwt_required  # This route now requires authorization via firebase jwt\ndef protected():\n    # we now access the JWT payload using request.firebase_jwt\n    return {\"message\": f\"Hello {request.firebase_jwt['email']}!\"}\n\nif __name__ == \"__main__\":\n    app.run(debug=True)\n```\n\nTo call the `/protected` route we have to update our auth header that we sent originally:\n\n```bash\n$ TOKEN=\"your-firebase-token ...\"\n$ curl -H \"Authorization: JWT ${TOKEN}\" http://127.0.0.1:5000/protected\n{\n  \"message\": \"Hello \u003cyour@email.com\u003e!\"\n}\n```\n\n## Extras\n\nFor convenience, the modules in the `firebase_admin` package are aliased as class-level attributes on the `FirebaseAdmin` object. For example:\n\n```python\nfrom flask import Flask\nfrom flask_firebase_admin import FirebaseAdmin\n\napp = Flask(__name__)\nfirebase = FirebaseAdmin(app)\ndb = firebase.firestore.client()  # \u003c-- connect firestore client\n\n@app.route(\"/unprotected\")\ndef unprotected():\n    return {\"message\": \"Hello anonymous user!\"}\n\n@app.route(\"/protected\")\n@firebase.jwt_required\ndef protected():\n    # do stuff in firestore using the db object defined above.\n    ...\n\nif __name__ == \"__main__\":\n    app.run(debug=True)\n```\n\n## Contributing\n\n1. Have or install a recent version of `poetry` (version \u003e= 1.1)\n1. Fork the repo\n1. Setup a virtual environment (however you prefer)\n1. Run `poetry install`\n1. Run `pre-commit install`\n1. Add your changes (adding/updating tests is always nice too)\n1. Commit your changes + push to your fork\n1. Open a PR\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrewrosss%2Fflask-firebase-admin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandrewrosss%2Fflask-firebase-admin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrewrosss%2Fflask-firebase-admin/lists"}