Skip to main content

FastAPI extension that provides JWT Auth support

Project description

fastapi-jwt-auth

Build Status Coverage Status PyPI version Downloads Downloads

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 because this extension inspired by flask-jwt-extended.

  • Access token and refresh token
  • Token freshness will only allow fresh tokens to access endpoint
  • Token revoking/blacklisting
  • Custom token revoking

Installation

pip install fastapi-jwt-auth

Usage

Setting AUTHJWT_SECRET_KEY in environment variable

  • For Linux, macOS, Windows Bash
export AUTHJWT_SECRET_KEY=secretkey
  • For Windows PowerShell
$Env:AUTHJWT_SECRET_KEY = "secretkey"

Create it

  • Create a file basic.py with:
from fastapi import FastAPI, Depends, HTTPException
from fastapi_jwt_auth import AuthJWT
from pydantic import BaseModel, Field

app = FastAPI()

class User(BaseModel):
    username: str = Field(...,min_length=1)
    password: str = Field(...,min_length=1)

# Provide a method to create access tokens. The create_access_token()
# function is used to actually generate the token, and you can return
# it to the caller however you choose.
@app.post('/login',status_code=200)
def login(user: User, Authorize: AuthJWT = Depends()):
    if user.username != 'test' or user.password != 'test':
        raise HTTPException(status_code=401,detail='Bad username or password')

    # identity must be between string or integer
    access_token = Authorize.create_access_token(identity=user.username)
    return {"access_token": access_token}

@app.get('/protected',status_code=200)
def protected(Authorize: AuthJWT = Depends()):
    # Protect an endpoint with jwt_required, which requires a valid access token
    # in the request to access.
    Authorize.jwt_required()

    # Access the identity of the current user with get_jwt_identity
    current_user = Authorize.get_jwt_identity()
    return {"logged_in_as": current_user}

Run it

Run the server with:

$ uvicorn basic:app --host 0.0.0.0

INFO:     Started server process [4235]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

Access it

To access a jwt_required protected url, all we have to do is send in the JWT with the request. By default, this is done with an authorization header that looks like:

Authorization: Bearer <access_token>

We can see this in action using CURL:

$ curl http://localhost:8000/protected

{"detail":"Missing Authorization Header"}

$ curl -H "Content-Type: application/json" -X POST \
  -d '{"username":"test","password":"test"}' http://localhost:8000/login

"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTczMzMxMzMsIm5iZiI6MTU5NzMzMzEzMywianRpIjoiNDczY2ExM2ItOWI1My00NDczLWJjZTctMWZiOWMzNTlmZmI0IiwiZXhwIjoxNTk3MzM0MDMzLCJpZGVudGl0eSI6InRlc3QiLCJ0eXBlIjoiYWNjZXNzIiwiZnJlc2giOmZhbHNlfQ.42CusQo6nsLxOk6bBUP1vnVX-REx4ZYBYYIjYChWf0c"

$ export TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTczMzMxMzMsIm5iZiI6MTU5NzMzMzEzMywianRpIjoiNDczY2ExM2ItOWI1My00NDczLWJjZTctMWZiOWMzNTlmZmI0IiwiZXhwIjoxNTk3MzM0MDMzLCJpZGVudGl0eSI6InRlc3QiLCJ0eXBlIjoiYWNjZXNzIiwiZnJlc2giOmZhbHNlfQ.42CusQo6nsLxOk6bBUP1vnVX-REx4ZYBYYIjYChWf0c

$ curl -H "Authorization: Bearer $TOKEN" http://localhost:8000/protected

{"logged_in_as":"test"}

Extract Token

Access all URL to see what the result

from fastapi import FastAPI, Depends, HTTPException
from fastapi_jwt_auth import AuthJWT
from pydantic import BaseModel, Field

app = FastAPI()

class User(BaseModel):
    username: str = Field(...,min_length=1)
    password: str = Field(...,min_length=1)

@app.post('/login',status_code=200)
def login(user: User, Authorize: AuthJWT = Depends()):
    if user.username != 'test' or user.password != 'test':
        raise HTTPException(status_code=401,detail='Bad username or password')

    access_token = Authorize.create_access_token(identity=user.username)
    return access_token

# Returns the JTI (unique identifier) of an encoded JWT
@app.get('/get-jti',status_code=200)
def get_jti(Authorize: AuthJWT = Depends()):
    access_token = Authorize.create_access_token(identity='test')
    return Authorize.get_jti(encoded_token=access_token)

