FastAPI extension that provides JWT Auth support (secure, easy to use, and lightweight)

Overview

FastAPI JWT Auth

Tests Coverage Status PyPI version Downloads


Documentation: https://indominusbyte.github.io/fastapi-jwt-auth

Source Code: https://github.com/IndominusByte/fastapi-jwt-auth


Features

FastAPI extension that provides JWT Auth support (secure, easy to use and lightweight), if you were familiar with flask-jwt-extended this extension suitable for you, cause this extension inspired by flask-jwt-extended 😀

  • Access tokens and refresh tokens
  • Freshness Tokens
  • Revoking Tokens
  • Support for WebSocket authorization
  • Support for adding custom claims to JSON Web Tokens
  • Storing tokens in cookies and CSRF protection

Installation

The easiest way to start working with this extension with pip

pip install fastapi-jwt-auth

If you want to use asymmetric (public/private) key signing algorithms, include the asymmetric extra requirements.

pip install 'fastapi-jwt-auth[asymmetric]'

License

This project is licensed under the terms of the MIT license.

Comments
  • Websocket Support

    Websocket Support

    Currently it looks as though websockets wont work with the standard require_jwt_auth() even when sent via cookies (which works with flask_jwt_extended). This is the error I'm getting:

    ERROR:    Exception in ASGI application
    Traceback (most recent call last):
      File "/home/user/dev/work/venv/lib/python3.8/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 154, in run_asgi
        result = await self.app(self.scope, self.asgi_receive, self.asgi_send)
      File "/home/user/dev/work/venv/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
        return await self.app(scope, receive, send)
      File "/home/user/dev/work/venv/lib/python3.8/site-packages/fastapi/applications.py", line 179, in __call__
        await super().__call__(scope, receive, send)
      File "/home/user/dev/work/venv/lib/python3.8/site-packages/starlette/applications.py", line 111, in __call__
        await self.middleware_stack(scope, receive, send)
      File "/home/user/dev/work/venv/lib/python3.8/site-packages/starlette/middleware/errors.py", line 146, in __call__
        await self.app(scope, receive, send)
      File "/home/user/dev/work/venv/lib/python3.8/site-packages/starlette/exceptions.py", line 58, in __call__
        await self.app(scope, receive, send)
      File "/home/user/dev/work/venv/lib/python3.8/site-packages/starlette/routing.py", line 566, in __call__
        await route.handle(scope, receive, send)
      File "/home/user/dev/work/venv/lib/python3.8/site-packages/starlette/routing.py", line 283, in handle
        await self.app(scope, receive, send)
      File "/home/user/dev/work/venv/lib/python3.8/site-packages/starlette/routing.py", line 57, in app
        await func(session)
      File "/home/user/dev/work/venv/lib/python3.8/site-packages/fastapi/routing.py", line 228, in app
        await dependant.call(**values)
      File "./backend/api/routers/apps.py", line 171, in dashboard
        Authorize.jwt_required()
      File "/home/user/dev/work/venv/lib/python3.8/site-packages/fastapi_jwt_auth/auth_jwt.py", line 670, in jwt_required
        self._verify_and_get_jwt_in_cookies('access',self._decode_issuer)
      File "/home/user/dev/work/venv/lib/python3.8/site-packages/fastapi_jwt_auth/auth_jwt.py", line 541, in _verify_and_get_jwt_in_cookies
        cookie = self._request.cookies.get(cookie_key)
    AttributeError: 'NoneType' object has no attribute 'cookies'
    
    enhancement 
    opened by SelfhostedPro 27
  • How to retrieve current user from request.headers while ratelimiting the endpoint?

    How to retrieve current user from request.headers while ratelimiting the endpoint?

    For ratelimiting the endpoint I want to use two approaches i)based on IP address (unprotected endpoint, no JWT access token)

    def get_remote_address(request: Request) -> str:
        """
        Returns the ip address for the current request (or 127.0.0.1 if none found)
        """
        return request.client.host or "127.0.0.1"
    

    It works fine

    2 ) based on current user, current user has to be retrieved from JWT access token. JWT access token is created using this fastapi-jwt-auth and user is in get-jwt-subject.

    from starlette.requests import Request
    from fastapi_jwt_auth import AuthJWT
    
    def get_user_from_headers(request: Request):
        if 'authorization' in request.headers:
            
            current_user = AuthJWT.get_jwt_subject()
            print(current_user)
            return current_user
        else:
             return  get_remote_address
    

    Doing this, I couldn't find current-user. How to find current_user if request.headers has authorization?

    opened by himalacharya 17
  • Personalization exeption messages

    Personalization exeption messages

    Hi, how can i personalize exeption messages?

    @app.exception_handler(AuthJWTException) def authjwt_exception_handler(request: Request, exc: AuthJWTException): return JSONResponse( status_code=exc.status_code, content={"detail": exc.message} )

    opened by MohammadmahdiAhmadi 6
  • Add enable setting to options

    Add enable setting to options

    Would it be feasible to add an optional option to enable or disable authentication to the jwtSettings?

    Currently I'm using Fast-API users (but I'm migrating to fastapi-jwt-auth) and one of the requests of some users is to be able to disable authentication (so that they can use their own authentication platform like authelia).

    With FastAPI users I highjack a function (essentially if the DISABLE_AUTH environment variable is set to true, I import a fake function that just returns true instead of the actual get_active_user function (code here)).

    I was wondering if there's a similar way to do that with this framework?

    opened by SelfhostedPro 5
  • How can I use it in graphql?

    How can I use it in graphql?

    Is it possible to use it in graphql? https://fastapi.tiangolo.com/advanced/graphql/

    Tried this: https://github.com/tiangolo/fastapi/issues/1279

    But it's not showing the graphiql ide : {"detail":"Method Not Allowed"}

    opened by amiyatulu 4
  • Freshness Tokens docs: fresh=False

    Freshness Tokens docs: fresh=False

    In https://indominusbyte.github.io/fastapi-jwt-auth/usage/freshness/

    def refresh():
        new_access_token = Authorize.create_access_token(subject=current_user,fresh=False)
    

    fresh=False. Took me a while to figure out on localhost why it was giving me the "Fresh token required" error. Switching this to True got me good. I'm a total JWT newb, and still wrapping my mind around it, so maybe it's user-error on my part?

    opened by lefnire 4
  • Print AuthJWTException message

    Print AuthJWTException message

    While testing protected endpoint, I put wrong access token (deleting some values in actual access token) in Postman. I tired to print AuthJwt exception but it gives nothing. When I donot supply access token, no any exception message is printed. For example: access token is eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

    But I put access token in Postman as eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJz to test It gives nothing while printing print(e).

    except AuthJWTException as e:
           print(e)
           return ErrorResponseModel(
                            "Something went wrong",
                            status.HTTP_200_OK,
                            status.HTTP_401_UNAUTHORIZED
                        )   
    

    Code in main.py

    application.add_exception_handler(AuthJWTException, authjwt_exception_handler)
    

    How toc check individual exception?

    opened by himalacharya 4
  • Invalid token type. Token must be a <class 'bytes'>

    Invalid token type. Token must be a

    Hi. I've got this problem. How to fix this?

    Request to get access token: curl -H "Content-Type: application/json" -X POST -d '{"email":"test","password":"test"}' http://localhost:8000/login Response: {"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0IiwiaWF0IjoxNjA0MzUwMTc4LCJuYmYiOjE2MDQzNTAxNzgsImp0aSI6IjI5Yjg3YTY0LTQyZDQtNGVlZC1iZmEyLTU4OTZhZjdhNjM2NiIsImV4cCI6MTYwNDM1MTA3OCwidHlwZSI6ImFjY2VzcyIsImZyZXNoIjpmYWxzZX0.o6JkaCJmANVbuwaj5loHmj_YBLfHchf8TiTssdwmgTM", "refresh_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0IiwiaWF0IjoxNjA0MzUwMTc4LCJuYmYiOjE2MDQzNTAxNzgsImp0aSI6IjY5NTc1MjBhLTFiNDItNDFhOS1iMmRmLWZmNTU2ODBhNDIyYiIsImV4cCI6MTYwNjk0MjE3OCwidHlwZSI6InJlZnJlc2gifQ.SVa5ol5sDGzcUnDtrf--oduG5jifapXYy2zulwt6fO0"}

    Request to protected endpoint with Authorize.jwt_required: curl -H "Authorization: Authorization-Token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0IiwiaWF0IjoxNjA0MzUwMTc4LCJuYmYiOjE2MDQzNTAxNzgsImp0aSI6IjI5Yjg3YTY0LTQyZDQtNGVlZC1iZmEyLTU4OTZhZjdhNjM2NiIsImV4cCI6MTYwNDM1MTA3OCwidHlwZSI6ImFjY2VzcyIsImZyZXNoIjpmYWxzZX0.o6JkaCJmANVbuwaj5loHmj_YBLfHchf8TiTssdwmgTM" http://localhost:8000/protected Response: {"detail":"Invalid token type. Token must be a <class 'bytes'>"}

    opened by NazarKostetskiy 4
  • Sliding sessions

    Sliding sessions

    I really appreciate your work on this project.

    It could be a nice feature to have sliding sessions available, i.e. sending fresh access tokens on every request, if a certain time of inactivity is not exceeded.

    Some information about this approach can be found here https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/.

    Any suggestions how this could be implemented? Maybe as a middleware?

    Best regards

    opened by hestal 3
  • Custom Token checker function not working

    Custom Token checker function not working

    I try to separate the logic of checking JWT tokens from one function so that it can be reused. But when I try to run the code, it does not work. I manage an access token in my database and check if it exists or not. The last generated token will be valid only for the access token. This access token must be checked at every protected endpoint. Here is my code:

    
    @router.get('/user')
    async def items(Authorize: AuthJWT = Depends(), db: AsyncIOMotorClient = Depends(get_database)):
        try:
            await jwt_token_checker(Authorize, db)
            return {"asd"}   
    
        except Exception as ex:
            return error
    

    Helper Function:

    async def jwt_token_checker( Authorize: AuthJWT , conn: AsyncIOMotorClient):
        try:
            Authorize.jwt_required()
            jti = Authorize.get_raw_jwt()['jti']
            current_user = Authorize.get_jwt_subject()
            access_token_check = await check_access_token(conn, Authorize, jti, current_user)
            
            errorMessage = ""
            if access_token_check == AuthEnum.FORBIDDEN_UNAUTHORIZED_ACCESS:
                errorMessage = Locale(
                    language, strings.FORBIDDEN_UNAUTHORIZED_ACCESS).string
                return errorMessage
        except Exception as ex:
            return error
    

    Is this right way to separate the token checker function? If not then can you please suggest me some solution.

    opened by techxonia 3
  • Support for RSA base encryption

    Support for RSA base encryption

    Hi, for RSA base encryption there is a public key that is used to decrypt messages. By the look of it, the library does not seem to support this. Would it make sense to add support for it ?

    opened by m4nuC 3
  • Fetching CSRF from headers requires update

    Fetching CSRF from headers requires update

    In this line, https://github.com/IndominusByte/fastapi-jwt-auth/blob/a6c06193319da0e4976c7472966f3a2891e0d50c/fastapi_jwt_auth/auth_jwt.py#L549 the code is trying to get CSRF_TOKEN from the headers and treating response.headers as a dict object which is true. But the headers don't contain the default "X-CSRF-Token". It contains the key-value pair with cookies as key and all cookie info as a string separated by ;.

    So whenever someone tries to get CSRF token the code is unable to find the key "X-CSRF-Token" in the headers but now it's inside key cookies, which needs to be parsed for extracting CSRF_TOKEN.

    That's why whenever someone uses csrf_protect as True, they get a Missing CSRF Token error every time

    I can see the code is not updated for the last 2 years. That might be the reason that it is not in compliance with the browser's headers.

    opened by shivam221098 0
  • create refresh and access token together

    create refresh and access token together

    now it can create an access token and refresh token together with a specific id that "aid" so in deny list we can block both of them, by blocking that is the same in both

    opened by Alima12 1
  • OpenApi docs

    OpenApi docs

    I'm having a problem with the OpenApi doc generation, I tested https://indominusbyte.github.io/fastapi-jwt-auth/advanced-usage/generate-docs/ and it keeps giving the error with the Authorization key being ignored by openApi, if you make the call via insomnia it works normally

    Att

    opened by wesleymr59 0
  • AttributeError: 'str' object has no attribute 'decode'

    AttributeError: 'str' object has no attribute 'decode'

    I am using pyjwt version 2.4.0 and I think it's conflicting and showing this error: AttributeError: 'str' object has no attribute 'decode' When I try to use this:

    access_token = self.authorize.create_access_token(subject=body.phone)
    refresh_token = self.authorize.create_refresh_token(subject=body.phone)
    

    When I down grade pyjwt to 1.7.0 it works fine.

    opened by sombek 1
  • Fixed a grammatical error in the docs

    Fixed a grammatical error in the docs

    A grammatical error was observed in the docs. It said "Which keeps javascript cannot be able to access the cookies."

    I think want was meant was "Which means javascript cannot be able to access the cookies."

    opened by VictoryIfebhor 0
Releases(v0.5.0)
  • v0.5.0(Nov 6, 2020)

  • v0.4.0(Nov 2, 2020)

  • v0.3.0(Oct 29, 2020)

    • (Deprecated) environment variable support
    • Change name function load_end() -> load_config()
    • Change name function get_jwt_identity() -> get_jwt_subject()
    • Change name identity claims to standard claims sub (Thanks to @rassie for suggestion)
    • Additional headers in claims
    • Get additional headers claims from request or parsing token directly
    • Leeway exp claim decode token
    • Dynamic token expires time
    • Change name blacklist -> denylist
    • Denylist custom check refresh and access tokens
    • Issuer claim
    • Audience claim
    • Jwt decode algorithms
    • Dynamic algorithm create token
    • Token multiple location
    • Support RSA encryption (Thanks to @jet10000 for make issues)
    • Custom header name and type
    • Custom error message key and status code
    • JWT in cookies (Thanks to @m4nuC for make issues)
    • Add Additional claims
    • Add Documentation (#9 by @paulussimanjuntak)
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Oct 7, 2020)

    • Call create_token and get_jti function must be from dependency injection
    • Improve blacklist loader
    • Can load env from pydantic
    • Add docs on readme how to use without dependency injection and example on multiple files
    • Fix raise jwt exception PR #1 by @ironslob
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Aug 13, 2020)

    • Access token and refresh token
    • Token freshness will only allow fresh tokens to access endpoint
    • Token revoking/blacklisting
    • Custom token revoking
    Source code(tar.gz)
    Source code(zip)
