Flask JWT Router is a Python library that adds authorised routes to a Flask app.

Overview

PyPI version Build Status codecov Codacy Badge Documentation Status PyPI - Python Version GitHub license

Flask JWT Router

Read the docs: Flask-JWT-Router

Flask JWT Router

Flask JWT Router is a Python library that adds authorised routes to a Flask app. Both basic & Google's OAuth2.0 authentication is supported.

Google-Cloud Google's OAuth2.0 supported

Google OAuth 2.0 Quick Start

Read the detailed instructions here: Flask-JWT-Router

oauth_options = {
    "client_id": "<CLIENT_ID>",
    "client_secret": "<CLIENT_SECRET>",
    "redirect_uri": "http://localhost:3000",
    "tablename": "users",
    "email_field": "email",
    "expires_in": 3600,
}

jwt_routes.init_app(app, google_oauth=oauth_options)

Now your front end needs a token. Create an endpoint & return a new access token from the clients header code. For Example::

from flask import request

@app.routes("/login", methods=["POST"])
def login():
    jwt_routes.google.oauth_login(request) # Pass in Flask's request

Now, the next time your front-end requests authorised resources flask-jwt-router will authenticate with this access token until it expires.

Installation

Stable version

pip install flask-jwt-router

Basic Usage

from flask import Flask
from flask_jwt_router import JwtRoutes

app = Flask(__name__)
# You are required to always set a unique SECRET_KEY for your app
app.config["SECRET_KEY"] = "your_app_secret_key"

JwtRoutes(app)

# If you're using the Flask factory pattern:
jwt_routes = JwtRoutes()  # Example with *entity_model - see below

def create_app(config):
   ...
   jwt_routes.init_app(app)

Whitelist Routes

app.config["WHITE_LIST_ROUTES"] = [
    ("POST", "/register"),
]

@app.route("/register", methods=["POST"])
def register():
    return "I don't need authorizing!"

Prefix your api name to whitelisted routes

    # All routes will
app.config["JWT_ROUTER_API_NAME"] = "/api/v1"
app.config["WHITE_LIST_ROUTES"] = [
    ("POST", "/register"),
]

@app.route("/api/v1/register", methods=["POST"])
def register():
    return "I don't need authorizing!"
   

Bypass Flask-JWT-Router on specified routes

    # Define homepage template routes for example on JWT_IGNORE_ROUTES 
    # & still get to use the api name on request handlers returning resources
    app.config["IGNORED_ROUTES"] = [
        ("GET", "/")
    ]

Declare an entity model

# Create your entity model (example uses Flask-SqlAlchemy)
class UserModel(db.Model):
    __tablename__ = "users"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    
# You can define the primary key name with `ENTITY_KEY` on Flask's config
app.config["ENTITY_KEY"] = "user_id"

# (`id` is used by default)
JwtRoutes(app, entity_models=[UserModel, TeacherModel, ...etc])

# Or pass later with `init_app`
def create_app(config):
    ...
    jwt_routes.init_app(app, entity_models=[UserModel, TeacherModel, ...etc])

Authorization

from your_app import jwt_routes

# white list the routes
app.config["WHITE_LIST_ROUTES"] = [
    ("POST", "/register"),
    ("POST", "/login"),
]

@app.route("/login", methods=["POST"])
def register():
    """I'm registering a new user & returning a token!"""
    return jsonify({
        "token": jwt_routes.create_token(entity_id=1, table_name='users')
    })

@app.route("/your_resource", methods=["POST"])
def login():
    """I'm authorized & updating my token!"""
    return jsonify({
        "token": jwt_routes.update_token(entity_id=1)
    })

*Warning: The table_name must be the same as your tablename or __tablename__ attribute's value. (With SqlAlchemy, you can define a __tablename__ attribute directly or else the name is derived from your entityโ€™s database table name).

Setting the Token Expire Duration

There are two ways to set the expire duration of the JWT.

from your app config

        # Set the token expire duration to 7 days
        app.config["JWT_EXPIRE_DAYS"] = 7

