Skip to main content

A library for quickly creating authentication using JWT and Cookies. Or storing a JWT token in a session

Project description

FastAPI EasyAuth

What is this?

This library quickly and easily creates authentication using JWT and Cookies. You can also use easyauth to identify an active user

Communication with me

If you want to point out inaccuracies, suggest an idea, or report an error, write to the mail tragglesocial@gmail.com

Using

This is the option where you store the jwt token in cookies. There is a more convenient way to store it in a session. Use the storage option in the session The section about storing jwt in a session is called sessionauth

First, we need to import the EasyAuth and Jwt classes from easyauth

from fastapi_easyauth import EasyAuth, Jwt, ALGORITHM

After that, we create instances of classes

jwt = Jwt(
    secret = "SECRET", # The secret key for generating tokens and decoding them. Keep the token secret
    algorithm = ALGORITHM.HS256 # The encryption algorithm
    model = MyModel # Your Pydantic model. When decoding the token, the result will be converted to this model
)

auth = EasyAuth(
    cookie_name = "user" # The Name Of The Cookie File
    jwt = jwt
    expires = exp.EXPIRES_30_DAYS # Cookie lifetime
    )

Great, everything is ready. Now we can create tokens and decode them. Also check if the user is active.

from fastapi import FastAPI, Request, Response, Depends
from fastapi_easyauth import EasyAuth, Jwt, ALGORITHM, exp

from pydantic import BaseModel

class User(BaseModel):
    name: str
    password: str

app = FastAPI()

jwt = Jwt(
    secret = "SECRET",
    algorithm = ALGORITHM.HS256
)

auth = EasyAuth(
    cookie_name = "user"
    jwt = jwt
    expires = exp.EXPIRES_30_DAYS
)

@app.post('/log')
def log(user: User, response: Response):
    token = jwt.create_token(user)
    auth.save_token_in_cookie(response, token)
    return {'status': 200}


@app.get('/active')
def active(user: User = Depends(auth.active_user))
    return user

sessionauth

Storing a JWT token in a session

This is a new way to store jwt tokens. The token will now be stored in the session. For convenience, the SessionAuth class was created

Before you start working with Session Auth in Fastape, you need to connect SessionMiddleware

from fastapi import FastAPI
from starlette.middleware.sessions import SessionMiddleware
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key = 'secret-key')

Using

First, we need to import the necessary classes.

from fastapi_easyauth.sessionauth import SessionAuth
from fastapi_easyauth import Jwt

After that, we create instances of the Jwt and SessionAuth classes

jwt = Jwt(
	'secret'
)

sessionauth = SessionAuth(
	jwt = jwt,
	name_in_session = 'session-auth' # our token will be stored under this name in the session
)

To create and save a token, you can use one or two functions

from pydantic import BaseModel

class UserModel(BaseModel):
	id: int
	username: str


router = APIRouter()

@router.get('/login')
async def login(usermodel: UserModel, request: Request):
	token = sessionauth.create_token(subject = usermodel)
	sessionauth.save_token_in_session(token, request)
	
	#or
	
	sessionauth.create_and_save_token_in_session(
	subject = usermodel,
	request = request
)

  

@router.get('/active')
async def active(
active_user: UserModel = Depends(sessionauth.active_user)
):

	return active_user

The active_user function will return the active user. It will automatically decrypt the token and return the dictionary or Pydantic model. If there is no token, it returns False

Checking if there is an authorized user

Sometimes we want to prevent unauthorized users from accessing our resources. The only_auth and async_only_auth decorators were created for this purpose. You must specify request: Request

How it works

We just need to wrap our endpoint in our decorator.

@router.get('/something')
@only_auth
def something(request: Request): ...


@router.get('/something/async')
@async_only_auth
async def something_async(request: Request): ...

You must specify request: Request only_auth for synchronous endpoint, and async_only_auth for asynchronous endpoint

Creating your own decorators

The OnlyAuthCreater class will help you to create your own decorators First, we need to create an instance of the OnlyAuthCreater class.

json_response = JSONResponse(
    content = {
        'detail': 'Access is closed to unauthorized users'
    },
    status_code = 401
)

creater = OnlyAuthCreater(
    redirect_url = 'http:127.0.0.1:8000/auth/login', # the user will be redirected to this url if he is not logged in.
    response = json_response, # this response will be returned if the user is not logged in
    sessionauth = sessionauth # an instance of the SessionAuth class
)

only_auth_decorator_redirect = creater.create_only_auth_decorator() # Creating a decorator that will redirect the user to a specific url (which you specified when initializing the OnlyAuthCreater class)
only_auth_decorator_response = creater.create_only_auth_decorator(response = True) # Creating a decorator that will return a JSON response (we specified this response when initializing the OnlyAuthCreater class)