# this will return the identity of the JWT that is accessing this endpoint.
# If no JWT is present, `None` is returned instead.
@app.get('/get-jwt-identity',status_code=200)
def get_jwt_identity(Authorize: AuthJWT = Depends()):
    Authorize.jwt_optional()

    current_user = Authorize.get_jwt_identity()
    return {"logged_in_as": current_user}

# this will return the python dictionary which has all
# of the claims of the JWT that is accessing the endpoint.
# If no JWT is currently present, return None instead
@app.get('/get-raw-jwt',status_code=200)
def get_raw_jwt(Authorize: AuthJWT = Depends()):
    Authorize.jwt_optional()

    token = Authorize.get_raw_jwt()
    return {"token": token}

Configuration Options (env)

  • AUTHJWT_ACCESS_TOKEN_EXPIRES
    How long an access token should live before it expires. If you not define in env variable default value is 15 minutes. Or you can custom with value int (seconds), example AUTHJWT_ACCESS_TOKEN_EXPIRES=300 its mean access token expired in 5 minute

  • AUTHJWT_REFRESH_TOKEN_EXPIRES
    How long a refresh token should live before it expires. If you not define in env variable default value is 30 days. Or you can custom with value int (seconds), example AUTHJWT_REFRESH_TOKEN_EXPIRES=86400 its mean refresh token expired in 1 day

  • AUTHJWT_BLACKLIST_ENABLED
    Enable/disable token revoking. Default value is None, for enable blacklist token: AUTHJWT_BLACKLIST_ENABLED=true

  • AUTHJWT_SECRET_KEY
    The secret key needed for symmetric based signing algorithms, such as HS*. If this is not set raise RuntimeError.

  • AUTHJWT_ALGORITHM
    Which algorithms are allowed to decode a JWT. Default value is HS256

Configuration (pydantic or list[tuple])

You can convert and validate type data from dotenv through pydantic (BaseSettings)

from fastapi_jwt_auth import AuthJWT
from pydantic import BaseSettings
from datetime import timedelta
from typing import Literal

# dotenv file parsing requires python-dotenv to be installed
# This can be done with either pip install python-dotenv
class Settings(BaseSettings):
    authjwt_access_token_expires: timedelta = timedelta(minutes=15)
    authjwt_refresh_token_expires: timedelta = timedelta(days=30)
    # literal type only available for python 3.8
    authjwt_blacklist_enabled: Literal['true','false']
    authjwt_secret_key: str
    authjwt_algorithm: str = 'HS256'

    class Config:
        env_file = '.env'
        env_file_encoding = 'utf-8'


@AuthJWT.load_env
def get_settings():
    return Settings()
    # or you can just parse a list of tuple
    # return [
    #     ("authjwt_access_token_expires",timedelta(minutes=2)),
    #     ("authjwt_refresh_token_expires",timedelta(days=5)),
    #     ("authjwt_blacklist_enabled","false"),
    #     ("authjwt_secret_key","testing"),
    #     ("authjwt_algorithm","HS256")
    # ]


print(AuthJWT._access_token_expires)
print(AuthJWT._refresh_token_expires)
print(AuthJWT._blacklist_enabled)
print(AuthJWT._secret_key)
print(AuthJWT._algorithm)

Examples

Examples are available on examples folder. There are:

Optional:

License

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi-jwt-auth-0.2.0.tar.gz (12.4 kB view details)

Uploaded Source

Built Distribution

fastapi_jwt_auth-0.2.0-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

File details

Details for the file fastapi-jwt-auth-0.2.0.tar.gz.

File metadata

  • Download URL: fastapi-jwt-auth-0.2.0.tar.gz
  • Upload date:
  • Size: 12.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.8.3

File hashes

Hashes for fastapi-jwt-auth-0.2.0.tar.gz
Algorithm Hash digest
SHA256 40e3134edb562d0ac5b83299a0822b0d32802b2487a31169b891f1228ddc3470
MD5 52a094d9d25e42f1055552867e1eaca1
BLAKE2b-256 209f04f2a06500c0bdc0a81533ca060163111d25b7c2bb0e9f428a1ba38466a1

See more details on using hashes here.

File details

Details for the file fastapi_jwt_auth-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: fastapi_jwt_auth-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 14.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.8.3

File hashes

Hashes for fastapi_jwt_auth-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1c3e30b46161d5fcb01c8d16111836419d589bbf63df5b918928c9522b612d9b
MD5 9a7be03d1579c6f1ef4d27e0c53fd525
BLAKE2b-256 aacf244e698ce18744fd8385a9fc1a15802f6c49b098bc5bab376c9fde88f5ab

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page