calling the set_exp

        # Set the token expire duration to 14 days
        jwt_routes = JwtRoutes()
        # jwt_routes.init_app( ...etc
        jwt_routes.set_exp(expire_days=14)

By default the expire duration is set to 30 days

Create & update Tokens on Routes

Create a new entity & return a new token

@app.route("/register", methods=["POST"])
    def register():
        user_data = request.get_json()
        try:
            user = UserModel(**user_data)
            user.create_user() # your entity creation logic

            # Here we pass the id as a kwarg to `create_token`
            token: str = jwt_routes.create_token(entity_id=user.id, table_name="users")

            # Now we can return a new token!
            return {
                "message": "User successfully created.",
                "token": str(token),  # casting is optional
            }, 200

Access entity on Flask's global context

    from app import app, jwt_routes

    # Example uses Marshmallow to serialize entity object
    class EntitySchema(Schema):
        id = fields.Integer()
        name = fields.String()

    @app.route("/login", methods=["GET"])
    def login():
        user_data = g.get("users") # This is your SqlAlchemy `__tablename__` or the default name.
        try:
            user_dumped = UserSchema().dump(user_data)
        except ValidationError as _:
           return {
                       "error": "User requested does not exist."
                   }, 401
        return {
            "data": user_dumped,
            "token": jwt_routes.update_token(entity_id=user_data.id),
        }, 200
        

If you are handling a request with a token in the headers you can call::

    jwt_routes.update_token(entity_id=user_data.id)

If you are handling a request without a token in the headers you can call::

    jwt_routes.create_token(entity_id=user_data.id, table_name="users")

An Example configuration for registering & logging in users of different types:

    app.config["IGNORED_ROUTES"] = [("GET", "/")]
    app.config["JWT_ROUTER_API_NAME"] = "/api/v1"
    app.config["WHITE_LIST_ROUTES"] = [
        ("POST", "/auth/user"), ("POST", "/auth/user/login"),
        ("POST", "/auth/teacher"), ("POST", "/auth/teacher/login"),
    ]
    
    # Optionally, you can pass your models to Flask's config:
    app.config["ENTITY_MODELS"] = [ UserModel, TeacherModel, ...etc ]

JSON Web Token setup

To send the JSON web token from your front end, you will need to pass a Bearer string in your authorization header. For example:

    fetch(url, {
        headers: {
            Authorization: "Bearer <my_token>",
        }
    })

Routing without headers

If you require calling a resource without passing headers, then you can use the auth query param (useful when streaming video files):

    url = "http://example.com/cars?auth=my_token"

Google OAuth 2.0 with ReactJS

Flask-JWT-Router supports auth Google's OAuth 2.0 Single Sign On strategy if you are using React only. (We will provide Google's OAuth 2.0 Single Sign On strategy for server to server as soon as possible!).

Quick Start

Create a login route for Google's OAuth 2.0

   @app.route("/api/v1/google_login", methods=["POST"])
    def google_login():
        data = jwt_routes.google.oauth_login(request)
        return data, 200

We have created a ReactJS library specifically for Flask-JWT-Router - react-google-oauth2.0 In your React app directory install react-google-oauth2.0:

npm install react-google-oauth2 --save 

Testing

Testing OAuth2.0 in a Flask app is non-trivial, especially if you rely on Flask-JWT-Router to append your user onto Flask's global context (or g). Therefore we have provided a utility method that returns a headers Dict that you can then use in your test view handler request. This example is using the Pytest library:

    @pytest.fixture()
    def client():
        # See https://flask.palletsprojects.com/en/1.1.x/testing/ for details


    def test_blogs(client):
        user_headers = jwt_routes.google.create_test_headers(email="[email protected]")
        rv = client.get("/blogs", headers=user_headers)

If you are not running a db in your tests, then you can use the entity kwarg. For example:

# user is an instantiated SqlAlchemy object
user_headers = jwt_routes.google.create_test_headers(email="[email protected]", entity=user)
# user_headers: { "X-Auth-Token": "Bearer <GOOGLE_OAUTH2_TEST>" }

If you require more than one request to a Flask view handler in a single unit test, then set the scope kwarg to application. (Default is function) For example:

_ = jwt_routes.google.create_test_headers(email="[email protected]", scope="application")

Authors

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

Make sure you have Python versions: 3.6, 3.7, 3.8 Then run:

    tox

To check the docs look good locally you can run:

    make html

License

MIT

Issues
  • Changed the the `entity_type` kwarg to `table_name` #111 and `register_entity` now throws exception if user hasn't passed `table_name` #91

    Changed the the `entity_type` kwarg to `table_name` #111 and `register_entity` now throws exception if user hasn't passed `table_name` #91

    #111

    1. Changed the the entity_type kwarg to table_name
    2. Added Deprecation warning for the entity_type kwargs

    #91

    1. Added test function to test whether register_entity throws an exception on not passing the table_name key
    2. Added code to throw KeyError exception in register_entity function of FlaskJWTRouter class if user doesn't pass a table_name
    opened by kousikmitra 19
  • remove 's' from entity on g context

    remove 's' from entity on g context

    when the entity data is assigned to Flask global context it can derive from a plural table entity name (especially if the user uses the tablename attribute). So removing the 's' makes it clearer when returning the global context entity value

    user = g.user 3 . # not g.users 
    
    enhancement help wanted good first issue 
    opened by joegasewicz 15
  • Returning 401 on any unauthorised routes

    Returning 401 on any unauthorised routes

    The bug fix needs to make sure 404's get returned on routes that don't exist (no request handlers for these routes).

    bug help wanted good first issue 
    opened by joegasewicz 13
  • Change the the entity_type kwarg to table_name

    Change the the entity_type kwarg to table_name

    Our API has 2 public methods, one of which is register_entity. This currently requires a kwarg of entity_type to donate the table name, which is confusing to the user.

    Change register_entity method's kwarg of entity_type to table_name. This may result in updating other parts of the codebase, docs, README, blog and tests.

    enhancement help wanted good first issue discussion 
    opened by joegasewicz 10
  • Fixed Returning 401 on any unauthorised routes #47

    Fixed Returning 401 on any unauthorised routes #47

    Implemented a method called _is_route_exist in _routing.py which checks whether a particular route exist in the current app to handle the requested URL. If a router exists it returns True else returns False Depending on the result the further processing is done as before.

    opened by kousikmitra 8
  • Handle possibly URL breaking characters

    Handle possibly URL breaking characters

    If the used variables for building the URL contain any URL characters such as &, /, =, they would create a possibly broken URL. Safer to assume they do and use the builtin urlencode. Also cleans up building the URL.

    opened by fre-sch 4
  • Throw exception if user hasn't passed a valid entity_type

    Throw exception if user hasn't passed a valid entity_type

    https://github.com/joegasewicz/Flask-JWT-Router/blob/8a273366aaceeb4e21938f2cdb69257a74d584d4/flask_jwt_router/_authentication.py#L92

    Check if entity_type kwarg exists, if not throw with a meaningful message to the user.

    enhancement help wanted good first issue 
    opened by joegasewicz 4
  • Pre-flight OPTIONS only set on POST #63

    Pre-flight OPTIONS only set on POST #63

    Release 0.0.26 - 2019-12-11

    opened by joegasewicz 3
  • Look into OAuth & perhaps we can wrap this strategy in a separate class / strategy / algorithm etc.

    Look into OAuth & perhaps we can wrap this strategy in a separate class / strategy / algorithm etc.

    enhancement question investigate discussion 
    opened by joegasewicz 3
  • Outdated docstring - nice easy fix for a beginner developer!

    Outdated docstring - nice easy fix for a beginner developer!

    Therefore we have provided a utility method that returns a headers Dict that you can then use in your test view handler request. Should be: Therefore we have provided a utility method that you can then use in your test view handler request.

    here: https://github.com/joegasewicz/flask-jwt-router/blob/e6e5bad9d5a3ecaff51279a05fa8a24e8cc44de8/flask_jwt_router/oauth2/google.py#L95

    here (should return -> str):

    https://github.com/joegasewicz/flask-jwt-router/blob/e6e5bad9d5a3ecaff51279a05fa8a24e8cc44de8/flask_jwt_router/oauth2/google.py#L248

    here (Should just return Bearer [email protected]): https://github.com/joegasewicz/flask-jwt-router/blob/e6e5bad9d5a3ecaff51279a05fa8a24e8cc44de8/flask_jwt_router/oauth2/google.py#L266

    documentation help wanted good first issue 
    opened by joegasewicz 3
  • Router test mixin should not duplicate any code from the Router class

    Router test mixin should not duplicate any code from the Router class

    Currently there is some code duplication within the handle_token methods.

    Employ a hook system to pull in the logic as required, could use a generator function etc...

    enhancement 
    opened by joegasewicz 0
  • Remove Travis CI badges

    Remove Travis CI badges

    Remove the following badges from the readme:

    • codevoc
    • code quality
    documentation help wanted good first issue 
    opened by joegasewicz 0
  • Documentation for redirect_uri

    Documentation for redirect_uri

    documentation help wanted good first issue 
    opened by joegasewicz 0
  • test issue when using X-Auth-Token headers

    test issue when using X-Auth-Token headers

    rv = client.get(url, headers={"X-Auth-Token": "Bearer 1234.1234.1234"}) causes:

    email = self.test_metadata[email]["email"]
     KeyError: '1234.1234.1234'
    
    bug help wanted good first issue 
    opened by joegasewicz 0
  • Flask secret key error could be improved

    Flask secret key error could be improved

    Currently, if a a SECRET_KEY flask config value is not set then flask-jwt-router throws. The message points to a broken link in the docs.

    bug documentation help wanted good first issue 
    opened by joegasewicz 0
  • Make all tests functional

    Make all tests functional

    Currently the routing fixture scope is set to class. This is due to some tests failing when set to function scope. This needs investigating.

    bug help wanted good first issue investigate 
    opened by joegasewicz 0
  • Remove url value

    Remove url value

    https://github.com/joegasewicz/flask-jwt-router/blob/1822b9160da8ef0c7933184481b1849fab565e0f/flask_jwt_router/oauth2/http_requests.py#L40

    Remove url value as this could display the client_secret in the logs

    bug help wanted good first issue 
    opened by joegasewicz 0
  • expires_in default value not set

    expires_in default value not set

    https://github.com/joegasewicz/flask-jwt-router/blob/1822b9160da8ef0c7933184481b1849fab565e0f/flask_jwt_router/_jwt_routes.py#L257

    Set the default value earlier

    bug help wanted good first issue 
    opened by joegasewicz 0
  • Jetbrains intelli sense not working on Google class

    Jetbrains intelli sense not working on Google class

    Jetbrains intelli sense not working on Google class

    bug 
    opened by joegasewicz 0