async_only_auth_decorator_redirect = creater.create_async_only_auth_decorator() # Asynchronous version. Redirect to a specific url
async_only_auth_decorator_response = creater.create_async_only_auth_decorator(response = True) # Asynchronous version. Returns a JSON response

Now the decorators you have created can be used

@router.get('/test')
@only_auth_decorator_redirect
def test(request: Request): ...

@router.get('/test')
@only_auth_decorator_response
def test(request: Request): ...


@router.get('/test')
@async_only_auth_decorator_redirect
async def test(request: Request): ...

@router.get('/test')
@async_only_auth_decorator_response
async def test(request: Request): ...

What is the RequestNotAdded error?

This error appears for one simple reason. For the only_auth, async_auth and OnlyAuthCreater decorators to work, you need a request sent to your endpoint. To solve this problem, you need to add the request: Request function to your endpoint parameters. This is the only way to work for decorators. Exemple:

# Wrong! You need to specify in the endpoint request
@router.get('/something/async')
@async_only_auth
async def something_async(): ...

# Wrong. This is not the correct name for Request. Be sure to specify the name of the request
@router.get('/something/async')
@async_only_auth
async def something_async(req: Request): ...

# Success!
@router.get('/something/async')
@async_only_auth
async def something_async(request: Request): ...

What was added and changed in version 0.1.0

  • Now, using only an instance of the EasyAuth class, you can create a token and immediately save it in a cookie.
@app.post('/login')
def login(user: User, response: Response):
    token = auth.create_token(subject = user, response = response)
    return token

@app.get('/getToken')
def get_token(request: Request):
    data = auth.decode_token(request)
    return data
  • The name of the Auth class has also been changed to EasyAuth.
  • All functions have been documented
  • Now, when initializing the Jwt class, you can specify the model. Each time you decode the token, the result will be returned in the form of the model that you specified
class User(BaseModel):
    id: int
    username: str

jwt = Jwt(
    secret = "SECRET",
    model = User
)


def get_user(token: str) -> User:
    # if you did not specify the model during initialization, the result will be returned as a dictionary
    
    user = jwt.decode_token(token)
    return user


def get_user_in_model(token: str) -> User:
    # If you are not going to add models when initializing the Jwt class, then you can use the decode_taken_in_model function.
    # It accepts a token and a model in which
    
    user = jwt.decode_token_in_model(token, User)
    return user

There are also two simple functions in this library so far. The first is password hashing. The second is an error about an unauthorized user.

def hash_password(password: str) -> str:
    """
    hash_password: hashes the password

    Args:
        password (str): User password

    Returns:
        str: hashed password
    """

    return hashlib.sha256(password.encode()).hexdigest()


def not_authorized() -> HTTPException:
    """
    not_authorized: a function that returns an error when an unauthorized user
    """

    return HTTPException(
        status_code=401,
        detail='Unauthorized'
    )

What was added or changed in version 0.2.1

  • A new way of storing the Jwt token has been added. It can now be stored in a session. The SessionAuth class has been added to work with sessions
  • Added new decorators only_auth and async_only_auth. The goal is to return a JSON response if the user is not logged in, otherwise endpoint works
  • The OnlyAuthCreater class has been added. This class creates custom decorators. You can decide which JSON response will be returned to the unauthorized user. Or redirect the user to another link

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-easyauth-0.3.1.tar.gz (13.4 kB view details)

Uploaded Source

Built Distribution

fastapi_easyauth-0.3.1-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

Details for the file fastapi-easyauth-0.3.1.tar.gz.

File metadata

  • Download URL: fastapi-easyauth-0.3.1.tar.gz
  • Upload date:
  • Size: 13.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.11.3

File hashes

Hashes for fastapi-easyauth-0.3.1.tar.gz
Algorithm Hash digest
SHA256 8cbd04586bf4115dd8829097988cac9c0a9e0c04e194e43ec2c3cb9ee0a494ac
MD5 08305b929ec78f8a3ec6853962cbabc4
BLAKE2b-256 b695ff77d114e093156f1c60f31f8307d68613f46ea4a14e20c82b9e10718c0c

See more details on using hashes here.

File details

Details for the file fastapi_easyauth-0.3.1-py3-none-any.whl.

File metadata

File hashes

Hashes for fastapi_easyauth-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 426b2f0e20380dac2ec77f528bbc72ec803b8966cb5bea6d103bb73b8e9f08ef
MD5 7889cce04e533871c538fc3537e4f2a0
BLAKE2b-256 1e740d7b1bd9d08358131bc0f23038ece2e880bb04a16c4ac8a972086925ebde

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