Owner
Nyoman Pradipta Dewantara
Security enthusiast and Python 🐍 enthusiast | CTF PLAYER
Nyoman Pradipta Dewantara
Automatic login utility of free Wi-Fi captive portals

wicafe Automatic login utility of free Wi-Fi captive portals Disclaimer: read and grant the Terms of Service of Wi-Fi services before using it! This u

Takumi Sueda 8 May 31, 2022
Authentication Module for django rest auth

django-rest-knox Authentication Module for django rest auth Knox provides easy to use authentication for Django REST Framework The aim is to allow for

James McMahon 878 Jan 04, 2023
Kube OpenID Connect is an application that can be used to easily enable authentication flows via OIDC for a kubernetes cluster

Kube OpenID Connect is an application that can be used to easily enable authentication flows via OIDC for a kubernetes cluster. Kubernetes supports OpenID Connect Tokens as a way to identify users wh

7 Nov 20, 2022
Easy and secure implementation of Azure AD for your FastAPI APIs 🔒 Single- and multi-tenant support.

Easy and secure implementation of Azure AD for your FastAPI APIs 🔒 Single- and multi-tenant support.

Intility 220 Jan 05, 2023
Minimal authorization through OO design and pure Ruby classes

Pundit Pundit provides a set of helpers which guide you in leveraging regular Ruby classes and object oriented design patterns to build a simple, robu