Releases(0.2.1)
Owner
Joe Gasewicz
Hi! I'm a Python, Typescript, Go & C Developer. I'm also a Jazz bassist. I'm based in London, UK & available for contracts in mid April 2021
Joe Gasewicz
Simple extension that provides Basic, Digest and Token HTTP authentication for Flask routes

Flask-HTTPAuth Simple extension that provides Basic and Digest HTTP authentication for Flask routes. Installation The easiest way to install this is t

Miguel Grinberg 940 Feb 13, 2021
Django Rest Framework App wih JWT Authentication and other DRF stuff

Django Queries App with JWT authentication, Class Based Views, Serializers, Swagger UI, CI/CD and other cool DRF stuff API Documentaion /swagger - Swa

Rafael Salimov 4 Dec 20, 2021
Storefront - A store App developed using Django, RESTFul API, JWT

Storefront A store App developed using Django, RESTFul API, JWT. SQLite has been

Muhammad Algshy 1 Jan 7, 2022
An open source Flask extension that provides JWT support (with batteries included)!

Flask-JWT-Extended Features Flask-JWT-Extended not only adds support for using JSON Web Tokens (JWT) to Flask for protecting views, but also many help

Landon Gilbert-Bland 1.2k Jan 10, 2022
Strong, Simple, and Precise security for Flask APIs (using jwt)

