{"id":13805924,"url":"https://github.com/joegasewicz/flask-jwt-router","last_synced_at":"2025-08-22T00:30:53.259Z","repository":{"id":34925281,"uuid":"191003928","full_name":"joegasewicz/flask-jwt-router","owner":"joegasewicz","description":"Flask JWT Router is a Python library that adds authorised routes to a Flask app.","archived":false,"fork":false,"pushed_at":"2023-02-16T04:08:37.000Z","size":3047,"stargazers_count":54,"open_issues_count":30,"forks_count":11,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-10T01:17:13.958Z","etag":null,"topics":["flask","jwt","pyjwt","sqlalchemy"],"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/joegasewicz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-06-09T12:30:31.000Z","updated_at":"2023-11-12T16:30:48.000Z","dependencies_parsed_at":"2024-01-03T01:20:34.605Z","dependency_job_id":"7df7d93f-2224-470b-a8ea-d89cc0c8cbbd","html_url":"https://github.com/joegasewicz/flask-jwt-router","commit_stats":{"total_commits":360,"total_committers":8,"mean_commits":45.0,"dds":0.1333333333333333,"last_synced_commit":"17ad0e184e5692d48ed7fefd35c0d8a5b435c189"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joegasewicz%2Fflask-jwt-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joegasewicz%2Fflask-jwt-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joegasewicz%2Fflask-jwt-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joegasewicz%2Fflask-jwt-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joegasewicz","download_url":"https://codeload.github.com/joegasewicz/flask-jwt-router/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230039162,"owners_count":18163364,"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":["flask","jwt","pyjwt","sqlalchemy"],"created_at":"2024-08-04T01:01:06.313Z","updated_at":"2024-12-20T06:06:18.858Z","avatar_url":"https://github.com/joegasewicz.png","language":"Python","funding_links":[],"categories":["Third-Party Extensions"],"sub_categories":["Auth"],"readme":"[![Python package](https://github.com/joegasewicz/flask-jwt-router/actions/workflows/python-package.yml/badge.svg)](https://github.com/joegasewicz/flask-jwt-router/actions/workflows/python-package.yml)\n[![PyPI version](https://badge.fury.io/py/flask-jwt-router.svg)](https://badge.fury.io/py/flask-jwt-router)\n[![codecov](https://codecov.io/gh/joegasewicz/Flask-JWT-Router/branch/master/graph/badge.svg)](https://codecov.io/gh/joegasewicz/Flask-JWT-Router)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/c15de26af47d48448392eaa5e0e41bcf)](https://www.codacy.com/manual/joegasewicz/Flask-JWT-Router?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=joegasewicz/Flask-JWT-Router\u0026amp;utm_campaign=Badge_Grade)\n[![Documentation Status](https://readthedocs.org/projects/flask-jwt-router/badge/?version=latest)](https://flask-jwt-router.readthedocs.io/en/latest/?badge=latest)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/flask-jwt-router)\n[![GitHub license](https://img.shields.io/github/license/joegasewicz/flask-jwt-router)](https://github.com/joegasewicz/flask-jwt-router/blob/master/LICENSE.txt)\n\n![Flask JWT Router](assets/logo.png?raw=true \"Title\")\n\nRead the docs: [Flask-JWT-Router](https://flask-jwt-router.readthedocs.io/en/latest/) \n\n# Flask JWT Router\n\nFlask JWT Router is a Python library that adds authorised routes to a Flask app. Both basic \u0026 Google's OAuth2.0 authentication\nis supported.\n\n## ![Google-Cloud](assets/Google-Cloud1.png) Google's OAuth2.0 supported\n\n\n## Quik Start\n```python\nfrom flask_jwt_router import JwtRoutes\n\njwt_routes = JwtRoutes()\njwt_routes.init_app(\n    app,\n    entity_models=[MyModel],\n)\n```\n\n\nNow your front end needs a token. Create an endpoint \u0026\nreturn a new access token from the clients header *code*.\nFor Example::\n```python\nfrom flask import request\n\n@app.routes(\"/login\", methods=[\"POST\"])\ndef login():\n    jwt_routes.google.oauth_login(request) # Pass in Flask's request\n```\n\n\nNow, the next time your front-end requests authorised resources\nflask-jwt-router will authenticate with this access token until\nit expires.\n\n## Installation\n\nStable version\n```bash\npip install flask-jwt-router\n```\n\n## Basic Usage\n ```python\nfrom flask import Flask\nfrom flask_jwt_router import JwtRoutes\n\napp = Flask(__name__)\n# You are required to always set a unique SECRET_KEY for your app\napp.config[\"SECRET_KEY\"] = \"your_app_secret_key\"\n\nJwtRoutes(app)\n\n# If you're using the Flask factory pattern:\njwt_routes = JwtRoutes()  # Example with *entity_model - see below\n\ndef create_app(config):\n    ...\n    jwt_routes.init_app(app)\n\n```\n\n## Whitelist Routes\n```python\napp.config[\"WHITE_LIST_ROUTES\"] = [\n    (\"POST\", \"/register\"),\n]\n\n@app.route(\"/register\", methods=[\"POST\"])\ndef register():\n    return \"I don't need authorizing!\"\n```\n\n## Prefix your api name to whitelisted routes\n```python\n    # All routes will\napp.config[\"JWT_ROUTER_API_NAME\"] = \"/api/v1\"\napp.config[\"WHITE_LIST_ROUTES\"] = [\n    (\"POST\", \"/register\"),\n]\n\n@app.route(\"/api/v1/register\", methods=[\"POST\"])\ndef register():\n    return \"I don't need authorizing!\"\n   \n```\n\n## Bypass Flask-JWT-Router on specified routes\n```python\n    # Define homepage template routes for example on JWT_IGNORE_ROUTES \n    # \u0026 still get to use the api name on request handlers returning resources\n    app.config[\"IGNORED_ROUTES\"] = [\n        (\"GET\", \"/\")\n    ]\n```\n\n## Declare an entity model\n```python\n# Create your entity model (example uses Flask-SqlAlchemy)\nclass UserModel(db.Model):\n    __tablename__ = \"users\"\n    id = db.Column(db.Integer, primary_key=True)\n    name = db.Column(db.String)\n    \n# You can define the primary key name with `ENTITY_KEY` on Flask's config\napp.config[\"ENTITY_KEY\"] = \"user_id\"\n\n# (`id` is used by default)\nJwtRoutes(app, entity_models=[UserModel, TeacherModel, ...etc])\n\n# Or pass later with `init_app`\ndef create_app(config):\n    ...\n    jwt_routes.init_app(app, entity_models=[UserModel, TeacherModel, ...etc])\n\n```\n\n## Authorization\n```python\nfrom your_app import jwt_routes\n\n# white list the routes\napp.config[\"WHITE_LIST_ROUTES\"] = [\n    (\"POST\", \"/register\"),\n    (\"POST\", \"/login\"),\n]\n\n@app.route(\"/login\", methods=[\"POST\"])\ndef register():\n    \"\"\"I'm registering a new user \u0026 returning a token!\"\"\"\n    return jsonify({\n        \"token\": jwt_routes.create_token(entity_id=1, table_name='users')\n    })\n\n@app.route(\"/your_resource\", methods=[\"POST\"])\ndef login():\n    \"\"\"I'm authorized \u0026 updating my token!\"\"\"\n    return jsonify({\n        \"token\": jwt_routes.update_token(entity_id=1)\n    })\n```\n\n*Warning: The `table_name` must be the same as your tablename or `__tablename__` attribute's value.\n(With SqlAlchemy, you can define a `__tablename__` attribute directly or else\nthe name is derived from your entity’s database table name).\n\n## Setting the Token Expire Duration\nThere are two ways to set the expire duration of the JWT.\n\nfrom your app config\n```python\n        # Set the token expire duration to 7 days\n        app.config[\"JWT_EXPIRE_DAYS\"] = 7\n```\ncalling the `set_exp`\n```python\n\n        # Set the token expire duration to 14 days\n        jwt_routes = JwtRoutes()\n        # jwt_routes.init_app( ...etc\n        jwt_routes.set_exp(expire_days=14)\n```\nBy default the expire duration is set to 30 days\n\n## Create \u0026 update Tokens on Routes\nCreate a new entity \u0026 return a new token\n```python\n@app.route(\"/register\", methods=[\"POST\"])\n    def register():\n        user_data = request.get_json()\n        try:\n            user = UserModel(**user_data)\n            user.create_user() # your entity creation logic\n\n            # Here we pass the id as a kwarg to `create_token`\n            token: str = jwt_routes.create_token(entity_id=user.id, table_name=\"users\")\n\n            # Now we can return a new token!\n            return {\n                \"message\": \"User successfully created.\",\n                \"token\": str(token),  # casting is optional\n            }, 200\n```\nAccess entity on Flask's global context\n```python\n    from app import app, jwt_routes\n\n    # Example uses Marshmallow to serialize entity object\n    class EntitySchema(Schema):\n        id = fields.Integer()\n        name = fields.String()\n\n    @app.route(\"/login\", methods=[\"GET\"])\n    def login():\n        user_data = g.get(\"users\") # This is your SqlAlchemy `__tablename__` or the default name.\n        try:\n            user_dumped = UserSchema().dump(user_data)\n        except ValidationError as _:\n           return {\n                       \"error\": \"User requested does not exist.\"\n                   }, 401\n        return {\n            \"data\": user_dumped,\n            \"token\": jwt_routes.update_token(entity_id=user_data.id),\n        }, 200\n        \n```\nIf you are handling a request with a token in the headers you can call::\n```python\n    jwt_routes.update_token(entity_id=user_data.id)\n```\n\nIf you are handling a request without a token in the headers you can call::\n\n```python\n    jwt_routes.create_token(entity_id=user_data.id, table_name=\"users\")\n```\n\nAn Example configuration for registering \u0026 logging in users of different types:\n```python\n    app.config[\"IGNORED_ROUTES\"] = [(\"GET\", \"/\")]\n    app.config[\"JWT_ROUTER_API_NAME\"] = \"/api/v1\"\n    app.config[\"WHITE_LIST_ROUTES\"] = [\n        (\"POST\", \"/auth/user\"), (\"POST\", \"/auth/user/login\"),\n        (\"POST\", \"/auth/teacher\"), (\"POST\", \"/auth/teacher/login\"),\n    ]\n    \n    # Optionally, you can pass your models to Flask's config:\n    app.config[\"ENTITY_MODELS\"] = [ UserModel, TeacherModel, ...etc ]\n```\n\n## JSON Web Token setup\nTo send the JSON web token from your front end, you will need to pass a `Bearer` string in your authorization header.\nFor example:\n```javascript\n    fetch(url, {\n        headers: {\n            Authorization: \"Bearer \u003cmy_token\u003e\",\n        }\n    })\n```\n### Routing without headers\nIf you require calling a resource without passing headers, then you can use the ``auth`` query param (useful when streaming video files):\n```python\n    url = \"http://example.com/cars?auth=my_token\"\n```\n\n### Google OAuth 2.0 Quick Start\n\nRead the detailed instructions here: [Flask-JWT-Router](https://flask-jwt-router.readthedocs.io/en/latest/google.html)\n```python\nfrom flask_jwt_router import Google, JwtRoutes\n\noauth_options = {\n    \"client_id\": \"\u003cCLIENT_ID\u003e\",\n    \"client_secret\": \"\u003cCLIENT_SECRET\u003e\",\n    \"redirect_uri\": \"http://localhost:3000\",\n    \"tablename\": \"users\",\n    \"email_field\": \"email\",\n    \"expires_in\": 3600,\n}\n\njwt_routes = JwtRoutes()\njwt_routes.init_app(\n    app,\n    google_oauth=oauth_options,\n    strategies=[Google],\n    entity_models=[MyModel],\n)\n```\n\n## Google OAuth 2.0 with ReactJS\nFlask-JWT-Router supports auth Google's OAuth 2.0 Single Sign On strategy if you are using React only.\n(We will provide Google's OAuth 2.0 Single Sign On strategy for server to server as soon as possible!).\n\n### Quick Start\nCreate a login route for Google's OAuth 2.0\n```python\n   @app.route(\"/api/v1/google_login\", methods=[\"POST\"])\n    def google_login():\n        google = jwt_routes.get_strategy(\"Google\")\n        data = google.oauth_login(request)\n        return data, 200\n```\n\nIf your app requires multiple redirect uri's then\nyou can use the `redirect_uri` kwarg to assign a uri for the current\nrequest handler. For example:\n```python\ngoogle = jwt_routes.get_strategy(\"Google\")\ndata = google.oauth_login(request, redirect=\"http://another_redirect.com\")\n```\n\nWe have created a ReactJS library specifically for Flask-JWT-Router - [react-google-oauth2.0](https://github.com/joegasewicz/react-google-oauth2.0)\nIn your React app directory install react-google-oauth2.0:\n```bash\nnpm install react-google-oauth2 --save \n```\n\n## Testing\n\nTesting OAuth2.0 in a Flask app is non-trivial, especially if you rely on Flask-JWT-Router\nto append your user onto Flask's global context (or `g`). Therefore we have provided a\nutility method that returns a headers Dict that you can then use in your test view handler\nrequest. This example is using the Pytest library:\n```python\n    from flask_jwt_router import (\n        BaseJwtRoutes,\n        JwtRoutes,\n        Google,\n        GoogleTestUtil,\n        TestRoutingMixin,\n    )\n\n    class TestJwtRoutes(TestRoutingMixin, BaseJwtRoutes):\n        pass\n    \n    \n    if not Config.E2E_TEST:\n        jwt_routes = JwtRoutes()\n    else:\n        jwt_routes = TestJwtRoutes()\n\n    if not config.E2E_TEST:\n        jwt_routes.init_app(\n            app,\n            google_oauth=oauth_options,\n            strategies=[Google],\n            entity_models=[MyModel],\n        )\n    else:\n        jwt_routes.init_app(\n            app,\n            google_oauth=oauth_options,\n            strategies=[GoogleTestUtil],\n            entity_models=[MyModel],\n        )\n```\n\n```python\n    @pytest.fixture()\n    def client():\n        # See https://flask.palletsprojects.com/en/1.1.x/testing/ for details\n\n\n    def test_blogs(client):\n        google = jwt_routes.get_strategy(\"GoogleTestUtil\")\n        user_headers = google.create_test_headers(email=\"user@gmail.com\")\n        rv = client.get(\"/blogs\", headers=user_headers)\n```\n\nIf you are not running a db in your tests, then you can use the `entity` kwarg.\nFor example:\n\n```python\n# user is an instantiated SqlAlchemy object\ngoogle = jwt_routes.get_strategy(\"GoogleTestUtil\")\nuser_headers = google.create_test_headers(email=\"user@gmail.com\", entity=user)\n# user_headers: { \"X-Auth-Token\": \"Bearer \u003cGOOGLE_OAUTH2_TEST\u003e\" }\n```\nIf you require more than one request to a Flask view handler in a single unit test, then set\nthe *scope* kwarg to **application**. (Default is *function*). If you are testing different \nentities within a single unit test method or function then you must pass in your entity.\nFor example:\n```python\nmy_entity = User(email=\"user@gmail.com\") # If you're testing against a real db, make sure this is an entry in the db\ngoogle = jwt_routes.get_strategy(\"GoogleTestUtil\")\n_ = google.create_test_headers(email=\"user@gmail.com\", scope=\"application\", entity=my_entity)\n\n```\n\n## Authors\n\n* **joegasewicz** - *Initial work* - [@joegasewicz](https://twitter.com/joegasewicz)\n* **Kousik Mitra** - *Initial work* - [@kousikmitra](https://github.com/kousikmitra)\n\n## Contributing\nPull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.\n\nPlease make sure to update tests as appropriate.\n\nMake sure you have Python versions: `3.6`,  `3.7`,  `3.8`\nThen run:\n```python\n    tox\n```\n\nTo check the docs look good locally you can run:\n```bash\n    make html\n```\n\n## License\n[MIT](https://choosealicense.com/licenses/mit/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoegasewicz%2Fflask-jwt-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoegasewicz%2Fflask-jwt-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoegasewicz%2Fflask-jwt-router/lists"}