Varvet 7.8k Jan 02, 2023
A Python inplementation for OAuth2

OAuth2-Python Discord Inplementation for OAuth2 login systems. This is a simple Python 'app' made to inplement in your programs that require (shitty)

Prifixy 0 Jan 06, 2022
FastAPI Simple authentication & Login API using GraphQL and JWT

JeffQL A Simple FastAPI authentication & Login API using GraphQL and JWT. I choose this Name JeffQL cause i have a Low level Friend with a Nickname Je

Yasser Tahiri 26 Nov 24, 2022
JSON Web Token Authentication support for Django REST Framework

REST framework JWT Auth JSON Web Token Authentication support for Django REST Framework Overview This package provides JSON Web Token Authentication s

Styria Digital Development 178 Jan 02, 2023
A module making it easier to manage Discord oAuth with Quart

quart_discord A module making it easier to manage Discord oAuth with Quart Install pip install git+https://github.com/xelA/ 5 Oct 27, 2022

Plotly Dash plugin to allow authentication through 3rd party OAuth providers.

dash-auth-external Integrate your dashboards with 3rd parties and external OAuth providers. Overview Do you want to build a Plotly Dash app which pull

James Holcombe 15 Dec 11, 2022
Awesome Django authorization, without the database

rules rules is a tiny but powerful app providing object-level permissions to Django, without requiring a database. At its core, it is a generic framew