flask-praetorian Strong, Simple, and Precise security for Flask APIs API security should be strong, simple, and precise like a Roman Legionary. This p

Tucker Beck 304 Jan 15, 2022
Strong, Simple, and Precise security for Flask APIs (using jwt)

flask-praetorian Strong, Simple, and Precise security for Flask APIs API security should be strong, simple, and precise like a Roman Legionary. This p

Tucker Beck 266 Feb 15, 2021
Boilerplate/Starter Project for building RESTful APIs using Flask, SQLite, JWT authentication.

auth-phyton Boilerplate/Starter Project for building RESTful APIs using Flask, SQLite, JWT authentication. Setup Step #1 - Install dependencies $ pip

sandhika 1 Dec 26, 2021
The ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS,JWE,JWK,JWA,JWT included.

Authlib The ultimate Python library in building OAuth and OpenID Connect servers. JWS, JWK, JWA, JWT are included. Authlib is compatible with Python2.

Hsiaoming Yang 2.9k Jan 12, 2022
The ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS,JWE,JWK,JWA,JWT included.

Authlib The ultimate Python library in building OAuth and OpenID Connect servers. JWS, JWK, JWA, JWT are included. Authlib is compatible with Python2.

Hsiaoming Yang 2.3k Feb 17, 2021
JWT authentication for Pyramid

JWT authentication for Pyramid This package implements an authentication policy for Pyramid that using JSON Web Tokens. This standard (RFC 7519) is of

Wichert Akkerman 73 Dec 3, 2021
FastAPI extension that provides JWT Auth support (secure, easy to use, and lightweight)

FastAPI JWT Auth Documentation: https://indominusbyte.github.io/fastapi-jwt-auth Source Code: https://github.com/IndominusByte/fastapi-jwt-auth Featur

Nyoman Pradipta Dewantara 313 Jan 11, 2022
Brute force a JWT token. Script uses multithreading.

JWT BF Brute force a JWT token. Script uses multithreading. Tested on Kali Linux v2021.4 (64-bit). Made for educational purposes. I hope it will help!

Ivan ล incek 2 Dec 9, 2021
A full Rest-API With Oauth2 and JWT for request & response a JSON file Using FastAPI and SQLAlchemy ๐Ÿ”‘

Pexon-Rest-API A full Rest-API for request & response a JSON file, Building a Simple WorkFlow that help you to Request a JSON File Format and Handling

Yasser Tahiri 16 Nov 12, 2021
Djagno grpc authentication service with jwt auth

Django gRPC authentication service STEP 1: Install packages pip install -r requirements.txt STEP 2: Make migrations and migrate python manage.py makem

Saeed Hassani Borzadaran 1 Dec 18, 2021
Authentication with fastapi and jwt cd realistic

Authentication with fastapi and jwt cd realistic Dependencies bcrypt==3.1.7 data

Fredh Macau 1 Jan 4, 2022
JWT Key Confusion PoC (CVE-2015-9235) Written for the Hack the Box challenge - Under Construction

JWT Key Confusion PoC (CVE-2015-9235) Written for the Hack the Box challenge - Under Construction This script performs a Java Web Token Key Confusion

Alex Fronteddu 1 Jan 13, 2022
This app makes it extremely easy to build Django powered SPA's (Single Page App) or Mobile apps exposing all registration and authentication related functionality as CBV's (Class Base View) and REST (JSON)

Welcome to django-rest-auth Repository is unmaintained at the moment (on pause). More info can be found on this issue page: https://github.com/Tivix/d

Tivix 2.3k Jan 13, 2022
Flask App With Login

Flask App With Login by FranciscoCharles Este projeto basico รฉ o resultado do estudos de algumas funcionalidades do micro framework Flask do Python. O

Charles 3 Nov 14, 2021
User Authentication in Flask using Flask-Login

User-Authentication-in-Flask Set up & Installation. 1 .Clone/Fork the git repo and create an environment Windows git clone https://github.com/Dev-Elie

ONDIEK ELIJAH OCHIENG 6 Jan 7, 2022