Created
October 15, 2020 19:10
-
-
Save MushroomMaula/2eaae0c5f467e5b64338953e891f7de9 to your computer and use it in GitHub Desktop.
More in depth example of fastapi-login usage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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