1.6k Dec 30, 2022
Todo app with authentication system.

todo list web app with authentication system. User can register, login, logout. User can login and create, delete, update task Home Page here you will

Anurag verma 3 Aug 18, 2022
Alisue 299 Dec 06, 2022
Luca Security Concept

Luca Security Concept This is the document source of luca's security concept. Please go here for the HTML version: https://luca-app.de/securityconcept

luca 43 Oct 22, 2022
A flask extension for managing permissions and scopes

Flask-Pundit A simple flask extension to organize resource authorization and scoping. This extension is heavily inspired by the ruby Pundit library. I

Anurag Chaudhury 49 Dec 23, 2022
Connect-4-AI - AI that plays Connect-4 using the minimax algorithm

Connect-4-AI Brief overview I coded up the Connect-4 (or four-in-a-row) game in

Favour Okeke 1 Feb 15, 2022
A recipe sharing API built using Django rest framework.

Recipe Sharing API This is the backend API for the recipe sharing platform at https://mesob-recipe.netlify.app/ This API allows users to share recipes

Hannah 21 Dec 30, 2022
Two factor authentication system using azure services and python language and its api's

FUTURE READY TALENT VIRTUAL INTERSHIP PROJECT PROJECT NAME - TWO FACTOR AUTHENTICATION SYSTEM Resources used: * Azure functions(python)

BHUSHAN SATISH DESHMUKH 1 Dec 10, 2021
Simple two factor authemtication system, made by me.

Simple two factor authemtication system, made by me. Honestly, i don't even know How 2FAs work I just used my knowledge and did whatever i could. Send

Refined 5 Jan 04, 2022
Simple Login - Login Extension for Flask - maintainer @cuducos

Login Extension for Flask The simplest way to add login to flask! How it works First, install it from PyPI: $ pip install flask_simplelogin Then, use

Flask Extensions 181 Jan 01, 2023