Skip to content

Instantly share code, notes, and snippets.

@MushroomMaula
Created October 15, 2020 19:10
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MushroomMaula/2eaae0c5f467e5b64338953e891f7de9 to your computer and use it in GitHub Desktop.
Save MushroomMaula/2eaae0c5f467e5b64338953e891f7de9 to your computer and use it in GitHub Desktop.
More in depth example of fastapi-login usage
from fastapi import FastAPI, Depends
from fastapi.security import OAuth2PasswordRequestForm
from fastapi_login import LoginManager
from fastapi_login.exceptions import InvalidCredentialsException
app = FastAPI()
manager = LoginManager(
# here we set the secret LoginManager uses to encrypt our Token
# normally you would use Environment Variables or some kind of config
# where you can store the secret
secret="your-secret",
# We also have to set the tokenUrl, which is used to register the URL
# in the OpenAPI docs.
# This should be the same URL the user uses to login to your Application
tokenUrl="/auth/login"
)
# Stores all kind of things including our users
DATABASE = {
'users': {
'admin': {
'username': 'admin',
# Only store hashed passwords in your db!
'password': 'hashed-password'
},
'anotherUser': {
'username': 'anotherUser',
'password': 'another-hashed-password'
}
}
}
@manager.user_loader
def get_user_from_db(username: str):
"""
Retrieve a user from the Database
:param str username: The username of the user, used as a unique key in the database
:return dict: The responding user
"""
return DATABASE['users'].get(username)
# remember this should be the same URL we used when initializing the LoginManager
@app.route('/auth/login')
def login(data: OAuth2PasswordRequestForm = Depends()):
# here we can use OAuth2PasswordRequestForm provided by FastAPI, so we dont have
# to define the Dependency ourselves. More at the FastAPI docs
# https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/#oauth2passwordrequestform
username = data.username
password = data.password
# now lets check if the user is in our db and if the password matches
user = get_user_from_db(username)
if not user:
# If our user is not in the db return a HTTP Exception
# we can use the one provided by fastapi-login
# if you want to you can also define your own using fastapi.HTTPException
raise InvalidCredentialsException
elif user['password'] != password:
# the provided password is invalid
raise InvalidCredentialsException
# now we create a token which our user can (for a specific time) use to access protected routes
access_token = manager.create_access_token(
# data is the value of the token
# sub should be the key used to look up the user in the database later on
# in our case thats the username, as `get_user_from_db` needs the username as a parameter
data={'sub': username}
)
# now we can return the encrypted token
return {'access_token': access_token}
# if you want to redirect after a successfull login you can either redirct client side using
# JavaScript or using a RedirectResponse and returning the access_token using a cookie
#
# response = RedirectResponse(...)
# manager.set_cookie(reponse, access_token)
# return response
#
# to enable access using cookies instead of headers the `use_cookies` parameter needs to be
# set to true on the LoginManagers initialization
@app.route('/private')
def logged_in_users_only(user=Depends(manager)):
# if the request is now made from a client which has logged in and a valid access_token
# is either in the header or as a cookie, if cookie authorization has been
# set on initialization of the manager, in the Request fastapi-login will automatically
# provide the user object from our database to this function.
# for example if the 'admin' user has logged in and has the token in the headers
# `user` would equal {'username': 'admin', 'password': 'hashed-password'}, the same as
# `get_user_from_db`
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment