diff --git a/configuration/oauth/index.html b/configuration/oauth/index.html index 0c6a80e0..8688d7cb 100644 --- a/configuration/oauth/index.html +++ b/configuration/oauth/index.html @@ -700,7 +700,7 @@ class UserTable(Base, SQLAlchemyBaseUserTable): - oauth_accounts = relationship("OAuthAccount") + oauth_accounts = relationship("OAuthAccountTable") class OAuthAccountTable(SQLAlchemyBaseOAuthAccountTable, Base): @@ -745,7 +745,7 @@ class UserTable(Base, SQLAlchemyBaseUserTable): - oauth_accounts = relationship("OAuthAccount") + oauth_accounts = relationship("OAuthAccountTable") class OAuthAccountTable(SQLAlchemyBaseOAuthAccountTable, Base): diff --git a/index.html b/index.html index de4e9826..e104b11f 100644 --- a/index.html +++ b/index.html @@ -595,7 +595,7 @@ PyPI version Downloads

-

All Contributors

+

All Contributors

@@ -705,6 +705,8 @@
jakemanger

πŸ› πŸ’»
Ikko Ashimine

πŸ’»
MatyΓ‘Ε‘ Richter

πŸ’» +
Hazedd

πŸ› πŸ“– +
Luis Roel

πŸ’΅ diff --git a/search/search_index.json b/search/search_index.json index 58bf3bc2..17099d81 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"FastAPI Users \u00b6 Ready-to-use and customizable users management for FastAPI Documentation : https://fastapi-users.github.io/fastapi-users/ Source Code : https://github.com/fastapi-users/fastapi-users Add quickly a registration and authentication system to your FastAPI project. FastAPI Users is designed to be as customizable and adaptable as possible. Features \u00b6 Extensible base user model Ready-to-use register, login, reset password and verify e-mail routes Ready-to-use social OAuth2 login flow Dependency callables to inject current user in route Pluggable password validation Customizable database backend SQLAlchemy ORM async backend included MongoDB async backend included thanks to mongodb/motor Tortoise ORM backend included ormar backend included Multiple customizable authentication backends Transports: Authorization header, Cookie Strategies: JWT, Database, Redis Full OpenAPI schema support, even with several authentication backends \ud83d\udcda Discover my book: Building Data Science Applications with FastAPI \u00b6 Develop, manage, and deploy efficient machine learning applications with Python What is this book about? \u00b6 This book covers the following exciting features: Explore the basics of modern Python and async I/O programming Get to grips with basic and advanced concepts of the FastAPI framework Implement a FastAPI dependency to efficiently run a machine learning model Integrate a simple face detection algorithm in a FastAPI backend Integrate common Python data science libraries in a web backend Deploy a performant and reliable web backend for a data science application If you feel this book is for you, get your copy today! Contributors and sponsors \u2728\u2615\ufe0f \u00b6 Thanks goes to these wonderful people ( emoji key ): Fran\u00e7ois Voron \ud83d\udea7 Paolo Dina \ud83d\udcb5 \ud83d\udcbb Dmytro Ohorodnik \ud83d\udc1b Matthew D. Scholefield \ud83d\udc1b roywes \ud83d\udc1b \ud83d\udcbb Satwik Kansal \ud83d\udcd6 Edd Salkield \ud83d\udcbb \ud83d\udcd6 mark-todd \ud83d\udcbb \ud83d\udcd6 lill74 \ud83d\udc1b \ud83d\udcbb \ud83d\udcd6 SelfhostedPro \ud83d\udee1\ufe0f \ud83d\udcbb Oskar Gmerek \ud83d\udcd6 Martin Collado \ud83d\udc1b \ud83d\udcbb Eric Lopes \ud83d\udcd6 \ud83d\udee1\ufe0f Beau Breon \ud83d\udcbb Niyas Mohammed \ud83d\udcd6 prostomarkeloff \ud83d\udcd6 \ud83d\udcbb Marius M\u00e9zerette \ud83d\udc1b \ud83e\udd14 Nickolas Grigoriadis \ud83d\udc1b Open Data Coder \ud83e\udd14 Mohammed Alshehri \ud83e\udd14 Tyler Renelle \ud83e\udd14 collerek \ud83d\udcbb Robert Bracco \ud83d\udcb5 Augusto Herrmann \ud83d\udcd6 Smithybrewer \ud83d\udc1b silllli \ud83d\udcd6 alexferrari88 \ud83d\udcb5 sandalwoodbox \ud83d\udc1b Vlad Hoi \ud83d\udcd6 Joe Nudell \ud83d\udc1b Ben \ud83d\udcbb BoYanZh \ud83d\udcd6 David Brochart \ud83d\udcd6 \ud83d\udcbb Daan Beverdam \ud83d\udcbb St\u00e9phane Raimbault \u26a0\ufe0f \ud83d\udc1b Sondre Lilleb\u00f8 Gundersen \ud83d\udcd6 Maxim \ud83d\udcd6 \ud83d\udc1b scottdavort \ud83d\udcb5 John Dukewich \ud83d\udcd6 Yasser Tahiri \ud83d\udcbb Brandon H. Goding \ud83d\udcbb PovilasK \ud83d\udcbb Just van den Broecke \ud83d\udcb5 jakemanger \ud83d\udc1b \ud83d\udcbb Ikko Ashimine \ud83d\udcbb Maty\u00e1\u0161 Richter \ud83d\udcbb This project follows the all-contributors specification. Contributions of any kind welcome! Development \u00b6 Setup environment \u00b6 You should create a virtual environment and activate it: python -m venv venv/ source venv/bin/activate And then install the development dependencies: pip install -r requirements.dev.txt Run unit tests \u00b6 You can run all the tests with: make test The command will start a MongoDB container for the related unit tests. So you should have Docker installed. Alternatively, you can run pytest yourself. The MongoDB unit tests will be skipped if no server is available on your local machine: pytest There are quite a few unit tests, so you might run into ulimit issues where there are too many open file descriptors. You may be able to set a new, higher limit temporarily with: ulimit -n 2048 Format the code \u00b6 Execute the following command to apply isort and black formatting: make format License \u00b6 This project is licensed under the terms of the MIT license.","title":"About"},{"location":"#fastapi-users","text":"Ready-to-use and customizable users management for FastAPI Documentation : https://fastapi-users.github.io/fastapi-users/ Source Code : https://github.com/fastapi-users/fastapi-users Add quickly a registration and authentication system to your FastAPI project. FastAPI Users is designed to be as customizable and adaptable as possible.","title":"FastAPI Users"},{"location":"#features","text":"Extensible base user model Ready-to-use register, login, reset password and verify e-mail routes Ready-to-use social OAuth2 login flow Dependency callables to inject current user in route Pluggable password validation Customizable database backend SQLAlchemy ORM async backend included MongoDB async backend included thanks to mongodb/motor Tortoise ORM backend included ormar backend included Multiple customizable authentication backends Transports: Authorization header, Cookie Strategies: JWT, Database, Redis Full OpenAPI schema support, even with several authentication backends","title":"Features"},{"location":"#discover-my-book-building-data-science-applications-with-fastapi","text":"Develop, manage, and deploy efficient machine learning applications with Python","title":"\ud83d\udcda Discover my book: Building Data Science Applications with FastAPI"},{"location":"#what-is-this-book-about","text":"This book covers the following exciting features: Explore the basics of modern Python and async I/O programming Get to grips with basic and advanced concepts of the FastAPI framework Implement a FastAPI dependency to efficiently run a machine learning model Integrate a simple face detection algorithm in a FastAPI backend Integrate common Python data science libraries in a web backend Deploy a performant and reliable web backend for a data science application If you feel this book is for you, get your copy today!","title":"What is this book about?"},{"location":"#contributors-and-sponsors","text":"Thanks goes to these wonderful people ( emoji key ): Fran\u00e7ois Voron \ud83d\udea7 Paolo Dina \ud83d\udcb5 \ud83d\udcbb Dmytro Ohorodnik \ud83d\udc1b Matthew D. Scholefield \ud83d\udc1b roywes \ud83d\udc1b \ud83d\udcbb Satwik Kansal \ud83d\udcd6 Edd Salkield \ud83d\udcbb \ud83d\udcd6 mark-todd \ud83d\udcbb \ud83d\udcd6 lill74 \ud83d\udc1b \ud83d\udcbb \ud83d\udcd6 SelfhostedPro \ud83d\udee1\ufe0f \ud83d\udcbb Oskar Gmerek \ud83d\udcd6 Martin Collado \ud83d\udc1b \ud83d\udcbb Eric Lopes \ud83d\udcd6 \ud83d\udee1\ufe0f Beau Breon \ud83d\udcbb Niyas Mohammed \ud83d\udcd6 prostomarkeloff \ud83d\udcd6 \ud83d\udcbb Marius M\u00e9zerette \ud83d\udc1b \ud83e\udd14 Nickolas Grigoriadis \ud83d\udc1b Open Data Coder \ud83e\udd14 Mohammed Alshehri \ud83e\udd14 Tyler Renelle \ud83e\udd14 collerek \ud83d\udcbb Robert Bracco \ud83d\udcb5 Augusto Herrmann \ud83d\udcd6 Smithybrewer \ud83d\udc1b silllli \ud83d\udcd6 alexferrari88 \ud83d\udcb5 sandalwoodbox \ud83d\udc1b Vlad Hoi \ud83d\udcd6 Joe Nudell \ud83d\udc1b Ben \ud83d\udcbb BoYanZh \ud83d\udcd6 David Brochart \ud83d\udcd6 \ud83d\udcbb Daan Beverdam \ud83d\udcbb St\u00e9phane Raimbault \u26a0\ufe0f \ud83d\udc1b Sondre Lilleb\u00f8 Gundersen \ud83d\udcd6 Maxim \ud83d\udcd6 \ud83d\udc1b scottdavort \ud83d\udcb5 John Dukewich \ud83d\udcd6 Yasser Tahiri \ud83d\udcbb Brandon H. Goding \ud83d\udcbb PovilasK \ud83d\udcbb Just van den Broecke \ud83d\udcb5 jakemanger \ud83d\udc1b \ud83d\udcbb Ikko Ashimine \ud83d\udcbb Maty\u00e1\u0161 Richter \ud83d\udcbb This project follows the all-contributors specification. Contributions of any kind welcome!","title":"Contributors and sponsors \u2728\u2615\ufe0f"},{"location":"#development","text":"","title":"Development"},{"location":"#setup-environment","text":"You should create a virtual environment and activate it: python -m venv venv/ source venv/bin/activate And then install the development dependencies: pip install -r requirements.dev.txt","title":"Setup environment"},{"location":"#run-unit-tests","text":"You can run all the tests with: make test The command will start a MongoDB container for the related unit tests. So you should have Docker installed. Alternatively, you can run pytest yourself. The MongoDB unit tests will be skipped if no server is available on your local machine: pytest There are quite a few unit tests, so you might run into ulimit issues where there are too many open file descriptors. You may be able to set a new, higher limit temporarily with: ulimit -n 2048","title":"Run unit tests"},{"location":"#format-the-code","text":"Execute the following command to apply isort and black formatting: make format","title":"Format the code"},{"location":"#license","text":"This project is licensed under the terms of the MIT license.","title":"License"},{"location":"installation/","text":"Installation \u00b6 You can add FastAPI Users to your FastAPI project in a few easy steps. First of all, install the dependency: With SQLAlchemy support \u00b6 pip install 'fastapi-users[sqlalchemy2]' With MongoDB support \u00b6 pip install 'fastapi-users[mongodb]' With Tortoise ORM support \u00b6 pip install 'fastapi-users[tortoise-orm]' With ormar support \u00b6 pip install 'fastapi-users[ormar]' That's it! Now, let's have a look at our User model .","title":"Installation"},{"location":"installation/#installation","text":"You can add FastAPI Users to your FastAPI project in a few easy steps. First of all, install the dependency:","title":"Installation"},{"location":"installation/#with-sqlalchemy-support","text":"pip install 'fastapi-users[sqlalchemy2]'","title":"With SQLAlchemy support"},{"location":"installation/#with-mongodb-support","text":"pip install 'fastapi-users[mongodb]'","title":"With MongoDB support"},{"location":"installation/#with-tortoise-orm-support","text":"pip install 'fastapi-users[tortoise-orm]'","title":"With Tortoise ORM support"},{"location":"installation/#with-ormar-support","text":"pip install 'fastapi-users[ormar]' That's it! Now, let's have a look at our User model .","title":"With ormar support"},{"location":"configuration/full-example/","text":"Full example \u00b6 Here is a full working example with JWT authentication to help get you started. Warning Notice that SECRET should be changed to a strong passphrase. Insecure passwords may give attackers full access to your database. SQLAlchemy \u00b6 Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[sqlalchemy] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import auth_backend , current_active_user , fastapi_users app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from app.models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import SQLAlchemyUserDatabase from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : SQLAlchemyUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True ) MongoDB \u00b6 Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[mongodb] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import auth_backend , current_active_user , fastapi_users app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } import os import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from app.models import UserDB DATABASE_URL = os . environ [ \"DATABASE_URL\" ] client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import MongoDBUserDatabase from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : MongoDBUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True ) Tortoise ORM \u00b6 Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[tortoise-orm] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from tortoise.contrib.fastapi import register_tortoise from app.db import DATABASE_URL from app.models import UserDB from app.users import auth_backend , current_active_user , fastapi_users app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"app.models\" ]}, generate_schemas = True , ) from fastapi_users.db import TortoiseUserDatabase from app.models import UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel ) from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import TortoiseUserDatabase from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : TortoiseUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True ) What now? \u00b6 You're ready to go! Be sure to check the Usage section to understand how to work with FastAPI Users .","title":"Full example"},{"location":"configuration/full-example/#full-example","text":"Here is a full working example with JWT authentication to help get you started. Warning Notice that SECRET should be changed to a strong passphrase. Insecure passwords may give attackers full access to your database.","title":"Full example"},{"location":"configuration/full-example/#sqlalchemy","text":"Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[sqlalchemy] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import auth_backend , current_active_user , fastapi_users app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from app.models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import SQLAlchemyUserDatabase from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : SQLAlchemyUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"SQLAlchemy"},{"location":"configuration/full-example/#mongodb","text":"Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[mongodb] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import auth_backend , current_active_user , fastapi_users app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } import os import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from app.models import UserDB DATABASE_URL = os . environ [ \"DATABASE_URL\" ] client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import MongoDBUserDatabase from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : MongoDBUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"MongoDB"},{"location":"configuration/full-example/#tortoise-orm","text":"Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[tortoise-orm] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from tortoise.contrib.fastapi import register_tortoise from app.db import DATABASE_URL from app.models import UserDB from app.users import auth_backend , current_active_user , fastapi_users app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"app.models\" ]}, generate_schemas = True , ) from fastapi_users.db import TortoiseUserDatabase from app.models import UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel ) from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import TortoiseUserDatabase from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : TortoiseUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"Tortoise ORM"},{"location":"configuration/full-example/#what-now","text":"You're ready to go! Be sure to check the Usage section to understand how to work with FastAPI Users .","title":"What now?"},{"location":"configuration/models/","text":"Models \u00b6 FastAPI Users defines a minimal User model for authentication purposes. It is structured like this: id ( UUID4 ) \u2013 Unique identifier of the user. Defaults to a UUID4 . email ( str ) \u2013 Email of the user. Validated by email-validator . is_active ( bool ) \u2013 Whether or not the user is active. If not, login and forgot password requests will be denied. Defaults to True . is_verified ( bool ) \u2013 Whether or not the user is verified. Optional but helpful with the verify router logic. Defaults to False . is_superuser ( bool ) \u2013 Whether or not the user is a superuser. Useful to implement administration logic. Defaults to False . Define your models \u00b6 There are four Pydantic models variations provided as mixins: BaseUser , which provides the basic fields and validation ; BaseCreateUser , dedicated to user registration, which consists of compulsory email and password fields ; BaseUpdateUser , dedicated to user profile update, which adds an optional password field ; BaseUserDB , which is a representation of the user in database, adding a hashed_password field. You should define each of those variations, inheriting from each mixin: from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass Adding your own fields \u00b6 You can of course add your own properties there to fit to your needs. In the example below, we add a required string property, first_name , and an optional date property, birthdate . import datetime from fastapi_users import models class User ( models . BaseUser ): first_name : str birthdate : Optional [ datetime . date ] class UserCreate ( models . BaseUserCreate ): first_name : str birthdate : Optional [ datetime . date ] class UserUpdate ( models . BaseUserUpdate ): first_name : Optional [ str ] birthdate : Optional [ datetime . date ] class UserDB ( User , models . BaseUserDB ): pass","title":"Models"},{"location":"configuration/models/#models","text":"FastAPI Users defines a minimal User model for authentication purposes. It is structured like this: id ( UUID4 ) \u2013 Unique identifier of the user. Defaults to a UUID4 . email ( str ) \u2013 Email of the user. Validated by email-validator . is_active ( bool ) \u2013 Whether or not the user is active. If not, login and forgot password requests will be denied. Defaults to True . is_verified ( bool ) \u2013 Whether or not the user is verified. Optional but helpful with the verify router logic. Defaults to False . is_superuser ( bool ) \u2013 Whether or not the user is a superuser. Useful to implement administration logic. Defaults to False .","title":"Models"},{"location":"configuration/models/#define-your-models","text":"There are four Pydantic models variations provided as mixins: BaseUser , which provides the basic fields and validation ; BaseCreateUser , dedicated to user registration, which consists of compulsory email and password fields ; BaseUpdateUser , dedicated to user profile update, which adds an optional password field ; BaseUserDB , which is a representation of the user in database, adding a hashed_password field. You should define each of those variations, inheriting from each mixin: from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass","title":"Define your models"},{"location":"configuration/models/#adding-your-own-fields","text":"You can of course add your own properties there to fit to your needs. In the example below, we add a required string property, first_name , and an optional date property, birthdate . import datetime from fastapi_users import models class User ( models . BaseUser ): first_name : str birthdate : Optional [ datetime . date ] class UserCreate ( models . BaseUserCreate ): first_name : str birthdate : Optional [ datetime . date ] class UserUpdate ( models . BaseUserUpdate ): first_name : Optional [ str ] birthdate : Optional [ datetime . date ] class UserDB ( User , models . BaseUserDB ): pass","title":"Adding your own fields"},{"location":"configuration/oauth/","text":"OAuth2 \u00b6 FastAPI Users provides an optional OAuth2 authentication support. It relies on HTTPX OAuth library , which is a pure-async implementation of OAuth2. Installation \u00b6 You should install the library with the optional dependencies for OAuth: pip install 'fastapi-users[sqlalchemy2,oauth]' pip install 'fastapi-users[mongodb,oauth]' pip install 'fastapi-users[tortoise-orm,oauth]' Configuration \u00b6 Instantiate an OAuth2 client \u00b6 You first need to get an HTTPX OAuth client instance. Read the documentation for more information. from httpx_oauth.clients.google import GoogleOAuth2 google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) Setup the models \u00b6 The user models differ a bit from the standard one as we have to have a way to store the OAuth information (access tokens, account ids...). from fastapi_users import models class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass Notice that we inherit from the BaseOAuthAccountMixin , which adds a List of BaseOAuthAccount objects. This object is structured like this: id ( UUID4 ) \u2013 Unique identifier of the OAuth account information. Defaults to a UUID4 . oauth_name ( str ) \u2013 Name of the OAuth service. It corresponds to the name property of the OAuth client. access_token ( str ) \u2013 Access token. expires_at ( Optional[int] ) - Timestamp at which the access token is expired. refresh_token ( Optional[str] ) \u2013 On services that support it, a token to get a fresh access token. account_id ( str ) - Identifier of the OAuth account on the corresponding service. account_email ( str ) - Email address of the OAuth account on the corresponding service. Setup the database adapter \u00b6 SQLAlchemy \u00b6 You'll need to define the SQLAlchemy model for storing OAuth accounts. We provide a base one for this: from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import relationship , sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): oauth_accounts = relationship ( \"OAuthAccount\" ) class OAuthAccountTable ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable , OAuthAccountTable ) Notice that we also manually added a relationship on the UserTable so that SQLAlchemy can properly retrieve the OAuth accounts of the user. When instantiating the database adapter, you should pass this SQLAlchemy model: from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import relationship , sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): oauth_accounts = relationship ( \"OAuthAccount\" ) class OAuthAccountTable ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable , OAuthAccountTable ) MongoDB \u00b6 Nothing to do, the basic configuration is enough. Tortoise ORM \u00b6 You'll need to define the Tortoise model for storing the OAuth account model. We provide a base one for this: from fastapi_users import models from fastapi_users.db import TortoiseBaseOAuthAccountModel , TortoiseBaseUserModel from tortoise import fields from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel class OAuthAccount ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"oauth_accounts\" ) Warning Note that you should define the foreign key yourself, so that you can point it the user model in your namespace. Then, you should declare it on the database adapter: from fastapi_users.db import TortoiseUserDatabase from .models import OAuthAccount , UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel , OAuthAccount ) Generate a router \u00b6 Once you have a FastAPIUsers instance, you can make it generate a single OAuth router for a given client and authentication backend. app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) Full example \u00b6 Warning Notice that SECRET should be changed to a strong passphrase. Insecure passwords may give attackers full access to your database. SQLAlchemy \u00b6 Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[sqlalchemy,oauth] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import ( auth_backend , current_active_user , fastapi_users , google_oauth_client , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import relationship , sessionmaker from app.models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): oauth_accounts = relationship ( \"OAuthAccount\" ) class OAuthAccountTable ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable , OAuthAccountTable ) from fastapi_users import models class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass import os from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import SQLAlchemyUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( os . environ [ \"GOOGLE_OAUTH_CLIENT_ID\" ], os . environ [ \"GOOGLE_OAUTH_CLIENT_SECRET\" ], ) class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : SQLAlchemyUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True ) MongoDB \u00b6 Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[mongodb,oauth] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import ( auth_backend , current_active_user , fastapi_users , google_oauth_client , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } import os import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from app.models import UserDB DATABASE_URL = os . environ [ \"DATABASE_URL\" ] client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass import os from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import MongoDBUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( os . environ [ \"GOOGLE_OAUTH_CLIENT_ID\" ], os . environ [ \"GOOGLE_OAUTH_CLIENT_SECRET\" ], ) class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : MongoDBUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True ) Tortoise ORM \u00b6 Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[tortoise-orm,oauth] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from tortoise.contrib.fastapi import register_tortoise from app.db import DATABASE_URL from app.models import UserDB from app.users import ( auth_backend , current_active_user , fastapi_users , google_oauth_client , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"app.models\" ]}, generate_schemas = True , ) from fastapi_users.db import TortoiseUserDatabase from app.models import OAuthAccount , UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel , OAuthAccount ) from fastapi_users import models from fastapi_users.db import TortoiseBaseOAuthAccountModel , TortoiseBaseUserModel from tortoise import fields from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel class OAuthAccount ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"oauth_accounts\" ) import os from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import TortoiseUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( os . environ [ \"GOOGLE_OAUTH_CLIENT_ID\" ], os . environ [ \"GOOGLE_OAUTH_CLIENT_SECRET\" ], ) class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : TortoiseUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"OAuth2"},{"location":"configuration/oauth/#oauth2","text":"FastAPI Users provides an optional OAuth2 authentication support. It relies on HTTPX OAuth library , which is a pure-async implementation of OAuth2.","title":"OAuth2"},{"location":"configuration/oauth/#installation","text":"You should install the library with the optional dependencies for OAuth: pip install 'fastapi-users[sqlalchemy2,oauth]' pip install 'fastapi-users[mongodb,oauth]' pip install 'fastapi-users[tortoise-orm,oauth]'","title":"Installation"},{"location":"configuration/oauth/#configuration","text":"","title":"Configuration"},{"location":"configuration/oauth/#instantiate-an-oauth2-client","text":"You first need to get an HTTPX OAuth client instance. Read the documentation for more information. from httpx_oauth.clients.google import GoogleOAuth2 google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" )","title":"Instantiate an OAuth2 client"},{"location":"configuration/oauth/#setup-the-models","text":"The user models differ a bit from the standard one as we have to have a way to store the OAuth information (access tokens, account ids...). from fastapi_users import models class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass Notice that we inherit from the BaseOAuthAccountMixin , which adds a List of BaseOAuthAccount objects. This object is structured like this: id ( UUID4 ) \u2013 Unique identifier of the OAuth account information. Defaults to a UUID4 . oauth_name ( str ) \u2013 Name of the OAuth service. It corresponds to the name property of the OAuth client. access_token ( str ) \u2013 Access token. expires_at ( Optional[int] ) - Timestamp at which the access token is expired. refresh_token ( Optional[str] ) \u2013 On services that support it, a token to get a fresh access token. account_id ( str ) - Identifier of the OAuth account on the corresponding service. account_email ( str ) - Email address of the OAuth account on the corresponding service.","title":"Setup the models"},{"location":"configuration/oauth/#setup-the-database-adapter","text":"","title":"Setup the database adapter"},{"location":"configuration/oauth/#sqlalchemy","text":"You'll need to define the SQLAlchemy model for storing OAuth accounts. We provide a base one for this: from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import relationship , sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): oauth_accounts = relationship ( \"OAuthAccount\" ) class OAuthAccountTable ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable , OAuthAccountTable ) Notice that we also manually added a relationship on the UserTable so that SQLAlchemy can properly retrieve the OAuth accounts of the user. When instantiating the database adapter, you should pass this SQLAlchemy model: from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import relationship , sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): oauth_accounts = relationship ( \"OAuthAccount\" ) class OAuthAccountTable ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable , OAuthAccountTable )","title":"SQLAlchemy"},{"location":"configuration/oauth/#mongodb","text":"Nothing to do, the basic configuration is enough.","title":"MongoDB"},{"location":"configuration/oauth/#tortoise-orm","text":"You'll need to define the Tortoise model for storing the OAuth account model. We provide a base one for this: from fastapi_users import models from fastapi_users.db import TortoiseBaseOAuthAccountModel , TortoiseBaseUserModel from tortoise import fields from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel class OAuthAccount ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"oauth_accounts\" ) Warning Note that you should define the foreign key yourself, so that you can point it the user model in your namespace. Then, you should declare it on the database adapter: from fastapi_users.db import TortoiseUserDatabase from .models import OAuthAccount , UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel , OAuthAccount )","title":"Tortoise ORM"},{"location":"configuration/oauth/#generate-a-router","text":"Once you have a FastAPIUsers instance, you can make it generate a single OAuth router for a given client and authentication backend. app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], )","title":"Generate a router"},{"location":"configuration/oauth/#full-example","text":"Warning Notice that SECRET should be changed to a strong passphrase. Insecure passwords may give attackers full access to your database.","title":"Full example"},{"location":"configuration/oauth/#sqlalchemy_1","text":"Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[sqlalchemy,oauth] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import ( auth_backend , current_active_user , fastapi_users , google_oauth_client , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import relationship , sessionmaker from app.models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): oauth_accounts = relationship ( \"OAuthAccount\" ) class OAuthAccountTable ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable , OAuthAccountTable ) from fastapi_users import models class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass import os from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import SQLAlchemyUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( os . environ [ \"GOOGLE_OAUTH_CLIENT_ID\" ], os . environ [ \"GOOGLE_OAUTH_CLIENT_SECRET\" ], ) class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : SQLAlchemyUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"SQLAlchemy"},{"location":"configuration/oauth/#mongodb_1","text":"Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[mongodb,oauth] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import ( auth_backend , current_active_user , fastapi_users , google_oauth_client , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } import os import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from app.models import UserDB DATABASE_URL = os . environ [ \"DATABASE_URL\" ] client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass import os from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import MongoDBUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( os . environ [ \"GOOGLE_OAUTH_CLIENT_ID\" ], os . environ [ \"GOOGLE_OAUTH_CLIENT_SECRET\" ], ) class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : MongoDBUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"MongoDB"},{"location":"configuration/oauth/#tortoise-orm_1","text":"Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[tortoise-orm,oauth] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from tortoise.contrib.fastapi import register_tortoise from app.db import DATABASE_URL from app.models import UserDB from app.users import ( auth_backend , current_active_user , fastapi_users , google_oauth_client , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"app.models\" ]}, generate_schemas = True , ) from fastapi_users.db import TortoiseUserDatabase from app.models import OAuthAccount , UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel , OAuthAccount ) from fastapi_users import models from fastapi_users.db import TortoiseBaseOAuthAccountModel , TortoiseBaseUserModel from tortoise import fields from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel class OAuthAccount ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"oauth_accounts\" ) import os from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import TortoiseUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( os . environ [ \"GOOGLE_OAUTH_CLIENT_ID\" ], os . environ [ \"GOOGLE_OAUTH_CLIENT_SECRET\" ], ) class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : TortoiseUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"Tortoise ORM"},{"location":"configuration/overview/","text":"Overview \u00b6 The schema below shows you how the library is structured and how each part fit together. flowchart LR FASTAPI_USERS{FastAPIUsers} USER_MANAGER{UserManager} DATABASE_DEPENDENCY[[get_user_db]] USER_MANAGER_DEPENDENCY[[get_user_manager]] CURRENT_USER[[current_user]] subgraph MODELS[Models] direction RL USER[User] USER_CREATE[UserCreate] USER_UPDATE[UserUpdate] USER_DB[UserDB] end subgraph DATABASE[Database adapters] direction RL SQLALCHEMY[SQLAlchemy] MONGODB[MongoDB] TORTOISE[Tortoise ORM] ORMAR[Ormar] end subgraph ROUTERS[Routers] direction RL AUTH[[get_auth_router]] OAUTH[[get_oauth_router]] REGISTER[[get_register_router]] VERIFY[[get_verify_router]] RESET[[get_reset_password_router]] USERS[[get_users_router]] end subgraph AUTH_BACKENDS[Authentication] direction RL subgraph TRANSPORTS[Transports] direction RL COOKIE[CookieTransport] BEARER[BearerTransport] end subgraph STRATEGIES[Strategies] direction RL JWT[JWTStrategy] end AUTH_BACKEND{AuthenticationBackend} end DATABASE --> DATABASE_DEPENDENCY DATABASE_DEPENDENCY --> USER_MANAGER MODELS --> USER_MANAGER MODELS --> FASTAPI_USERS USER_MANAGER --> USER_MANAGER_DEPENDENCY USER_MANAGER_DEPENDENCY --> FASTAPI_USERS FASTAPI_USERS --> ROUTERS TRANSPORTS --> AUTH_BACKEND STRATEGIES --> AUTH_BACKEND AUTH_BACKEND --> AUTH AUTH_BACKEND --> OAUTH AUTH_BACKEND --> FASTAPI_USERS FASTAPI_USERS --> CURRENT_USER Models \u00b6 Pydantic models representing the data structure of a user. Base classes are provided with the required fields to make authentication work. You should sub-class each of them and add your own fields there. \u27a1\ufe0f Configure the models Database adapters \u00b6 FastAPI Users is compatible with various databases and ORM. To build the interface between those database tools and the library, we provide database adapters classes that you need to instantiate and configure. \u27a1\ufe0f I'm using SQLAlchemy \u27a1\ufe0f I'm using MongoDB \u27a1\ufe0f I'm using Tortoise ORM \u27a1\ufe0f I'm using ormar Authentication backends \u00b6 Authentication backends define the way users sessions are managed in your app, like access tokens or cookies. They are composed of two parts: a transport , which is how the token will be carried over the requests (e.g. cookies, headers...) and a strategy , which is how the token will be generated and secured (e.g. a JWT, a token in database...). \u27a1\ufe0f Configure the authentication backends UserManager \u00b6 The UserManager object bears most of the logic of FastAPI Users: registration, verification, password reset... We provide a BaseUserManager with this common logic; which you should overload to define how to validate passwords or handle events. This UserManager object should be provided through a FastAPI dependency, get_user_manager . \u27a1\ufe0f Configure UserManager FastAPIUsers and routers \u00b6 Finally, FastAPIUsers object is the main class from which you'll be able to generate routers for classic routes like registration or login, but also get the current_user dependency factory to inject the authenticated user in your own routes. \u27a1\ufe0f Configure FastAPIUsers and routers","title":"Overview"},{"location":"configuration/overview/#overview","text":"The schema below shows you how the library is structured and how each part fit together. flowchart LR FASTAPI_USERS{FastAPIUsers} USER_MANAGER{UserManager} DATABASE_DEPENDENCY[[get_user_db]] USER_MANAGER_DEPENDENCY[[get_user_manager]] CURRENT_USER[[current_user]] subgraph MODELS[Models] direction RL USER[User] USER_CREATE[UserCreate] USER_UPDATE[UserUpdate] USER_DB[UserDB] end subgraph DATABASE[Database adapters] direction RL SQLALCHEMY[SQLAlchemy] MONGODB[MongoDB] TORTOISE[Tortoise ORM] ORMAR[Ormar] end subgraph ROUTERS[Routers] direction RL AUTH[[get_auth_router]] OAUTH[[get_oauth_router]] REGISTER[[get_register_router]] VERIFY[[get_verify_router]] RESET[[get_reset_password_router]] USERS[[get_users_router]] end subgraph AUTH_BACKENDS[Authentication] direction RL subgraph TRANSPORTS[Transports] direction RL COOKIE[CookieTransport] BEARER[BearerTransport] end subgraph STRATEGIES[Strategies] direction RL JWT[JWTStrategy] end AUTH_BACKEND{AuthenticationBackend} end DATABASE --> DATABASE_DEPENDENCY DATABASE_DEPENDENCY --> USER_MANAGER MODELS --> USER_MANAGER MODELS --> FASTAPI_USERS USER_MANAGER --> USER_MANAGER_DEPENDENCY USER_MANAGER_DEPENDENCY --> FASTAPI_USERS FASTAPI_USERS --> ROUTERS TRANSPORTS --> AUTH_BACKEND STRATEGIES --> AUTH_BACKEND AUTH_BACKEND --> AUTH AUTH_BACKEND --> OAUTH AUTH_BACKEND --> FASTAPI_USERS FASTAPI_USERS --> CURRENT_USER","title":"Overview"},{"location":"configuration/overview/#models","text":"Pydantic models representing the data structure of a user. Base classes are provided with the required fields to make authentication work. You should sub-class each of them and add your own fields there. \u27a1\ufe0f Configure the models","title":"Models"},{"location":"configuration/overview/#database-adapters","text":"FastAPI Users is compatible with various databases and ORM. To build the interface between those database tools and the library, we provide database adapters classes that you need to instantiate and configure. \u27a1\ufe0f I'm using SQLAlchemy \u27a1\ufe0f I'm using MongoDB \u27a1\ufe0f I'm using Tortoise ORM \u27a1\ufe0f I'm using ormar","title":"Database adapters"},{"location":"configuration/overview/#authentication-backends","text":"Authentication backends define the way users sessions are managed in your app, like access tokens or cookies. They are composed of two parts: a transport , which is how the token will be carried over the requests (e.g. cookies, headers...) and a strategy , which is how the token will be generated and secured (e.g. a JWT, a token in database...). \u27a1\ufe0f Configure the authentication backends","title":"Authentication backends"},{"location":"configuration/overview/#usermanager","text":"The UserManager object bears most of the logic of FastAPI Users: registration, verification, password reset... We provide a BaseUserManager with this common logic; which you should overload to define how to validate passwords or handle events. This UserManager object should be provided through a FastAPI dependency, get_user_manager . \u27a1\ufe0f Configure UserManager","title":"UserManager"},{"location":"configuration/overview/#fastapiusers-and-routers","text":"Finally, FastAPIUsers object is the main class from which you'll be able to generate routers for classic routes like registration or login, but also get the current_user dependency factory to inject the authenticated user in your own routes. \u27a1\ufe0f Configure FastAPIUsers and routers","title":"FastAPIUsers and routers"},{"location":"configuration/user-manager/","text":"UserManager \u00b6 The UserManager class is the core logic of FastAPI Users. We provide the BaseUserManager class which you should extend to set some parameters and define logic, for example when a user just registered or forgot its password. It's designed to be easily extensible and customizable so that you can integrate less generic logic. Create your UserManager class \u00b6 You should define your own version of the UserManager class to set various parameters. from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager from .db import get_user_db from .models import UserCreate , UserDB SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db = Depends ( get_user_db )): yield UserManager ( user_db ) As you can see, you have to define here various attributes and methods. You can find the complete list of those below. Create get_user_manager dependency \u00b6 The UserManager class will be injected at runtime using a FastAPI dependency. This way, you can run it in a database session or swap it with a mock during testing. from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager from .db import get_user_db from .models import UserCreate , UserDB SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db = Depends ( get_user_db )): yield UserManager ( user_db ) Notice that we use the get_user_db dependency we defined earlier to inject the database instance. Customize attributes and methods \u00b6 Attributes \u00b6 user_db_model : Pydantic model of a DB representation of a user. reset_password_token_secret : Secret to encode reset password token. Use a strong passphrase and keep it secure. reset_password_token_lifetime_seconds : Lifetime of reset password token. Defaults to 3600. reset_password_token_audience : JWT audience of reset password token. Defaults to fastapi-users:reset . verification_token_secret : Secret to encode verification token. Use a strong passphrase and keep it secure. verification_token_lifetime_seconds : Lifetime of verification token. Defaults to 3600. verification_token_audience : JWT audience of verification token. Defaults to fastapi-users:verify . Methods \u00b6 validate_password \u00b6 Validate a password. Arguments password ( str ): the password to validate. user ( Union[UserCreate, User] ): user model which we are currently validating the password. Useful if you want to check that the password doesn't contain the name or the birthdate of the user for example. Output This function should return None if the password is valid or raise InvalidPasswordException if not. This exception expects an argument reason telling why the password is invalid. It'll be part of the error response. Example from fastapi_users import BaseUserManager , InvalidPasswordException class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def validate_password ( self , password : str , user : Union [ UserCreate , UserDB ], ) -> None : if len ( password ) < 8 : raise InvalidPasswordException ( reason = \"Password should be at least 8 characters\" ) if user . email in password : raise InvalidPasswordException ( reason = \"Password should not contain e-mail\" ) on_after_register \u00b6 Perform logic after successful user registration. Typically, you'll want to send a welcome e-mail or add it to your marketing analytics pipeline. Arguments user ( UserDB ): the registered user. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) on_after_update \u00b6 Perform logic after successful user update. It may be useful, for example, if you wish to update your user in a data analytics or customer success platform. Arguments user ( UserDB ): the updated user. update_dict ( Dict[str, Any] ): dictionary with the updated user fields. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_update ( self , user : UserDB , update_dict : Dict [ str , Any ], request : Optional [ Request ] = None , ): print ( f \"User { user . id } has been updated with { update_dict } .\" ) on_after_request_verify \u00b6 Perform logic after successful verification request. Typically, you'll want to send an e-mail with the link (and the token) that allows the user to verify their e-mail. Arguments user ( UserDB ): the user to verify. token ( str ): the verification token. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) on_after_verify \u00b6 Perform logic after successful user verification. This may be useful if you wish to send another e-mail or store this information in a data analytics or customer success platform. Arguments user ( UserDB ): the verified user. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_verify ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has been verified\" ) on_after_forgot_password \u00b6 Perform logic after successful forgot password request. Typically, you'll want to send an e-mail with the link (and the token) that allows the user to reset their password. Arguments user ( UserDB ): the user that forgot its password. token ( str ): the forgot password token request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) on_after_reset_password \u00b6 Perform logic after successful password reset. For example, you may want to send an e-mail to the concerned user to warn him that their password has been changed and that they should take action if they think they have been hacked. Arguments user ( UserDB ): the user that reset its password. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_reset_password ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has reset their password.\" )","title":"UserManager"},{"location":"configuration/user-manager/#usermanager","text":"The UserManager class is the core logic of FastAPI Users. We provide the BaseUserManager class which you should extend to set some parameters and define logic, for example when a user just registered or forgot its password. It's designed to be easily extensible and customizable so that you can integrate less generic logic.","title":"UserManager"},{"location":"configuration/user-manager/#create-your-usermanager-class","text":"You should define your own version of the UserManager class to set various parameters. from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager from .db import get_user_db from .models import UserCreate , UserDB SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db = Depends ( get_user_db )): yield UserManager ( user_db ) As you can see, you have to define here various attributes and methods. You can find the complete list of those below.","title":"Create your UserManager class"},{"location":"configuration/user-manager/#create-get_user_manager-dependency","text":"The UserManager class will be injected at runtime using a FastAPI dependency. This way, you can run it in a database session or swap it with a mock during testing. from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager from .db import get_user_db from .models import UserCreate , UserDB SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db = Depends ( get_user_db )): yield UserManager ( user_db ) Notice that we use the get_user_db dependency we defined earlier to inject the database instance.","title":"Create get_user_manager dependency"},{"location":"configuration/user-manager/#customize-attributes-and-methods","text":"","title":"Customize attributes and methods"},{"location":"configuration/user-manager/#attributes","text":"user_db_model : Pydantic model of a DB representation of a user. reset_password_token_secret : Secret to encode reset password token. Use a strong passphrase and keep it secure. reset_password_token_lifetime_seconds : Lifetime of reset password token. Defaults to 3600. reset_password_token_audience : JWT audience of reset password token. Defaults to fastapi-users:reset . verification_token_secret : Secret to encode verification token. Use a strong passphrase and keep it secure. verification_token_lifetime_seconds : Lifetime of verification token. Defaults to 3600. verification_token_audience : JWT audience of verification token. Defaults to fastapi-users:verify .","title":"Attributes"},{"location":"configuration/user-manager/#methods","text":"","title":"Methods"},{"location":"configuration/user-manager/#validate_password","text":"Validate a password. Arguments password ( str ): the password to validate. user ( Union[UserCreate, User] ): user model which we are currently validating the password. Useful if you want to check that the password doesn't contain the name or the birthdate of the user for example. Output This function should return None if the password is valid or raise InvalidPasswordException if not. This exception expects an argument reason telling why the password is invalid. It'll be part of the error response. Example from fastapi_users import BaseUserManager , InvalidPasswordException class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def validate_password ( self , password : str , user : Union [ UserCreate , UserDB ], ) -> None : if len ( password ) < 8 : raise InvalidPasswordException ( reason = \"Password should be at least 8 characters\" ) if user . email in password : raise InvalidPasswordException ( reason = \"Password should not contain e-mail\" )","title":"validate_password"},{"location":"configuration/user-manager/#on_after_register","text":"Perform logic after successful user registration. Typically, you'll want to send a welcome e-mail or add it to your marketing analytics pipeline. Arguments user ( UserDB ): the registered user. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" )","title":"on_after_register"},{"location":"configuration/user-manager/#on_after_update","text":"Perform logic after successful user update. It may be useful, for example, if you wish to update your user in a data analytics or customer success platform. Arguments user ( UserDB ): the updated user. update_dict ( Dict[str, Any] ): dictionary with the updated user fields. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_update ( self , user : UserDB , update_dict : Dict [ str , Any ], request : Optional [ Request ] = None , ): print ( f \"User { user . id } has been updated with { update_dict } .\" )","title":"on_after_update"},{"location":"configuration/user-manager/#on_after_request_verify","text":"Perform logic after successful verification request. Typically, you'll want to send an e-mail with the link (and the token) that allows the user to verify their e-mail. Arguments user ( UserDB ): the user to verify. token ( str ): the verification token. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" )","title":"on_after_request_verify"},{"location":"configuration/user-manager/#on_after_verify","text":"Perform logic after successful user verification. This may be useful if you wish to send another e-mail or store this information in a data analytics or customer success platform. Arguments user ( UserDB ): the verified user. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_verify ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has been verified\" )","title":"on_after_verify"},{"location":"configuration/user-manager/#on_after_forgot_password","text":"Perform logic after successful forgot password request. Typically, you'll want to send an e-mail with the link (and the token) that allows the user to reset their password. Arguments user ( UserDB ): the user that forgot its password. token ( str ): the forgot password token request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" )","title":"on_after_forgot_password"},{"location":"configuration/user-manager/#on_after_reset_password","text":"Perform logic after successful password reset. For example, you may want to send an e-mail to the concerned user to warn him that their password has been changed and that they should take action if they think they have been hacked. Arguments user ( UserDB ): the user that reset its password. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_reset_password ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has reset their password.\" )","title":"on_after_reset_password"},{"location":"configuration/authentication/","text":"Authentication \u00b6 FastAPI Users allows you to plug in several authentication methods. How it works? \u00b6 You can have several authentication methods, e.g. a cookie authentication for browser-based queries and a JWT token authentication for pure API queries. When checking authentication, each method is run one after the other. The first method yielding a user wins. If no method yields a user, an HTTPException is raised. For each backend, you'll be able to add a router with the corresponding /login and /logout . More on this in the routers documentation . Transport + Strategy = Authentication backend \u00b6 An authentication backend is composed of two parts: Transport \u00b6 It manages how the token will be carried over the request. We currently provide two methods: Bearer \u00b6 The token will be send through an Authorization: Bearer header. Pros and cons \u2705 Easy to read and set in every requests. \u274c Needs to be stored manually somewhere in the client. \u27a1\ufe0f Use it if you want to implement a mobile application or a pure REST API. Cookie \u00b6 The token will be send through a cookie. Pros and cons \u2705 Automatically stored and sent securely by web browsers in every requests. \u2705 Automatically removed at expiration by web browsers. \u274c Needs a CSRF protection for maximum security. \u274c Harder to work with outside a browser, like a mobile app or a server. \u27a1\ufe0f Use it if you want to implement a web frontend. Strategy \u00b6 It manages how the token is generated and secured. We currently provide two methods: JWT \u00b6 The token is self-contained in a JSON Web Token. Pros and cons \u2705 Self-contained: it doesn't need to be stored in a database. \u274c Can't be invalidated on the server-side: it's valid until it expires. \u27a1\ufe0f Use it if you want to get up-and-running quickly. Database \u00b6 The token is stored in a table (or collection) in your database. Pros and cons \u2705 Secure and performant. \u2705 Tokens can be invalidated server-side by removing them from the database. \u2705 Highly customizable: add your own fields, create an API to retrieve the active sessions of your users, etc. \u274c Configuration is a bit more complex. \u27a1\ufe0f Use it if you want maximum flexibility in your token management. Redis \u00b6 The token is stored in a Redis key-store. Pros and cons \u2705 Secure and performant. \u2705 Tokens can be invalidated server-side by removing them from Redis. \u274c A Redis server is needed. \u27a1\ufe0f Use it if you want maximum performance while being able to invalidate tokens.","title":"Introduction"},{"location":"configuration/authentication/#authentication","text":"FastAPI Users allows you to plug in several authentication methods.","title":"Authentication"},{"location":"configuration/authentication/#how-it-works","text":"You can have several authentication methods, e.g. a cookie authentication for browser-based queries and a JWT token authentication for pure API queries. When checking authentication, each method is run one after the other. The first method yielding a user wins. If no method yields a user, an HTTPException is raised. For each backend, you'll be able to add a router with the corresponding /login and /logout . More on this in the routers documentation .","title":"How it works?"},{"location":"configuration/authentication/#transport-strategy-authentication-backend","text":"An authentication backend is composed of two parts:","title":"Transport + Strategy = Authentication backend"},{"location":"configuration/authentication/#transport","text":"It manages how the token will be carried over the request. We currently provide two methods:","title":"Transport"},{"location":"configuration/authentication/#bearer","text":"The token will be send through an Authorization: Bearer header. Pros and cons \u2705 Easy to read and set in every requests. \u274c Needs to be stored manually somewhere in the client. \u27a1\ufe0f Use it if you want to implement a mobile application or a pure REST API.","title":"Bearer"},{"location":"configuration/authentication/#cookie","text":"The token will be send through a cookie. Pros and cons \u2705 Automatically stored and sent securely by web browsers in every requests. \u2705 Automatically removed at expiration by web browsers. \u274c Needs a CSRF protection for maximum security. \u274c Harder to work with outside a browser, like a mobile app or a server. \u27a1\ufe0f Use it if you want to implement a web frontend.","title":"Cookie"},{"location":"configuration/authentication/#strategy","text":"It manages how the token is generated and secured. We currently provide two methods:","title":"Strategy"},{"location":"configuration/authentication/#jwt","text":"The token is self-contained in a JSON Web Token. Pros and cons \u2705 Self-contained: it doesn't need to be stored in a database. \u274c Can't be invalidated on the server-side: it's valid until it expires. \u27a1\ufe0f Use it if you want to get up-and-running quickly.","title":"JWT"},{"location":"configuration/authentication/#database","text":"The token is stored in a table (or collection) in your database. Pros and cons \u2705 Secure and performant. \u2705 Tokens can be invalidated server-side by removing them from the database. \u2705 Highly customizable: add your own fields, create an API to retrieve the active sessions of your users, etc. \u274c Configuration is a bit more complex. \u27a1\ufe0f Use it if you want maximum flexibility in your token management.","title":"Database"},{"location":"configuration/authentication/#redis","text":"The token is stored in a Redis key-store. Pros and cons \u2705 Secure and performant. \u2705 Tokens can be invalidated server-side by removing them from Redis. \u274c A Redis server is needed. \u27a1\ufe0f Use it if you want maximum performance while being able to invalidate tokens.","title":"Redis"},{"location":"configuration/authentication/backend/","text":"Create a backend \u00b6 As we said, a backend is the combination of a transport and a strategy. That way, you can create a complete strategy exactly fitting your needs. For this, you have to use the AuthenticationBackend class. from fastapi_users.authentication import AuthenticationBackend , BearerTransport , JWTStrategy SECRET = \"SECRET\" bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) As you can see, instantiation is quite simple. It accepts the following arguments: name ( str ): Name of the backend. Each backend should have a unique name. transport ( Transport ): An instance of a Transport class. get_strategy ( Callable[..., Strategy] ): A dependency callable returning an instance of a Strategy class. Next steps \u00b6 You can have as many authentication backends as you wish. You'll then have to pass those backends to your FastAPIUsers instance and generate an auth router for each one of them.","title":"Create a backend"},{"location":"configuration/authentication/backend/#create-a-backend","text":"As we said, a backend is the combination of a transport and a strategy. That way, you can create a complete strategy exactly fitting your needs. For this, you have to use the AuthenticationBackend class. from fastapi_users.authentication import AuthenticationBackend , BearerTransport , JWTStrategy SECRET = \"SECRET\" bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) As you can see, instantiation is quite simple. It accepts the following arguments: name ( str ): Name of the backend. Each backend should have a unique name. transport ( Transport ): An instance of a Transport class. get_strategy ( Callable[..., Strategy] ): A dependency callable returning an instance of a Strategy class.","title":"Create a backend"},{"location":"configuration/authentication/backend/#next-steps","text":"You can have as many authentication backends as you wish. You'll then have to pass those backends to your FastAPIUsers instance and generate an auth router for each one of them.","title":"Next steps"},{"location":"configuration/authentication/strategies/database/","text":"Database \u00b6 The most natural way for storing tokens is of course the very same database you're using for your application. In this strategy, we set up a table (or collection) for storing those tokens with the associated user id. On each request, we try to retrive this token from the database to get the corresponding user id. Configuration \u00b6 The configuration of this strategy is a bit more complex than the others as it requires you to configure models and a database adapter, exactly like we did for users . Model \u00b6 You should define an AccessToken Pydantic model inheriting from BaseAccessToken . from fastapi_users.authentication.strategy.db import BaseAccessToken class AccessToken ( BaseAccessToken ): pass It is structured like this: token ( str ) \u2013 Unique identifier of the token. It's generated automatically upon login by the strategy. user_id ( UUID4 ) \u2013 User id. of the user associated to this token. created_at ( datetime ) \u2013 Date and time of creation of the token. It's used to determine if the token is expired or not. Database adapter \u00b6 SQLAlchemy Tortoise ORM MongoDB from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from fastapi_users_db_sqlalchemy.access_token import ( SQLAlchemyAccessTokenDatabase , SQLAlchemyBaseAccessTokenTable , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import AccessToken , UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass class AccessTokenTable ( SQLAlchemyBaseAccessTokenTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) async def get_access_token_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyAccessTokenDatabase ( AccessToken , session , AccessTokenTable ) With Tortoise ORM, you need to define a proper Tortoise model for AccessToken and manually specify the user foreign key. Besides, you need to modify the Pydantic model a bit so that it works well with this Tortoise model. model.py adapter.py from fastapi_users import models from fastapi_users.authentication.strategy.db.models import BaseAccessToken from fastapi_users.db import TortoiseBaseUserModel from fastapi_users_db_tortoise.access_token import TortoiseBaseAccessTokenModel from tortoise import fields from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel class AccessTokenModel ( TortoiseBaseAccessTokenModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"access_tokens\" ) class AccessToken ( BaseAccessToken , PydanticModel ): class Config : orm_mode = True orig_model = AccessTokenModel from fastapi_users.db import TortoiseUserDatabase from fastapi_users_db_tortoise.access_token import TortoiseAccessTokenDatabase from .models import AccessToken , AccessTokenModel , UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel ) async def get_access_token_db (): yield TortoiseAccessTokenDatabase ( AccessToken , AccessTokenModel ) import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from fastapi_users_db_mongodb.access_token import MongoDBAccessTokenDatabase from .models import AccessToken , UserDB DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] users_collection = db [ \"users\" ] access_tokens_collection = db [ \"access_tokens\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , users_collection ) async def get_access_token_db (): yield MongoDBAccessTokenDatabase ( AccessToken , access_tokens_collection ) Strategy \u00b6 from fastapi import Depends from fastapi_users.authentication.db import AccessTokenDatabase , DatabaseStrategy from .models import AccessToken , UserCreate , UserDB def get_database_strategy ( access_token_db : AccessTokenDatabase [ AccessToken ] = Depends ( get_access_token_db ), ) -> DatabaseStrategy [ UserCreate , UserDB , AccessToken ]: return DatabaseStrategy ( access_token_db , lifetime_seconds = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: database ( AccessTokenDatabase ): A database adapter instance for AccessToken table, like we defined above. lifetime_seconds ( int ): The lifetime of the token in seconds. Why it's inside a function? To allow strategies to be instantiated dynamically with other dependencies, they have to be provided as a callable to the authentication backend. As you can see here, this pattern allows us to dynamically inject a connection to the database. Logout \u00b6 On logout, this strategy will delete the token from the database.","title":"Database"},{"location":"configuration/authentication/strategies/database/#database","text":"The most natural way for storing tokens is of course the very same database you're using for your application. In this strategy, we set up a table (or collection) for storing those tokens with the associated user id. On each request, we try to retrive this token from the database to get the corresponding user id.","title":"Database"},{"location":"configuration/authentication/strategies/database/#configuration","text":"The configuration of this strategy is a bit more complex than the others as it requires you to configure models and a database adapter, exactly like we did for users .","title":"Configuration"},{"location":"configuration/authentication/strategies/database/#model","text":"You should define an AccessToken Pydantic model inheriting from BaseAccessToken . from fastapi_users.authentication.strategy.db import BaseAccessToken class AccessToken ( BaseAccessToken ): pass It is structured like this: token ( str ) \u2013 Unique identifier of the token. It's generated automatically upon login by the strategy. user_id ( UUID4 ) \u2013 User id. of the user associated to this token. created_at ( datetime ) \u2013 Date and time of creation of the token. It's used to determine if the token is expired or not.","title":"Model"},{"location":"configuration/authentication/strategies/database/#database-adapter","text":"SQLAlchemy Tortoise ORM MongoDB from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from fastapi_users_db_sqlalchemy.access_token import ( SQLAlchemyAccessTokenDatabase , SQLAlchemyBaseAccessTokenTable , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import AccessToken , UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass class AccessTokenTable ( SQLAlchemyBaseAccessTokenTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) async def get_access_token_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyAccessTokenDatabase ( AccessToken , session , AccessTokenTable ) With Tortoise ORM, you need to define a proper Tortoise model for AccessToken and manually specify the user foreign key. Besides, you need to modify the Pydantic model a bit so that it works well with this Tortoise model. model.py adapter.py from fastapi_users import models from fastapi_users.authentication.strategy.db.models import BaseAccessToken from fastapi_users.db import TortoiseBaseUserModel from fastapi_users_db_tortoise.access_token import TortoiseBaseAccessTokenModel from tortoise import fields from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel class AccessTokenModel ( TortoiseBaseAccessTokenModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"access_tokens\" ) class AccessToken ( BaseAccessToken , PydanticModel ): class Config : orm_mode = True orig_model = AccessTokenModel from fastapi_users.db import TortoiseUserDatabase from fastapi_users_db_tortoise.access_token import TortoiseAccessTokenDatabase from .models import AccessToken , AccessTokenModel , UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel ) async def get_access_token_db (): yield TortoiseAccessTokenDatabase ( AccessToken , AccessTokenModel ) import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from fastapi_users_db_mongodb.access_token import MongoDBAccessTokenDatabase from .models import AccessToken , UserDB DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] users_collection = db [ \"users\" ] access_tokens_collection = db [ \"access_tokens\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , users_collection ) async def get_access_token_db (): yield MongoDBAccessTokenDatabase ( AccessToken , access_tokens_collection )","title":"Database adapter"},{"location":"configuration/authentication/strategies/database/#strategy","text":"from fastapi import Depends from fastapi_users.authentication.db import AccessTokenDatabase , DatabaseStrategy from .models import AccessToken , UserCreate , UserDB def get_database_strategy ( access_token_db : AccessTokenDatabase [ AccessToken ] = Depends ( get_access_token_db ), ) -> DatabaseStrategy [ UserCreate , UserDB , AccessToken ]: return DatabaseStrategy ( access_token_db , lifetime_seconds = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: database ( AccessTokenDatabase ): A database adapter instance for AccessToken table, like we defined above. lifetime_seconds ( int ): The lifetime of the token in seconds. Why it's inside a function? To allow strategies to be instantiated dynamically with other dependencies, they have to be provided as a callable to the authentication backend. As you can see here, this pattern allows us to dynamically inject a connection to the database.","title":"Strategy"},{"location":"configuration/authentication/strategies/database/#logout","text":"On logout, this strategy will delete the token from the database.","title":"Logout"},{"location":"configuration/authentication/strategies/jwt/","text":"JWT \u00b6 JSON Web Token (JWT) is an internet standard for creating access tokens based on JSON. They don't need to be stored in a database: the data is self-contained inside and cryptographically signed. Configuration \u00b6 from fastapi_users.authentication import JWTStrategy SECRET = \"SECRET\" def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: secret ( Union[str, pydantic.SecretStr] ): A constant secret which is used to encode the token. Use a strong passphrase and keep it secure. lifetime_seconds ( Optional[int] ): The lifetime of the token in seconds. Can be set to None but in this case the token will be valid forever ; which may raise serious security concerns. token_audience ( Optional[List[str]] ): A list of valid audiences for the JWT token. Defaults to [\"fastapi-users:auth\"] . Why it's inside a function? To allow strategies to be instantiated dynamically with other dependencies, they have to be provided as a callable to the authentication backend. For JWTStrategy , since it doesn't require dependencies, it can be as simple as the function above. Logout \u00b6 On logout, this strategy won't do anything . Indeed, a JWT can't be invalidated on the server-side: it's valid until it expires.","title":"JWT"},{"location":"configuration/authentication/strategies/jwt/#jwt","text":"JSON Web Token (JWT) is an internet standard for creating access tokens based on JSON. They don't need to be stored in a database: the data is self-contained inside and cryptographically signed.","title":"JWT"},{"location":"configuration/authentication/strategies/jwt/#configuration","text":"from fastapi_users.authentication import JWTStrategy SECRET = \"SECRET\" def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: secret ( Union[str, pydantic.SecretStr] ): A constant secret which is used to encode the token. Use a strong passphrase and keep it secure. lifetime_seconds ( Optional[int] ): The lifetime of the token in seconds. Can be set to None but in this case the token will be valid forever ; which may raise serious security concerns. token_audience ( Optional[List[str]] ): A list of valid audiences for the JWT token. Defaults to [\"fastapi-users:auth\"] . Why it's inside a function? To allow strategies to be instantiated dynamically with other dependencies, they have to be provided as a callable to the authentication backend. For JWTStrategy , since it doesn't require dependencies, it can be as simple as the function above.","title":"Configuration"},{"location":"configuration/authentication/strategies/jwt/#logout","text":"On logout, this strategy won't do anything . Indeed, a JWT can't be invalidated on the server-side: it's valid until it expires.","title":"Logout"},{"location":"configuration/authentication/strategies/redis/","text":"Redis \u00b6 Redis is an ultra-fast key-store database. As such, it's a good candidate for token management. In this strategy, a token is generated and associated with the user id. in the database. On each request, we try to retrieve this token from Redis to get the corresponding user id. Configuration \u00b6 import aioredis from fastapi_users.authentication import RedisStrategy redis = aioredis . from_url ( \"redis://localhost:6379\" , decode_responses = True ) def get_redis_strategy () -> RedisStrategy : return RedisStrategy ( redis , lifetime_seconds = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: redis ( aioredis.Redis ): An instance of aioredis.Redis . Note that the decode_responses flag set to True is necessary. lifetime_seconds ( Optional[int] ): The lifetime of the token in seconds. Defaults to None , which means the token doesn't expire. Why it's inside a function? To allow strategies to be instantiated dynamically with other dependencies, they have to be provided as a callable to the authentication backend. Logout \u00b6 On logout, this strategy will delete the token from the Redis store.","title":"Redis"},{"location":"configuration/authentication/strategies/redis/#redis","text":"Redis is an ultra-fast key-store database. As such, it's a good candidate for token management. In this strategy, a token is generated and associated with the user id. in the database. On each request, we try to retrieve this token from Redis to get the corresponding user id.","title":"Redis"},{"location":"configuration/authentication/strategies/redis/#configuration","text":"import aioredis from fastapi_users.authentication import RedisStrategy redis = aioredis . from_url ( \"redis://localhost:6379\" , decode_responses = True ) def get_redis_strategy () -> RedisStrategy : return RedisStrategy ( redis , lifetime_seconds = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: redis ( aioredis.Redis ): An instance of aioredis.Redis . Note that the decode_responses flag set to True is necessary. lifetime_seconds ( Optional[int] ): The lifetime of the token in seconds. Defaults to None , which means the token doesn't expire. Why it's inside a function? To allow strategies to be instantiated dynamically with other dependencies, they have to be provided as a callable to the authentication backend.","title":"Configuration"},{"location":"configuration/authentication/strategies/redis/#logout","text":"On logout, this strategy will delete the token from the Redis store.","title":"Logout"},{"location":"configuration/authentication/transports/bearer/","text":"Bearer \u00b6 With this transport, the token is expected inside the Authorization header of the HTTP request with the Bearer scheme. It's particularly suited for pure API interaction or mobile apps. Configuration \u00b6 from fastapi_users.authentication import BearerTransport bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) As you can see, instantiation is quite simple. It accepts the following arguments: tokenUrl ( str ): The exact path of your login endpoint. It'll allow the interactive documentation to automatically discover it and get a working Authorize button. In most cases, you'll probably need a relative path, not absolute. You can read more details about this in the FastAPI documentation . Login \u00b6 This method will return the in the following form upon successful login: 200 OK { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"token_type\" : \"bearer\" } Check documentation about login route . Logout \u00b6 The logout method with this transport returns nothing. Authentication \u00b6 This method expects that you provide a Bearer authentication with a valid token corresponding to your strategy. curl http://localhost:9000/protected-route -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI'","title":"Bearer"},{"location":"configuration/authentication/transports/bearer/#bearer","text":"With this transport, the token is expected inside the Authorization header of the HTTP request with the Bearer scheme. It's particularly suited for pure API interaction or mobile apps.","title":"Bearer"},{"location":"configuration/authentication/transports/bearer/#configuration","text":"from fastapi_users.authentication import BearerTransport bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) As you can see, instantiation is quite simple. It accepts the following arguments: tokenUrl ( str ): The exact path of your login endpoint. It'll allow the interactive documentation to automatically discover it and get a working Authorize button. In most cases, you'll probably need a relative path, not absolute. You can read more details about this in the FastAPI documentation .","title":"Configuration"},{"location":"configuration/authentication/transports/bearer/#login","text":"This method will return the in the following form upon successful login: 200 OK { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"token_type\" : \"bearer\" } Check documentation about login route .","title":"Login"},{"location":"configuration/authentication/transports/bearer/#logout","text":"The logout method with this transport returns nothing.","title":"Logout"},{"location":"configuration/authentication/transports/bearer/#authentication","text":"This method expects that you provide a Bearer authentication with a valid token corresponding to your strategy. curl http://localhost:9000/protected-route -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI'","title":"Authentication"},{"location":"configuration/authentication/transports/cookie/","text":"Cookie \u00b6 Cookies are an easy way to store stateful information into the user browser. Thus, it is more useful for browser-based navigation (e.g. a front-end app making API requests) rather than pure API interaction. Configuration \u00b6 from fastapi_users.authentication import CookieTransport cookie_transport = CookieTransport ( cookie_max_age = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: cookie_name ( fastapiusersauth ): Name of the cookie. cookie_max_age ( Optional[int] ): The lifetime of the cookie in seconds. None by default, which means it's a session cookie. cookie_path ( / ): Cookie path. cookie_domain ( None ): Cookie domain. cookie_secure ( True ): Whether to only send the cookie to the server via SSL request. cookie_httponly ( True ): Whether to prevent access to the cookie via JavaScript. cookie_samesite ( lax ): A string that specifies the samesite strategy for the cookie. Valid values are lax , strict and none . Defaults to lax . Login \u00b6 This method will return a response with a valid set-cookie header upon successful login: 200 OK Check documentation about login route . Logout \u00b6 This method will remove the authentication cookie: 200 OK Check documentation about logout route . Authentication \u00b6 This method expects that you provide a valid cookie in the headers.","title":"Cookie"},{"location":"configuration/authentication/transports/cookie/#cookie","text":"Cookies are an easy way to store stateful information into the user browser. Thus, it is more useful for browser-based navigation (e.g. a front-end app making API requests) rather than pure API interaction.","title":"Cookie"},{"location":"configuration/authentication/transports/cookie/#configuration","text":"from fastapi_users.authentication import CookieTransport cookie_transport = CookieTransport ( cookie_max_age = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: cookie_name ( fastapiusersauth ): Name of the cookie. cookie_max_age ( Optional[int] ): The lifetime of the cookie in seconds. None by default, which means it's a session cookie. cookie_path ( / ): Cookie path. cookie_domain ( None ): Cookie domain. cookie_secure ( True ): Whether to only send the cookie to the server via SSL request. cookie_httponly ( True ): Whether to prevent access to the cookie via JavaScript. cookie_samesite ( lax ): A string that specifies the samesite strategy for the cookie. Valid values are lax , strict and none . Defaults to lax .","title":"Configuration"},{"location":"configuration/authentication/transports/cookie/#login","text":"This method will return a response with a valid set-cookie header upon successful login: 200 OK Check documentation about login route .","title":"Login"},{"location":"configuration/authentication/transports/cookie/#logout","text":"This method will remove the authentication cookie: 200 OK Check documentation about logout route .","title":"Logout"},{"location":"configuration/authentication/transports/cookie/#authentication","text":"This method expects that you provide a valid cookie in the headers.","title":"Authentication"},{"location":"configuration/databases/mongodb/","text":"MongoDB \u00b6 FastAPI Users provides the necessary tools to work with MongoDB databases thanks to mongodb/motor package for full async support. Setup database connection and collection \u00b6 Let's create a MongoDB connection and instantiate a collection. import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from .models import UserDB DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) You can choose any name for the database and the collection. Warning You may have noticed the uuidRepresentation parameter. It controls how the UUID values will be encoded in the database. By default, it's set to pythonLegacy but new applications should consider setting this to standard for cross language compatibility. Read more about this . Create the database adapter \u00b6 The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from .models import UserDB DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) Notice that we pass a reference to your UserDB model . Info The database adapter will automatically create a unique index on id and email . Warning FastAPI Users will use its defined id UUID as unique identifier for the user, rather than the builtin MongoDB _id .","title":"MongoDB"},{"location":"configuration/databases/mongodb/#mongodb","text":"FastAPI Users provides the necessary tools to work with MongoDB databases thanks to mongodb/motor package for full async support.","title":"MongoDB"},{"location":"configuration/databases/mongodb/#setup-database-connection-and-collection","text":"Let's create a MongoDB connection and instantiate a collection. import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from .models import UserDB DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) You can choose any name for the database and the collection. Warning You may have noticed the uuidRepresentation parameter. It controls how the UUID values will be encoded in the database. By default, it's set to pythonLegacy but new applications should consider setting this to standard for cross language compatibility. Read more about this .","title":"Setup database connection and collection"},{"location":"configuration/databases/mongodb/#create-the-database-adapter","text":"The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from .models import UserDB DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) Notice that we pass a reference to your UserDB model . Info The database adapter will automatically create a unique index on id and email . Warning FastAPI Users will use its defined id UUID as unique identifier for the user, rather than the builtin MongoDB _id .","title":"Create the database adapter"},{"location":"configuration/databases/ormar/","text":"Ormar \u00b6 FastAPI Users provides the necessary tools to work with ormar. Installation \u00b6 Install the database driver that corresponds to your DBMS: pip install asyncpg psycopg2 pip install aiomysql pymysql pip install aiosqlite For the sake of this tutorial from now on, we'll use a simple SQLite database. Setup User table \u00b6 Let's declare our User ORM model. import databases import sqlalchemy from fastapi_users.db import OrmarBaseUserModel , OrmarUserDatabase from .models import UserDB DATABASE_URL = \"sqlite:///test.db\" metadata = sqlalchemy . MetaData () database = databases . Database ( DATABASE_URL ) class UserModel ( OrmarBaseUserModel ): class Meta : tablename = \"users\" metadata = metadata database = database engine = sqlalchemy . create_engine ( DATABASE_URL ) metadata . create_all ( engine ) async def get_user_db (): yield OrmarUserDatabase ( UserDB , UserModel ) As you can see, FastAPI Users provides an abstract model that will include base fields for our User table. You can of course add you own fields there to fit to your needs! Create the database adapter \u00b6 The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. import databases import sqlalchemy from fastapi_users.db import OrmarBaseUserModel , OrmarUserDatabase from .models import UserDB DATABASE_URL = \"sqlite:///test.db\" metadata = sqlalchemy . MetaData () database = databases . Database ( DATABASE_URL ) class UserModel ( OrmarBaseUserModel ): class Meta : tablename = \"users\" metadata = metadata database = database engine = sqlalchemy . create_engine ( DATABASE_URL ) metadata . create_all ( engine ) async def get_user_db (): yield OrmarUserDatabase ( UserDB , UserModel ) Notice that we pass a reference to your UserDB model . Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See Alembic .","title":"Ormar"},{"location":"configuration/databases/ormar/#ormar","text":"FastAPI Users provides the necessary tools to work with ormar.","title":"Ormar"},{"location":"configuration/databases/ormar/#installation","text":"Install the database driver that corresponds to your DBMS: pip install asyncpg psycopg2 pip install aiomysql pymysql pip install aiosqlite For the sake of this tutorial from now on, we'll use a simple SQLite database.","title":"Installation"},{"location":"configuration/databases/ormar/#setup-user-table","text":"Let's declare our User ORM model. import databases import sqlalchemy from fastapi_users.db import OrmarBaseUserModel , OrmarUserDatabase from .models import UserDB DATABASE_URL = \"sqlite:///test.db\" metadata = sqlalchemy . MetaData () database = databases . Database ( DATABASE_URL ) class UserModel ( OrmarBaseUserModel ): class Meta : tablename = \"users\" metadata = metadata database = database engine = sqlalchemy . create_engine ( DATABASE_URL ) metadata . create_all ( engine ) async def get_user_db (): yield OrmarUserDatabase ( UserDB , UserModel ) As you can see, FastAPI Users provides an abstract model that will include base fields for our User table. You can of course add you own fields there to fit to your needs!","title":"Setup User table"},{"location":"configuration/databases/ormar/#create-the-database-adapter","text":"The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. import databases import sqlalchemy from fastapi_users.db import OrmarBaseUserModel , OrmarUserDatabase from .models import UserDB DATABASE_URL = \"sqlite:///test.db\" metadata = sqlalchemy . MetaData () database = databases . Database ( DATABASE_URL ) class UserModel ( OrmarBaseUserModel ): class Meta : tablename = \"users\" metadata = metadata database = database engine = sqlalchemy . create_engine ( DATABASE_URL ) metadata . create_all ( engine ) async def get_user_db (): yield OrmarUserDatabase ( UserDB , UserModel ) Notice that we pass a reference to your UserDB model . Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See Alembic .","title":"Create the database adapter"},{"location":"configuration/databases/sqlalchemy/","text":"SQLAlchemy \u00b6 FastAPI Users provides the necessary tools to work with SQL databases thanks to SQLAlchemy ORM with asyncio . Warning The previous adapter using encode/databases is now deprecated but can still be installed using fastapi-users[sqlalchemy] . Asynchronous driver \u00b6 To work with your DBMS, you'll need to install the corresponding asyncio driver. The common choices are: For PostgreSQL: pip install asyncpg For SQLite: pip install aiosqlite For the sake of this tutorial from now on, we'll use a simple SQLite databse. Setup User table \u00b6 Let's declare our SQLAlchemy User table. from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) As you can see, FastAPI Users provides a mixin that will include base fields for our User table. You can of course add you own fields there to fit to your needs! Implement a function to create the tables \u00b6 We'll now create an utility function to create all the defined tables. from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) This function can be called, for example, during the initialization of your FastAPI app. Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See Alembic . Create the database adapter dependency \u00b6 The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) Notice that we define first a get_async_session dependency returning us a fresh SQLAlchemy session to interact with the database. It's then used inside the get_user_db dependency to generate our adapter. Notice that we pass it three things: A reference to your UserDB model . The session instance we just injected. The UserTable variable, which is the actual SQLAlchemy model.","title":"SQLAlchemy"},{"location":"configuration/databases/sqlalchemy/#sqlalchemy","text":"FastAPI Users provides the necessary tools to work with SQL databases thanks to SQLAlchemy ORM with asyncio . Warning The previous adapter using encode/databases is now deprecated but can still be installed using fastapi-users[sqlalchemy] .","title":"SQLAlchemy"},{"location":"configuration/databases/sqlalchemy/#asynchronous-driver","text":"To work with your DBMS, you'll need to install the corresponding asyncio driver. The common choices are: For PostgreSQL: pip install asyncpg For SQLite: pip install aiosqlite For the sake of this tutorial from now on, we'll use a simple SQLite databse.","title":"Asynchronous driver"},{"location":"configuration/databases/sqlalchemy/#setup-user-table","text":"Let's declare our SQLAlchemy User table. from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) As you can see, FastAPI Users provides a mixin that will include base fields for our User table. You can of course add you own fields there to fit to your needs!","title":"Setup User table"},{"location":"configuration/databases/sqlalchemy/#implement-a-function-to-create-the-tables","text":"We'll now create an utility function to create all the defined tables. from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) This function can be called, for example, during the initialization of your FastAPI app. Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See Alembic .","title":"Implement a function to create the tables"},{"location":"configuration/databases/sqlalchemy/#create-the-database-adapter-dependency","text":"The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) Notice that we define first a get_async_session dependency returning us a fresh SQLAlchemy session to interact with the database. It's then used inside the get_user_db dependency to generate our adapter. Notice that we pass it three things: A reference to your UserDB model . The session instance we just injected. The UserTable variable, which is the actual SQLAlchemy model.","title":"Create the database adapter dependency"},{"location":"configuration/databases/tortoise/","text":"Tortoise ORM \u00b6 FastAPI Users provides the necessary tools to work with Tortoise ORM. Installation \u00b6 Install the database driver that corresponds to your DBMS: pip install asyncpg pip install aiomysql pip install aiosqlite For the sake of this tutorial from now on, we'll use a simple SQLite databse. Setup User table and model \u00b6 Let's declare our User ORM model. from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel As you can see, FastAPI Users provides an abstract model that will include base fields for our User table. You can of course add you own fields there to fit to your needs! In order to make the Pydantic model and the Tortoise ORM model working well together, you'll have to add a mixin and some configuration options to your UserDB model. Tortoise ORM provides utilities to ease the integration with Pydantic and we'll use them here. from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel The PydanticModel mixin adds methods used internally by Tortoise ORM to the Pydantic model so that it can easily transform it back to an ORM model. It expects then that you provide the property orig_model which should point to the User ORM model we defined just above . Create the database adapter \u00b6 The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. from fastapi_users.db import TortoiseUserDatabase from .models import UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel ) Notice that we pass a reference to your UserDB model . Register Tortoise \u00b6 For using Tortoise ORM we must register our models and database. Tortoise ORM supports integration with FastAPI out-of-the-box. It will automatically bind startup and shutdown events. from tortoise.contrib.fastapi import register_tortoise register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"models\" ]}, generate_schemas = True , ) Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See https://tortoise-orm.readthedocs.io/en/latest/migration.html .","title":"Tortoise ORM"},{"location":"configuration/databases/tortoise/#tortoise-orm","text":"FastAPI Users provides the necessary tools to work with Tortoise ORM.","title":"Tortoise ORM"},{"location":"configuration/databases/tortoise/#installation","text":"Install the database driver that corresponds to your DBMS: pip install asyncpg pip install aiomysql pip install aiosqlite For the sake of this tutorial from now on, we'll use a simple SQLite databse.","title":"Installation"},{"location":"configuration/databases/tortoise/#setup-user-table-and-model","text":"Let's declare our User ORM model. from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel As you can see, FastAPI Users provides an abstract model that will include base fields for our User table. You can of course add you own fields there to fit to your needs! In order to make the Pydantic model and the Tortoise ORM model working well together, you'll have to add a mixin and some configuration options to your UserDB model. Tortoise ORM provides utilities to ease the integration with Pydantic and we'll use them here. from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel The PydanticModel mixin adds methods used internally by Tortoise ORM to the Pydantic model so that it can easily transform it back to an ORM model. It expects then that you provide the property orig_model which should point to the User ORM model we defined just above .","title":"Setup User table and model"},{"location":"configuration/databases/tortoise/#create-the-database-adapter","text":"The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. from fastapi_users.db import TortoiseUserDatabase from .models import UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel ) Notice that we pass a reference to your UserDB model .","title":"Create the database adapter"},{"location":"configuration/databases/tortoise/#register-tortoise","text":"For using Tortoise ORM we must register our models and database. Tortoise ORM supports integration with FastAPI out-of-the-box. It will automatically bind startup and shutdown events. from tortoise.contrib.fastapi import register_tortoise register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"models\" ]}, generate_schemas = True , ) Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See https://tortoise-orm.readthedocs.io/en/latest/migration.html .","title":"Register Tortoise"},{"location":"configuration/routers/","text":"Routers \u00b6 We're almost there! The last step is to configure the FastAPIUsers object that will wire the user manager, the authentication classes and let us generate the actual API routes . Configure FastAPIUsers \u00b6 Configure FastAPIUsers object with all the elements we defined before. More precisely: get_user_manager : Dependency callable getter to inject the user manager class instance. See UserManager . auth_backends : List of authentication backends. See Authentication . user_model : Pydantic model of a user. user_create_model : Pydantic model for creating a user. user_update_model : Pydantic model for updating a user. user_db_model : Pydantic model of a DB representation of a user. from fastapi_users import FastAPIUsers fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) Available routers \u00b6 This helper class will let you generate useful routers to setup the authentication system. Each of them is optional , so you can pick only the one that you are interested in! Here are the routers provided: Auth router : Provides /login and /logout routes for a given authentication backend . Register router : Provides /register routes to allow a user to create a new account. Reset password router : Provides /forgot-password and /reset-password routes to allow a user to reset its password. Verify router : Provides /request-verify-token and /verify routes to manage user e-mail verification. Users router : Provides routes to manage users. OAuth router : Provides routes to perform an OAuth authentication against a service provider (like Google or Facebook). You should check out each of them to understand how to use them.","title":"Introduction"},{"location":"configuration/routers/#routers","text":"We're almost there! The last step is to configure the FastAPIUsers object that will wire the user manager, the authentication classes and let us generate the actual API routes .","title":"Routers"},{"location":"configuration/routers/#configure-fastapiusers","text":"Configure FastAPIUsers object with all the elements we defined before. More precisely: get_user_manager : Dependency callable getter to inject the user manager class instance. See UserManager . auth_backends : List of authentication backends. See Authentication . user_model : Pydantic model of a user. user_create_model : Pydantic model for creating a user. user_update_model : Pydantic model for updating a user. user_db_model : Pydantic model of a DB representation of a user. from fastapi_users import FastAPIUsers fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , )","title":"Configure FastAPIUsers"},{"location":"configuration/routers/#available-routers","text":"This helper class will let you generate useful routers to setup the authentication system. Each of them is optional , so you can pick only the one that you are interested in! Here are the routers provided: Auth router : Provides /login and /logout routes for a given authentication backend . Register router : Provides /register routes to allow a user to create a new account. Reset password router : Provides /forgot-password and /reset-password routes to allow a user to reset its password. Verify router : Provides /request-verify-token and /verify routes to manage user e-mail verification. Users router : Provides routes to manage users. OAuth router : Provides routes to perform an OAuth authentication against a service provider (like Google or Facebook). You should check out each of them to understand how to use them.","title":"Available routers"},{"location":"configuration/routers/auth/","text":"Auth router \u00b6 The auth router will generate /login and /logout routes for a given authentication backend . Check the routes usage to learn how to use them. Setup \u00b6 from fastapi import FastAPI from fastapi_users import FastAPIUsers fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ], ) Optional: user verification \u00b6 You can require the user to be verified (i.e. is_verified property set to True ) to allow login. You have to set the requires_verification parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_auth_router ( auth_backend , requires_verification = True ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ], )","title":"Auth router"},{"location":"configuration/routers/auth/#auth-router","text":"The auth router will generate /login and /logout routes for a given authentication backend . Check the routes usage to learn how to use them.","title":"Auth router"},{"location":"configuration/routers/auth/#setup","text":"from fastapi import FastAPI from fastapi_users import FastAPIUsers fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ], )","title":"Setup"},{"location":"configuration/routers/auth/#optional-user-verification","text":"You can require the user to be verified (i.e. is_verified property set to True ) to allow login. You have to set the requires_verification parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_auth_router ( auth_backend , requires_verification = True ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ], )","title":"Optional: user verification"},{"location":"configuration/routers/register/","text":"Register routes \u00b6 The register router will generate a /register route to allow a user to create a new account. Check the routes usage to learn how to use them. Setup \u00b6 from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Register routes"},{"location":"configuration/routers/register/#register-routes","text":"The register router will generate a /register route to allow a user to create a new account. Check the routes usage to learn how to use them.","title":"Register routes"},{"location":"configuration/routers/register/#setup","text":"from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Setup"},{"location":"configuration/routers/reset/","text":"Reset password router \u00b6 The reset password router will generate /forgot-password (the user asks for a token to reset its password) and /reset-password (the user changes its password given the token) routes. Check the routes usage to learn how to use them. Setup \u00b6 from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Reset password router"},{"location":"configuration/routers/reset/#reset-password-router","text":"The reset password router will generate /forgot-password (the user asks for a token to reset its password) and /reset-password (the user changes its password given the token) routes. Check the routes usage to learn how to use them.","title":"Reset password router"},{"location":"configuration/routers/reset/#setup","text":"from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Setup"},{"location":"configuration/routers/users/","text":"Users router \u00b6 This router provides routes to manage users. Check the routes usage to learn how to use them. Setup \u00b6 from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ], ) Optional: user verification \u00b6 You can require the user to be verified (i.e. is_verified property set to True ) to access those routes. You have to set the requires_verification parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_users_router ( requires_verification = True ), prefix = \"/users\" , tags = [ \"users\" ], )","title":"Users router"},{"location":"configuration/routers/users/#users-router","text":"This router provides routes to manage users. Check the routes usage to learn how to use them.","title":"Users router"},{"location":"configuration/routers/users/#setup","text":"from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ], )","title":"Setup"},{"location":"configuration/routers/users/#optional-user-verification","text":"You can require the user to be verified (i.e. is_verified property set to True ) to access those routes. You have to set the requires_verification parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_users_router ( requires_verification = True ), prefix = \"/users\" , tags = [ \"users\" ], )","title":"Optional: user verification"},{"location":"configuration/routers/verify/","text":"Verify router \u00b6 This router provides routes to manage user email verification. Check the routes usage to learn how to use them. \ud83d\udc4f\ud83d\udc4f\ud83d\udc4f A big thank you to Edd Salkield and Mark Todd who worked hard on this feature! Setup \u00b6 from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Verify router"},{"location":"configuration/routers/verify/#verify-router","text":"This router provides routes to manage user email verification. Check the routes usage to learn how to use them. \ud83d\udc4f\ud83d\udc4f\ud83d\udc4f A big thank you to Edd Salkield and Mark Todd who worked hard on this feature!","title":"Verify router"},{"location":"configuration/routers/verify/#setup","text":"from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Setup"},{"location":"cookbook/create-user-programmatically/","text":"Create a user programmatically \u00b6 Sometimes, you'll need to create a user programmatically in the code rather than passing by the REST API endpoint. To do this, we'll create a function that you can call from your code. In this context, we are outside the dependency injection mechanism of FastAPI, so we have to take care of instantiating the UserManager class and all other dependent objects manually . For this cookbook, we'll consider you are starting from the SQLAlchemy full example , but it'll be rather similar for other DBMS. 1. Define dependencies as context managers \u00b6 Generally, FastAPI dependencies are defined as generators , using the yield keyword. FastAPI knows very well to handle them inside its dependency injection system. For example, here is the definition of the get_user_manager dependency: async def get_user_manager ( user_db : SQLAlchemyUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) In Python, when we want to use a generator, we have to use a for loop, which would be a bit unnatural in this context since we have only one value to get, the user manager instance. To avoid this, we'll transform them into context managers , so we can call them using the with..as syntax. Fortunately, the standard library provides tools to automatically transform generators into context managers. In the following sample, we import our dependencies and create a context manager version using contextlib.asynccontextmanager : import contextlib from app.db import get_async_session , get_user_db from app.models import UserCreate from app.users import get_user_manager from fastapi_users.manager import UserAlreadyExists get_async_session_context = contextlib . asynccontextmanager ( get_async_session ) get_user_db_context = contextlib . asynccontextmanager ( get_user_db ) get_user_manager_context = contextlib . asynccontextmanager ( get_user_manager ) async def create_user ( email : str , password : str , is_superuser : bool = False ): try : async with get_async_session_context () as session : async with get_user_db_context ( session ) as user_db : async with get_user_manager_context ( user_db ) as user_manager : user = await user_manager . create ( UserCreate ( email = email , password = password , is_superuser = is_superuser ) ) print ( f \"User created { user } \" ) except UserAlreadyExists : print ( f \"User { email } already exists\" ) I have other dependencies Since FastAPI Users fully embraces dependency injection, you may have more arguments passed to your database or user manager dependencies. It's important then to not forget anyone. Once again, outside the dependency injection system, you are responsible of instantiating everything yourself. 2. Write a function \u00b6 We are now ready to write a function. The example below shows you a basic example but you can of course adapt it to your own needs. The key part here is once again to take care of opening every context managers and pass them every required arguments , as the dependency manager would do. import contextlib from app.db import get_async_session , get_user_db from app.models import UserCreate from app.users import get_user_manager from fastapi_users.manager import UserAlreadyExists get_async_session_context = contextlib . asynccontextmanager ( get_async_session ) get_user_db_context = contextlib . asynccontextmanager ( get_user_db ) get_user_manager_context = contextlib . asynccontextmanager ( get_user_manager ) async def create_user ( email : str , password : str , is_superuser : bool = False ): try : async with get_async_session_context () as session : async with get_user_db_context ( session ) as user_db : async with get_user_manager_context ( user_db ) as user_manager : user = await user_manager . create ( UserCreate ( email = email , password = password , is_superuser = is_superuser ) ) print ( f \"User created { user } \" ) except UserAlreadyExists : print ( f \"User { email } already exists\" ) 3. Use it \u00b6 You can now easily use it in a script. For example: import asyncio if __name__ == \"__main__\" : asyncio . run ( create_user ( \"king.arthur@camelot.bt\" , \"guinevere\" ))","title":"Create a user programmatically"},{"location":"cookbook/create-user-programmatically/#create-a-user-programmatically","text":"Sometimes, you'll need to create a user programmatically in the code rather than passing by the REST API endpoint. To do this, we'll create a function that you can call from your code. In this context, we are outside the dependency injection mechanism of FastAPI, so we have to take care of instantiating the UserManager class and all other dependent objects manually . For this cookbook, we'll consider you are starting from the SQLAlchemy full example , but it'll be rather similar for other DBMS.","title":"Create a user programmatically"},{"location":"cookbook/create-user-programmatically/#1-define-dependencies-as-context-managers","text":"Generally, FastAPI dependencies are defined as generators , using the yield keyword. FastAPI knows very well to handle them inside its dependency injection system. For example, here is the definition of the get_user_manager dependency: async def get_user_manager ( user_db : SQLAlchemyUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) In Python, when we want to use a generator, we have to use a for loop, which would be a bit unnatural in this context since we have only one value to get, the user manager instance. To avoid this, we'll transform them into context managers , so we can call them using the with..as syntax. Fortunately, the standard library provides tools to automatically transform generators into context managers. In the following sample, we import our dependencies and create a context manager version using contextlib.asynccontextmanager : import contextlib from app.db import get_async_session , get_user_db from app.models import UserCreate from app.users import get_user_manager from fastapi_users.manager import UserAlreadyExists get_async_session_context = contextlib . asynccontextmanager ( get_async_session ) get_user_db_context = contextlib . asynccontextmanager ( get_user_db ) get_user_manager_context = contextlib . asynccontextmanager ( get_user_manager ) async def create_user ( email : str , password : str , is_superuser : bool = False ): try : async with get_async_session_context () as session : async with get_user_db_context ( session ) as user_db : async with get_user_manager_context ( user_db ) as user_manager : user = await user_manager . create ( UserCreate ( email = email , password = password , is_superuser = is_superuser ) ) print ( f \"User created { user } \" ) except UserAlreadyExists : print ( f \"User { email } already exists\" ) I have other dependencies Since FastAPI Users fully embraces dependency injection, you may have more arguments passed to your database or user manager dependencies. It's important then to not forget anyone. Once again, outside the dependency injection system, you are responsible of instantiating everything yourself.","title":"1. Define dependencies as context managers"},{"location":"cookbook/create-user-programmatically/#2-write-a-function","text":"We are now ready to write a function. The example below shows you a basic example but you can of course adapt it to your own needs. The key part here is once again to take care of opening every context managers and pass them every required arguments , as the dependency manager would do. import contextlib from app.db import get_async_session , get_user_db from app.models import UserCreate from app.users import get_user_manager from fastapi_users.manager import UserAlreadyExists get_async_session_context = contextlib . asynccontextmanager ( get_async_session ) get_user_db_context = contextlib . asynccontextmanager ( get_user_db ) get_user_manager_context = contextlib . asynccontextmanager ( get_user_manager ) async def create_user ( email : str , password : str , is_superuser : bool = False ): try : async with get_async_session_context () as session : async with get_user_db_context ( session ) as user_db : async with get_user_manager_context ( user_db ) as user_manager : user = await user_manager . create ( UserCreate ( email = email , password = password , is_superuser = is_superuser ) ) print ( f \"User created { user } \" ) except UserAlreadyExists : print ( f \"User { email } already exists\" )","title":"2. Write a function"},{"location":"cookbook/create-user-programmatically/#3-use-it","text":"You can now easily use it in a script. For example: import asyncio if __name__ == \"__main__\" : asyncio . run ( create_user ( \"king.arthur@camelot.bt\" , \"guinevere\" ))","title":"3. Use it"},{"location":"migration/08_to_1x/","text":"0.8.x \u27a1\ufe0f 1.x.x \u00b6 1.0 version introduces major breaking changes that need you to update some of your code and migrate your data. Id. are UUID \u00b6 Users and OAuth accounts id. are now represented as real UUID objects instead of plain strings. This change was introduced to leverage efficient storage and indexing for DBMS that supports UUID (especially PostgreSQL and Mongo). In Python code \u00b6 If you were doing comparison betwen a user id. and a string (in unit tests for example), you should now cast the id. to string: # Before assert \"d35d213e-f3d8-4f08-954a-7e0d1bea286f\" == user . id # Now assert \"d35d213e-f3d8-4f08-954a-7e0d1bea286f\" == str ( user . id ) If you were refering to user id. in your Pydantic models, the field should now be of UUID4 type instead of str : from pydantic import BaseModel , UUID4 # Before class Model ( BaseModel ): user_id : str # After class Model ( BaseModel ): user_id : UUID4 MongoDB \u00b6 To avoid any issues, it's recommended to use the standard UUID representation when instantiating the MongoDB client: DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) This parameter controls how the UUID values will be encoded in the database. By default, it's set to pythonLegacy but new applications should consider setting this to standard for cross language compatibility. Read more about this . In database \u00b6 Id. were before stored as strings in the database. You should make a migration to convert string data to UUID data. Danger Scripts below are provided as guidelines. Please review them carefully , adapt them and check that they are working on a test database before applying them to production. BE CAREFUL. THEY CAN DESTROY YOUR DATA. . PostgreSQL \u00b6 PostgreSQL supports UUID type. If not already, you should enable the uuid-ossp extension: CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\" ; To convert the existing id. string column, we can: Create a new column with UUID type. Fill it with the id. converted to UUID. Drop the original id. column. Make the new column a primary key and rename it. ALTER TABLE \"user\" ADD uuid_id UUID ; UPDATE \"user\" SET uuid_id = uuid ( id ); ALTER TABLE \"user\" DROP id ; ALTER TABLE \"user\" ADD PRIMARY KEY ( uuid_id ); ALTER TABLE \"user\" RENAME COLUMN uuid_id TO id ; MySQL \u00b6 MySQL doesn't support UUID type. We'll just convert the column to CHAR(36) type: ALTER TABLE \"user\" MODIFY id CHAR ( 36 ); MongoDB \u00b6 Mongo shell \u00b6 For MongoDB, we can use a forEach iterator to convert the id. for each document: db . getCollection ( 'users' ). find (). forEach ( function ( user ) { var uuid = UUID ( user . id ); db . getCollection ( 'users' ). update ({ _id : user . _id }, [{ $set : { id : uuid }}]); }); Python \u00b6 import uuid import motor.motor_asyncio async def migrate_uuid (): client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] users = db [ \"users\" ] async for user in users . find ({}): await users . update_one ( { \"_id\" : user [ \"_id\" ]}, { \"$set\" : { \"id\" : uuid . UUID ( user [ \"id\" ])}}, ) Splitted routers \u00b6 You now have the responsibility to wire the routers . FastAPI Users doesn't give a bloated users router anymore. Event handlers are also removed. You have to provide your \"after-\" logic as a parameter of the router generator. Before \u00b6 jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) @fastapi_users . on_after_register () def on_after_register ( user : User , request : Request ): print ( f \"User { user . id } has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str , request : Request ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) After \u00b6 def on_after_register ( user : UserDB , request : Request ): print ( f \"User { user . id } has registered.\" ) def on_after_forgot_password ( user : UserDB , token : str , request : Request ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app . include_router ( fastapi_users . get_auth_router ( jwt_authentication ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router ( on_after_register ), prefix = \"/auth\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_reset_password_router ( SECRET , after_forgot_password = on_after_forgot_password ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) Important things to notice: FastAPIUsers takes two arguments less ( reset_password_token_secret and reset_password_token_lifetime_seconds ). You have more flexibility to choose the prefix and tags of the routers. The /login / /logout are now your responsibility to include for each backend. The path will change (before /login/jwt , after /jwt/login ). If you don't care about some of those routers, you can discard them.","title":"0.8.x \u27a1\ufe0f 1.x.x"},{"location":"migration/08_to_1x/#08x-1xx","text":"1.0 version introduces major breaking changes that need you to update some of your code and migrate your data.","title":"0.8.x \u27a1\ufe0f 1.x.x"},{"location":"migration/08_to_1x/#id-are-uuid","text":"Users and OAuth accounts id. are now represented as real UUID objects instead of plain strings. This change was introduced to leverage efficient storage and indexing for DBMS that supports UUID (especially PostgreSQL and Mongo).","title":"Id. are UUID"},{"location":"migration/08_to_1x/#in-python-code","text":"If you were doing comparison betwen a user id. and a string (in unit tests for example), you should now cast the id. to string: # Before assert \"d35d213e-f3d8-4f08-954a-7e0d1bea286f\" == user . id # Now assert \"d35d213e-f3d8-4f08-954a-7e0d1bea286f\" == str ( user . id ) If you were refering to user id. in your Pydantic models, the field should now be of UUID4 type instead of str : from pydantic import BaseModel , UUID4 # Before class Model ( BaseModel ): user_id : str # After class Model ( BaseModel ): user_id : UUID4","title":"In Python code"},{"location":"migration/08_to_1x/#mongodb","text":"To avoid any issues, it's recommended to use the standard UUID representation when instantiating the MongoDB client: DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) This parameter controls how the UUID values will be encoded in the database. By default, it's set to pythonLegacy but new applications should consider setting this to standard for cross language compatibility. Read more about this .","title":"MongoDB"},{"location":"migration/08_to_1x/#in-database","text":"Id. were before stored as strings in the database. You should make a migration to convert string data to UUID data. Danger Scripts below are provided as guidelines. Please review them carefully , adapt them and check that they are working on a test database before applying them to production. BE CAREFUL. THEY CAN DESTROY YOUR DATA. .","title":"In database"},{"location":"migration/08_to_1x/#postgresql","text":"PostgreSQL supports UUID type. If not already, you should enable the uuid-ossp extension: CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\" ; To convert the existing id. string column, we can: Create a new column with UUID type. Fill it with the id. converted to UUID. Drop the original id. column. Make the new column a primary key and rename it. ALTER TABLE \"user\" ADD uuid_id UUID ; UPDATE \"user\" SET uuid_id = uuid ( id ); ALTER TABLE \"user\" DROP id ; ALTER TABLE \"user\" ADD PRIMARY KEY ( uuid_id ); ALTER TABLE \"user\" RENAME COLUMN uuid_id TO id ;","title":"PostgreSQL"},{"location":"migration/08_to_1x/#mysql","text":"MySQL doesn't support UUID type. We'll just convert the column to CHAR(36) type: ALTER TABLE \"user\" MODIFY id CHAR ( 36 );","title":"MySQL"},{"location":"migration/08_to_1x/#mongodb_1","text":"","title":"MongoDB"},{"location":"migration/08_to_1x/#mongo-shell","text":"For MongoDB, we can use a forEach iterator to convert the id. for each document: db . getCollection ( 'users' ). find (). forEach ( function ( user ) { var uuid = UUID ( user . id ); db . getCollection ( 'users' ). update ({ _id : user . _id }, [{ $set : { id : uuid }}]); });","title":"Mongo shell"},{"location":"migration/08_to_1x/#python","text":"import uuid import motor.motor_asyncio async def migrate_uuid (): client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] users = db [ \"users\" ] async for user in users . find ({}): await users . update_one ( { \"_id\" : user [ \"_id\" ]}, { \"$set\" : { \"id\" : uuid . UUID ( user [ \"id\" ])}}, )","title":"Python"},{"location":"migration/08_to_1x/#splitted-routers","text":"You now have the responsibility to wire the routers . FastAPI Users doesn't give a bloated users router anymore. Event handlers are also removed. You have to provide your \"after-\" logic as a parameter of the router generator.","title":"Splitted routers"},{"location":"migration/08_to_1x/#before","text":"jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) @fastapi_users . on_after_register () def on_after_register ( user : User , request : Request ): print ( f \"User { user . id } has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str , request : Request ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" )","title":"Before"},{"location":"migration/08_to_1x/#after","text":"def on_after_register ( user : UserDB , request : Request ): print ( f \"User { user . id } has registered.\" ) def on_after_forgot_password ( user : UserDB , token : str , request : Request ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app . include_router ( fastapi_users . get_auth_router ( jwt_authentication ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router ( on_after_register ), prefix = \"/auth\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_reset_password_router ( SECRET , after_forgot_password = on_after_forgot_password ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) Important things to notice: FastAPIUsers takes two arguments less ( reset_password_token_secret and reset_password_token_lifetime_seconds ). You have more flexibility to choose the prefix and tags of the routers. The /login / /logout are now your responsibility to include for each backend. The path will change (before /login/jwt , after /jwt/login ). If you don't care about some of those routers, you can discard them.","title":"After"},{"location":"migration/1x_to_2x/","text":"1.x.x \u27a1\ufe0f 2.x.x \u00b6 JWT authentication backend \u00b6 To be fully compatible with Swagger authentication, the output of a successful login operation with the JWT authentication backend has changed: Before { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } After { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"token_type\" : \"bearer\" } Make sure to update your clients to read the token in the right property.","title":"1.x.x \u27a1\ufe0f 2.x.x"},{"location":"migration/1x_to_2x/#1xx-2xx","text":"","title":"1.x.x \u27a1\ufe0f 2.x.x"},{"location":"migration/1x_to_2x/#jwt-authentication-backend","text":"To be fully compatible with Swagger authentication, the output of a successful login operation with the JWT authentication backend has changed: Before { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } After { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"token_type\" : \"bearer\" } Make sure to update your clients to read the token in the right property.","title":"JWT authentication backend"},{"location":"migration/2x_to_3x/","text":"2.x.x \u27a1\ufe0f 3.x.x \u00b6 Emails are now case-insensitive \u00b6 Before 3.x.x, the local part (before the @) of the email address was case-sensitive. Therefore, king.arthur@camelot.bt and King.Arthur@camelot.bt were considered as two different users . This behaviour was a bit confusing and not consistent with 99% of web services out there. After 3.x.x, users are fetched from the database with a case-insensitive email search. Bear in mind though that if the user registers with the email King.Arthur@camelot.bt , it will be stored exactly like this in the database (with casing) ; but he will be able to login as king.arthur@camelot.bt . Danger It's super important then, before you upgrade to 3.x.x that you check if there are several users with the same email with different cases ; and that you merge or delete those accounts .","title":"2.x.x \u27a1\ufe0f 3.x.x"},{"location":"migration/2x_to_3x/#2xx-3xx","text":"","title":"2.x.x \u27a1\ufe0f 3.x.x"},{"location":"migration/2x_to_3x/#emails-are-now-case-insensitive","text":"Before 3.x.x, the local part (before the @) of the email address was case-sensitive. Therefore, king.arthur@camelot.bt and King.Arthur@camelot.bt were considered as two different users . This behaviour was a bit confusing and not consistent with 99% of web services out there. After 3.x.x, users are fetched from the database with a case-insensitive email search. Bear in mind though that if the user registers with the email King.Arthur@camelot.bt , it will be stored exactly like this in the database (with casing) ; but he will be able to login as king.arthur@camelot.bt . Danger It's super important then, before you upgrade to 3.x.x that you check if there are several users with the same email with different cases ; and that you merge or delete those accounts .","title":"Emails are now case-insensitive"},{"location":"migration/3x_to_4x/","text":"3.x.x \u27a1\ufe0f 4.x.x \u00b6 expires_at property in OAuthAccount is now optional \u00b6 Before 4.x.x, the expires_at property in OAuthAccount model was mandatory. It was causing issues with some services that don't have such expiration property. If you use SQLAlchemy or Tortoise databases adapters, you'll have to make a migration to update your database schema.","title":"3.x.x \u27a1\ufe0f 4.x.x"},{"location":"migration/3x_to_4x/#3xx-4xx","text":"","title":"3.x.x \u27a1\ufe0f 4.x.x"},{"location":"migration/3x_to_4x/#expires_at-property-in-oauthaccount-is-now-optional","text":"Before 4.x.x, the expires_at property in OAuthAccount model was mandatory. It was causing issues with some services that don't have such expiration property. If you use SQLAlchemy or Tortoise databases adapters, you'll have to make a migration to update your database schema.","title":"expires_at property in OAuthAccount is now optional"},{"location":"migration/4x_to_5x/","text":"4.x.x \u27a1\ufe0f 5.x.x \u00b6 New property is_verified in User model. \u00b6 Starting 5.x.x., there is a new e-mail verification feature . Even if optional, the is_verified property has been added to the User model. If you use SQLAlchemy or Tortoise databases adapters, you'll have to make a migration to update your database schema.","title":"4.x.x \u27a1\ufe0f 5.x.x"},{"location":"migration/4x_to_5x/#4xx-5xx","text":"","title":"4.x.x \u27a1\ufe0f 5.x.x"},{"location":"migration/4x_to_5x/#new-property-is_verified-in-user-model","text":"Starting 5.x.x., there is a new e-mail verification feature . Even if optional, the is_verified property has been added to the User model. If you use SQLAlchemy or Tortoise databases adapters, you'll have to make a migration to update your database schema.","title":"New property is_verified in User model."},{"location":"migration/6x_to_7x/","text":"6.x.x \u27a1\ufe0f 7.x.x \u00b6 The deprecated dependencies to retrieve current user have been removed. Use the current_user factory instead. [ Documentation ] When trying to authenticate a not verified user, a status code 403 is raised instead of status code 401. Thanks @daanbeverdam \ud83c\udf89 [ Documentation ] Your UserUpdate model shouldn't inherit from the base User class. If you have custom fields, you should repeat them in this model. [ Documentation ] Database adapters now live in their own repositories and packages . When upgrading to v7.0.0, the dependency for your database adapter should automatically be installed. The import statements remain unchanged.","title":"6.x.x \u27a1\ufe0f 7.x.x"},{"location":"migration/6x_to_7x/#6xx-7xx","text":"The deprecated dependencies to retrieve current user have been removed. Use the current_user factory instead. [ Documentation ] When trying to authenticate a not verified user, a status code 403 is raised instead of status code 401. Thanks @daanbeverdam \ud83c\udf89 [ Documentation ] Your UserUpdate model shouldn't inherit from the base User class. If you have custom fields, you should repeat them in this model. [ Documentation ] Database adapters now live in their own repositories and packages . When upgrading to v7.0.0, the dependency for your database adapter should automatically be installed. The import statements remain unchanged.","title":"6.x.x \u27a1\ufe0f 7.x.x"},{"location":"migration/7x_to_8x/","text":"7.x.x \u27a1\ufe0f 8.x.x \u00b6 Version 8 includes the biggest code changes since version 1. We reorganized lot of parts of the code to make it even more modular and integrate more into the dependency injection system of FastAPI. Most importantly, you need now to implement a UserManager class and a associated dependency to create an instance of this class. Event handlers should live in the UserManager \u00b6 Before, event handlers like on_after_register or on_after_forgot_password were defined in their own functions that were passed as arguments of router generators. Now, they should be methods of the UserManager class. You can read more in the UserManager documentation . Password validation should live in the UserManager \u00b6 Before, password validation was defined in its own function that was passed as argument of FastAPIUsers . Now, it should be a method of the UserManager class. You can read more in the UserManager documentation . Verify token secret and lifetime parameters are attributes of UserManager \u00b6 Before, verify token and lifetime parameters were passed as argument of get_verify_router . Now, they should be defined as attributes of the UserManager class. You can read more in the UserManager documentation . Reset password token secret and lifetime parameters are attributes of UserManager \u00b6 Before, reset password token and lifetime parameters were passed as argument of get_verify_router . Now, they should be defined as attributes of the UserManager class. You can read more in the UserManager documentation . Database adapter should be provided in a dependency \u00b6 Before, we advised to directly instantiate the database adapter class. Now, it should be instantiated inside a dependency that you define yourself. The benefit of this is that it lives in the dependency injection system of FastAPI, allowing you to have more dynamic logic to create your instance. \u27a1\ufe0f I'm using SQLAlchemy \u27a1\ufe0f I'm using MongoDB \u27a1\ufe0f I'm using Tortoise ORM \u27a1\ufe0f I'm using ormar FastAPIUsers now expect a get_user_manager dependency \u00b6 Before, the database adapter instance was passed as argument of FastAPIUsers . Now, you should define a get_user_manager dependency returning an instance of your UserManager class. This dependency will be dependent of the database adapter dependency. You can read more in the UserManager documentation and FastAPIUsers documentation Lost? \u00b6 If you're unsure or a bit lost, make sure to check the full working examples .","title":"7.x.x \u27a1\ufe0f 8.x.x"},{"location":"migration/7x_to_8x/#7xx-8xx","text":"Version 8 includes the biggest code changes since version 1. We reorganized lot of parts of the code to make it even more modular and integrate more into the dependency injection system of FastAPI. Most importantly, you need now to implement a UserManager class and a associated dependency to create an instance of this class.","title":"7.x.x \u27a1\ufe0f 8.x.x"},{"location":"migration/7x_to_8x/#event-handlers-should-live-in-the-usermanager","text":"Before, event handlers like on_after_register or on_after_forgot_password were defined in their own functions that were passed as arguments of router generators. Now, they should be methods of the UserManager class. You can read more in the UserManager documentation .","title":"Event handlers should live in the UserManager"},{"location":"migration/7x_to_8x/#password-validation-should-live-in-the-usermanager","text":"Before, password validation was defined in its own function that was passed as argument of FastAPIUsers . Now, it should be a method of the UserManager class. You can read more in the UserManager documentation .","title":"Password validation should live in the UserManager"},{"location":"migration/7x_to_8x/#verify-token-secret-and-lifetime-parameters-are-attributes-of-usermanager","text":"Before, verify token and lifetime parameters were passed as argument of get_verify_router . Now, they should be defined as attributes of the UserManager class. You can read more in the UserManager documentation .","title":"Verify token secret and lifetime parameters are attributes of UserManager"},{"location":"migration/7x_to_8x/#reset-password-token-secret-and-lifetime-parameters-are-attributes-of-usermanager","text":"Before, reset password token and lifetime parameters were passed as argument of get_verify_router . Now, they should be defined as attributes of the UserManager class. You can read more in the UserManager documentation .","title":"Reset password token secret and lifetime parameters are attributes of UserManager"},{"location":"migration/7x_to_8x/#database-adapter-should-be-provided-in-a-dependency","text":"Before, we advised to directly instantiate the database adapter class. Now, it should be instantiated inside a dependency that you define yourself. The benefit of this is that it lives in the dependency injection system of FastAPI, allowing you to have more dynamic logic to create your instance. \u27a1\ufe0f I'm using SQLAlchemy \u27a1\ufe0f I'm using MongoDB \u27a1\ufe0f I'm using Tortoise ORM \u27a1\ufe0f I'm using ormar","title":"Database adapter should be provided in a dependency"},{"location":"migration/7x_to_8x/#fastapiusers-now-expect-a-get_user_manager-dependency","text":"Before, the database adapter instance was passed as argument of FastAPIUsers . Now, you should define a get_user_manager dependency returning an instance of your UserManager class. This dependency will be dependent of the database adapter dependency. You can read more in the UserManager documentation and FastAPIUsers documentation","title":"FastAPIUsers now expect a get_user_manager dependency"},{"location":"migration/7x_to_8x/#lost","text":"If you're unsure or a bit lost, make sure to check the full working examples .","title":"Lost?"},{"location":"migration/8x_to_9x/","text":"8.x.x \u27a1\ufe0f 9.x.x \u00b6 Version 9 revamps the authentication backends: we splitted the logic of a backend into two: the transport , which is how the token will be carried over the request and the strategy , which is how the token is generated and secured. The benefit of this is that we'll soon be able to propose new strategies, like database session tokens, without having to repeat the transport logic which remains the same. Convert the authentication backend \u00b6 You now have to generate an authentication backend with a transport and a strategy. I used JWTAuthentication \u00b6 Before After from fastapi_users.authentication import JWTAuthentication jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"auth/jwt/login\" ) from fastapi_users.authentication import AuthenticationBackend , BearerTransport , JWTStrategy SECRET = \"SECRET\" bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) Warning There is no default name anymore: you need to provide it yourself for each of your backends. I used CookieAuthentication \u00b6 Before After from fastapi_users.authentication import CookieAuthentication cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) from fastapi_users.authentication import AuthenticationBackend , CookieTransport , JWTStrategy SECRET = \"SECRET\" cookie_transport = CookieTransport ( cookie_max_age = 3600 ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"cookie\" , transport = cookie_transport , get_strategy = get_jwt_strategy , ) Warning There is no default name anymore: you need to provide it yourself for each of your backends. Tip Notice that the strategy is the same for both authentication backends. That's the beauty of this approach: the token generation is decoupled from its transport. OAuth: one router for each backend \u00b6 Before, a single OAuth router was enough to login with any of your authentication backend. Now, you need to generate a router for each of your backends. Before After app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) authentication_backend is not needed on /authorize \u00b6 The consequence of this is that you don't need to specify the authentication backend when making a request to /authorize . Before After curl \\ -H \"Content-Type: application/json\" \\ -X GET \\ http://localhost:8000/auth/google/authorize?authentication_backend = jwt curl \\ -H \"Content-Type: application/json\" \\ -X GET \\ http://localhost:8000/auth/google/authorize Lost? \u00b6 If you're unsure or a bit lost, make sure to check the full working examples .","title":"8.x.x \u27a1\ufe0f 9.x.x"},{"location":"migration/8x_to_9x/#8xx-9xx","text":"Version 9 revamps the authentication backends: we splitted the logic of a backend into two: the transport , which is how the token will be carried over the request and the strategy , which is how the token is generated and secured. The benefit of this is that we'll soon be able to propose new strategies, like database session tokens, without having to repeat the transport logic which remains the same.","title":"8.x.x \u27a1\ufe0f 9.x.x"},{"location":"migration/8x_to_9x/#convert-the-authentication-backend","text":"You now have to generate an authentication backend with a transport and a strategy.","title":"Convert the authentication backend"},{"location":"migration/8x_to_9x/#i-used-jwtauthentication","text":"Before After from fastapi_users.authentication import JWTAuthentication jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"auth/jwt/login\" ) from fastapi_users.authentication import AuthenticationBackend , BearerTransport , JWTStrategy SECRET = \"SECRET\" bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) Warning There is no default name anymore: you need to provide it yourself for each of your backends.","title":"I used JWTAuthentication"},{"location":"migration/8x_to_9x/#i-used-cookieauthentication","text":"Before After from fastapi_users.authentication import CookieAuthentication cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) from fastapi_users.authentication import AuthenticationBackend , CookieTransport , JWTStrategy SECRET = \"SECRET\" cookie_transport = CookieTransport ( cookie_max_age = 3600 ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"cookie\" , transport = cookie_transport , get_strategy = get_jwt_strategy , ) Warning There is no default name anymore: you need to provide it yourself for each of your backends. Tip Notice that the strategy is the same for both authentication backends. That's the beauty of this approach: the token generation is decoupled from its transport.","title":"I used CookieAuthentication"},{"location":"migration/8x_to_9x/#oauth-one-router-for-each-backend","text":"Before, a single OAuth router was enough to login with any of your authentication backend. Now, you need to generate a router for each of your backends. Before After app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], )","title":"OAuth: one router for each backend"},{"location":"migration/8x_to_9x/#authentication_backend-is-not-needed-on-authorize","text":"The consequence of this is that you don't need to specify the authentication backend when making a request to /authorize . Before After curl \\ -H \"Content-Type: application/json\" \\ -X GET \\ http://localhost:8000/auth/google/authorize?authentication_backend = jwt curl \\ -H \"Content-Type: application/json\" \\ -X GET \\ http://localhost:8000/auth/google/authorize","title":"authentication_backend is not needed on /authorize"},{"location":"migration/8x_to_9x/#lost","text":"If you're unsure or a bit lost, make sure to check the full working examples .","title":"Lost?"},{"location":"usage/current-user/","text":"Get current user \u00b6 FastAPI Users provides a dependency callable to easily inject authenticated user in your routes. They are available from your FastAPIUsers instance. Tip For more information about how to make an authenticated request to your API, check the documentation of your Authentication method . current_user \u00b6 Return a dependency callable to retrieve currently authenticated user, passing the following parameters: optional : If True , None is returned if there is no authenticated user or if it doesn't pass the other requirements. Otherwise, throw 401 Unauthorized . Defaults to False . active : If True , throw 401 Unauthorized if the authenticated user is inactive. Defaults to False . verified : If True , throw 403 Forbidden if the authenticated user is not verified. Defaults to False . superuser : If True , throw 403 Forbidden if the authenticated user is not a superuser. Defaults to False . get_enabled_backends : Optional dependency callable returning a list of enabled authentication backends. Useful if you want to dynamically enable some authentication backends based on external logic, like a configuration in database. By default, all specified authentication backends are enabled. Please not however that every backends will appear in the OpenAPI documentation, as FastAPI resolves it statically. Create it once and reuse it This function is a factory , a function returning another function \ud83e\udd2f It's this returned function that will be the dependency called by FastAPI in your API routes. To avoid having to generate it on each route and avoid issues when unit testing, it's strongly recommended that you assign the result in a variable and reuse it at will in your routes. The examples below demonstrate this pattern. Examples \u00b6 Get the current user ( active or not ) \u00b6 current_user = fastapi_users . current_user () @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_user )): return f \"Hello, { user . email } \" Get the current active user \u00b6 current_active_user = fastapi_users . current_user ( active = True ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_active_user )): return f \"Hello, { user . email } \" Get the current active and verified user \u00b6 current_active_verified_user = fastapi_users . current_user ( active = True , verified = True ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_active_verified_user )): return f \"Hello, { user . email } \" Get the current active superuser \u00b6 current_superuser = fastapi_users . current_user ( active = True , superuser = True ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_superuser )): return f \"Hello, { user . email } \" Dynamically enable authentication backends \u00b6 Warning This is an advanced feature for cases where you have several authentication backends that are enabled conditionally. In most cases, you won't need this option. from fastapi import Request from fastapi_users.authentication import AuthenticationBackend , BearerTransport , CookieTransport , JWTStrategy SECRET = \"SECRET\" bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) cookie_transport = CookieTransport ( cookie_max_age = 3600 ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) jwt_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) cookie_backend = AuthenticationBackend ( name = \"jwt\" , transport = cookie_transport , get_strategy = get_jwt_strategy , ) async def get_enabled_backends ( request : Request ): \"\"\"Return the enabled dependencies following custom logic.\"\"\" if request . url . path == \"/protected-route-only-jwt\" : return [ jwt_backend ] else : return [ cookie_backend , jwt_backend ] current_active_user = fastapi_users . current_user ( active = True , get_enabled_backends = get_enabled_backends ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_active_user )): return f \"Hello, { user . email } . You are authenticated with a cookie or a JWT.\" @app . get ( \"/protected-route-only-jwt\" ) def protected_route ( user : User = Depends ( current_active_user )): return f \"Hello, { user . email } . You are authenticated with a JWT.\" In a path operation \u00b6 If you don't need the user in the route logic, you can use this syntax: @app . get ( \"/protected-route\" , dependencies = [ Depends ( current_superuser )]) def protected_route (): return \"Hello, some user.\" You can read more about this in FastAPI docs .","title":"Get current user"},{"location":"usage/current-user/#get-current-user","text":"FastAPI Users provides a dependency callable to easily inject authenticated user in your routes. They are available from your FastAPIUsers instance. Tip For more information about how to make an authenticated request to your API, check the documentation of your Authentication method .","title":"Get current user"},{"location":"usage/current-user/#current_user","text":"Return a dependency callable to retrieve currently authenticated user, passing the following parameters: optional : If True , None is returned if there is no authenticated user or if it doesn't pass the other requirements. Otherwise, throw 401 Unauthorized . Defaults to False . active : If True , throw 401 Unauthorized if the authenticated user is inactive. Defaults to False . verified : If True , throw 403 Forbidden if the authenticated user is not verified. Defaults to False . superuser : If True , throw 403 Forbidden if the authenticated user is not a superuser. Defaults to False . get_enabled_backends : Optional dependency callable returning a list of enabled authentication backends. Useful if you want to dynamically enable some authentication backends based on external logic, like a configuration in database. By default, all specified authentication backends are enabled. Please not however that every backends will appear in the OpenAPI documentation, as FastAPI resolves it statically. Create it once and reuse it This function is a factory , a function returning another function \ud83e\udd2f It's this returned function that will be the dependency called by FastAPI in your API routes. To avoid having to generate it on each route and avoid issues when unit testing, it's strongly recommended that you assign the result in a variable and reuse it at will in your routes. The examples below demonstrate this pattern.","title":"current_user"},{"location":"usage/current-user/#examples","text":"","title":"Examples"},{"location":"usage/current-user/#get-the-current-user-active-or-not","text":"current_user = fastapi_users . current_user () @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_user )): return f \"Hello, { user . email } \"","title":"Get the current user (active or not)"},{"location":"usage/current-user/#get-the-current-active-user","text":"current_active_user = fastapi_users . current_user ( active = True ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_active_user )): return f \"Hello, { user . email } \"","title":"Get the current active user"},{"location":"usage/current-user/#get-the-current-active-and-verified-user","text":"current_active_verified_user = fastapi_users . current_user ( active = True , verified = True ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_active_verified_user )): return f \"Hello, { user . email } \"","title":"Get the current active and verified user"},{"location":"usage/current-user/#get-the-current-active-superuser","text":"current_superuser = fastapi_users . current_user ( active = True , superuser = True ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_superuser )): return f \"Hello, { user . email } \"","title":"Get the current active superuser"},{"location":"usage/current-user/#dynamically-enable-authentication-backends","text":"Warning This is an advanced feature for cases where you have several authentication backends that are enabled conditionally. In most cases, you won't need this option. from fastapi import Request from fastapi_users.authentication import AuthenticationBackend , BearerTransport , CookieTransport , JWTStrategy SECRET = \"SECRET\" bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) cookie_transport = CookieTransport ( cookie_max_age = 3600 ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) jwt_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) cookie_backend = AuthenticationBackend ( name = \"jwt\" , transport = cookie_transport , get_strategy = get_jwt_strategy , ) async def get_enabled_backends ( request : Request ): \"\"\"Return the enabled dependencies following custom logic.\"\"\" if request . url . path == \"/protected-route-only-jwt\" : return [ jwt_backend ] else : return [ cookie_backend , jwt_backend ] current_active_user = fastapi_users . current_user ( active = True , get_enabled_backends = get_enabled_backends ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_active_user )): return f \"Hello, { user . email } . You are authenticated with a cookie or a JWT.\" @app . get ( \"/protected-route-only-jwt\" ) def protected_route ( user : User = Depends ( current_active_user )): return f \"Hello, { user . email } . You are authenticated with a JWT.\"","title":"Dynamically enable authentication backends"},{"location":"usage/current-user/#in-a-path-operation","text":"If you don't need the user in the route logic, you can use this syntax: @app . get ( \"/protected-route\" , dependencies = [ Depends ( current_superuser )]) def protected_route (): return \"Hello, some user.\" You can read more about this in FastAPI docs .","title":"In a path operation"},{"location":"usage/flow/","text":"Flow \u00b6 This page will present you a complete registration and authentication flow once you've setup FastAPI Users . Each example will be presented with a cURL and an axios example. 1. Registration \u00b6 First step, of course, is to register as a user. Request \u00b6 cURL axios curl \\ -H \"Content-Type: application/json\" \\ -X POST \\ -d \"{\\\"email\\\": \\\"king.arthur@camelot.bt\\\",\\\"password\\\": \\\"guinevere\\\"}\" \\ http://localhost:8000/auth/register axios . post ( 'http://localhost:8000/auth/register' , { email : 'king.arthur@camelot.bt' , password : 'guinevere' , }) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } Info Several things to bear in mind: If you have defined other required fields in your User model (like a first name or a birthdate), you'll have to provide them in the payload. The user is active by default. The user cannot set is_active or is_superuser itself at registration. Only a superuser can do it by PATCHing the user. 2. Login \u00b6 Now, you can login as this new user. You can generate a login route for each authentication backend . Each backend will have a different response. Bearer + JWT \u00b6 Request \u00b6 cURL axios curl \\ -H \"Content-Type: multipart/form-data\" \\ -X POST \\ -F \"username=king.arthur@camelot.bt\" \\ -F \"password=guinevere\" \\ http://localhost:8000/auth/jwt/login const formData = new FormData (); formData . set ( 'username' , 'king.arthur@camelot.bt' ); formData . set ( 'password' , 'guinevere' ); axios . post ( 'http://localhost:8000/auth/jwt/login' , formData , { headers : { 'Content-Type' : 'multipart/form-data' , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Warning Notice that we don't send it as a JSON payload here but with form data instead. Also, the email is provided by a field named username . Response \u00b6 You'll get a JSON response looking like this: { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM\" , \"token_type\" : \"bearer\" } You can use this token to make authenticated requests as the user king.arthur@camelot.bt . We'll see how in the next section. Cookie + JWT \u00b6 Request \u00b6 cURL axios curl \\ -v \\ -H \"Content-Type: multipart/form-data\" \\ -X POST \\ -F \"username=king.arthur@camelot.bt\" \\ -F \"password=guinevere\" \\ http://localhost:8000/auth/cookie/login const formData = new FormData (); formData . set ( 'username' , 'king.arthur@camelot.bt' ); formData . set ( 'password' , 'guinevere' ); axios . post ( 'http://localhost:8000/auth/cookie/login' , formData , { headers : { 'Content-Type' : 'multipart/form-data' , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Warning Notice that we don't send it as a JSON payload here but with form data instead. Also, the email is provided by a field named username . Response \u00b6 You'll get an empty response. However, the response will come with a Set-Cookie header (that's why we added the -v option in cURL to see them). set-cookie: fastapiusersauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiYzYwNjBmMTEtNTM0OS00YTI0LThiNGEtYTJhODc1ZGM1Mzk1IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4OTQ3fQ.qNA4oPVYhoqrJIk-zvAyEfEVoEnP156G30H_SWEU0sU; HttpOnly; Max-Age=3600; Path=/; Secure You can make authenticated requests as the user king.arthur@camelot.bt by setting a Cookie header with this cookie. Tip The cookie backend is more suited for browsers, as they handle them automatically. This means that if you make a login request in the browser, it will automatically store the cookie and automatically send it in subsequent requests. 3. Get my profile \u00b6 Now that we can authenticate, we can get our own profile data. Depending on your authentication backend , the method to authenticate the request will vary. We'll stick with JWT from now on. Request \u00b6 cURL axios export TOKEN = \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM\" ; curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X GET \\ http://localhost:8000/users/me const TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM' ; axios . get ( 'http://localhost:8000/users/me' , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } Tip If you use one of the dependency callable to protect one of your own endpoint, you'll have to authenticate exactly in the same way. 4. Update my profile \u00b6 We can also update our own profile. For example, we can change our password like this. Request \u00b6 cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X PATCH \\ -d \"{\\\"password\\\": \\\"lancelot\\\"}\" \\ http://localhost:8000/users/me axios . patch ( 'http://localhost:8000/users/me' , { password : 'lancelot' , }, { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } Info Once again, the user cannot set is_active or is_superuser itself. Only a superuser can do it by PATCHing the user. 5. Become a superuser \ud83e\uddb8\ud83c\udffb\u200d\u2642\ufe0f \u00b6 If you want to manage the users of your application, you'll have to become a superuser . The very first superuser can only be set at database level : open it through a CLI or a GUI, find your user and set the is_superuser column/property to true . 5.1. Get the profile of any user \u00b6 Now that you are a superuser, you can leverage the power of superuser routes . You can for example get the profile of any user in the database given its id. Request \u00b6 cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X GET \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios . get ( 'http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476' , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 5.1. Update any user \u00b6 We can now update the profile of any user. For example, we can promote it as superuser. Request \u00b6 cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X PATCH \\ -d \"{\\\"is_superuser\\\": true}\" \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios . patch ( 'http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476' , { is_superuser : true , }, { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : true } 5.2. Delete any user \u00b6 Finally, we can delete a user. Request \u00b6 cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X DELETE \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios . delete ( 'http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476' , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get an empty response. 6. Logout \u00b6 We can also end the session. Request \u00b6 cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Cookie: fastapiusersauth= $TOKEN \" \\ -X POST \\ http://localhost:8000/auth/cookie/logout axios . post ( 'http://localhost:8000/auth/cookie/logout' , null , { headers : { 'Cookie' : `fastapiusersauth= ${ TOKEN } ` , }, } ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get an empty response. Conclusion \u00b6 That's it! You now have a good overview of how you can manage the users through the API. Be sure to check the Routes page to have all the details about each endpoints.","title":"Flow"},{"location":"usage/flow/#flow","text":"This page will present you a complete registration and authentication flow once you've setup FastAPI Users . Each example will be presented with a cURL and an axios example.","title":"Flow"},{"location":"usage/flow/#1-registration","text":"First step, of course, is to register as a user.","title":"1. Registration"},{"location":"usage/flow/#request","text":"cURL axios curl \\ -H \"Content-Type: application/json\" \\ -X POST \\ -d \"{\\\"email\\\": \\\"king.arthur@camelot.bt\\\",\\\"password\\\": \\\"guinevere\\\"}\" \\ http://localhost:8000/auth/register axios . post ( 'http://localhost:8000/auth/register' , { email : 'king.arthur@camelot.bt' , password : 'guinevere' , }) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response","text":"You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } Info Several things to bear in mind: If you have defined other required fields in your User model (like a first name or a birthdate), you'll have to provide them in the payload. The user is active by default. The user cannot set is_active or is_superuser itself at registration. Only a superuser can do it by PATCHing the user.","title":"Response"},{"location":"usage/flow/#2-login","text":"Now, you can login as this new user. You can generate a login route for each authentication backend . Each backend will have a different response.","title":"2. Login"},{"location":"usage/flow/#bearer-jwt","text":"","title":"Bearer + JWT"},{"location":"usage/flow/#request_1","text":"cURL axios curl \\ -H \"Content-Type: multipart/form-data\" \\ -X POST \\ -F \"username=king.arthur@camelot.bt\" \\ -F \"password=guinevere\" \\ http://localhost:8000/auth/jwt/login const formData = new FormData (); formData . set ( 'username' , 'king.arthur@camelot.bt' ); formData . set ( 'password' , 'guinevere' ); axios . post ( 'http://localhost:8000/auth/jwt/login' , formData , { headers : { 'Content-Type' : 'multipart/form-data' , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Warning Notice that we don't send it as a JSON payload here but with form data instead. Also, the email is provided by a field named username .","title":"Request"},{"location":"usage/flow/#response_1","text":"You'll get a JSON response looking like this: { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM\" , \"token_type\" : \"bearer\" } You can use this token to make authenticated requests as the user king.arthur@camelot.bt . We'll see how in the next section.","title":"Response"},{"location":"usage/flow/#cookie-jwt","text":"","title":"Cookie + JWT"},{"location":"usage/flow/#request_2","text":"cURL axios curl \\ -v \\ -H \"Content-Type: multipart/form-data\" \\ -X POST \\ -F \"username=king.arthur@camelot.bt\" \\ -F \"password=guinevere\" \\ http://localhost:8000/auth/cookie/login const formData = new FormData (); formData . set ( 'username' , 'king.arthur@camelot.bt' ); formData . set ( 'password' , 'guinevere' ); axios . post ( 'http://localhost:8000/auth/cookie/login' , formData , { headers : { 'Content-Type' : 'multipart/form-data' , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Warning Notice that we don't send it as a JSON payload here but with form data instead. Also, the email is provided by a field named username .","title":"Request"},{"location":"usage/flow/#response_2","text":"You'll get an empty response. However, the response will come with a Set-Cookie header (that's why we added the -v option in cURL to see them). set-cookie: fastapiusersauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiYzYwNjBmMTEtNTM0OS00YTI0LThiNGEtYTJhODc1ZGM1Mzk1IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4OTQ3fQ.qNA4oPVYhoqrJIk-zvAyEfEVoEnP156G30H_SWEU0sU; HttpOnly; Max-Age=3600; Path=/; Secure You can make authenticated requests as the user king.arthur@camelot.bt by setting a Cookie header with this cookie. Tip The cookie backend is more suited for browsers, as they handle them automatically. This means that if you make a login request in the browser, it will automatically store the cookie and automatically send it in subsequent requests.","title":"Response"},{"location":"usage/flow/#3-get-my-profile","text":"Now that we can authenticate, we can get our own profile data. Depending on your authentication backend , the method to authenticate the request will vary. We'll stick with JWT from now on.","title":"3. Get my profile"},{"location":"usage/flow/#request_3","text":"cURL axios export TOKEN = \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM\" ; curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X GET \\ http://localhost:8000/users/me const TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM' ; axios . get ( 'http://localhost:8000/users/me' , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_3","text":"You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } Tip If you use one of the dependency callable to protect one of your own endpoint, you'll have to authenticate exactly in the same way.","title":"Response"},{"location":"usage/flow/#4-update-my-profile","text":"We can also update our own profile. For example, we can change our password like this.","title":"4. Update my profile"},{"location":"usage/flow/#request_4","text":"cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X PATCH \\ -d \"{\\\"password\\\": \\\"lancelot\\\"}\" \\ http://localhost:8000/users/me axios . patch ( 'http://localhost:8000/users/me' , { password : 'lancelot' , }, { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_4","text":"You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } Info Once again, the user cannot set is_active or is_superuser itself. Only a superuser can do it by PATCHing the user.","title":"Response"},{"location":"usage/flow/#5-become-a-superuser","text":"If you want to manage the users of your application, you'll have to become a superuser . The very first superuser can only be set at database level : open it through a CLI or a GUI, find your user and set the is_superuser column/property to true .","title":"5. Become a superuser \ud83e\uddb8\ud83c\udffb\u200d\u2642\ufe0f"},{"location":"usage/flow/#51-get-the-profile-of-any-user","text":"Now that you are a superuser, you can leverage the power of superuser routes . You can for example get the profile of any user in the database given its id.","title":"5.1. Get the profile of any user"},{"location":"usage/flow/#request_5","text":"cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X GET \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios . get ( 'http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476' , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_5","text":"You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false }","title":"Response"},{"location":"usage/flow/#51-update-any-user","text":"We can now update the profile of any user. For example, we can promote it as superuser.","title":"5.1. Update any user"},{"location":"usage/flow/#request_6","text":"cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X PATCH \\ -d \"{\\\"is_superuser\\\": true}\" \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios . patch ( 'http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476' , { is_superuser : true , }, { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_6","text":"You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : true }","title":"Response"},{"location":"usage/flow/#52-delete-any-user","text":"Finally, we can delete a user.","title":"5.2. Delete any user"},{"location":"usage/flow/#request_7","text":"cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X DELETE \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios . delete ( 'http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476' , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_7","text":"You'll get an empty response.","title":"Response"},{"location":"usage/flow/#6-logout","text":"We can also end the session.","title":"6. Logout"},{"location":"usage/flow/#request_8","text":"cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Cookie: fastapiusersauth= $TOKEN \" \\ -X POST \\ http://localhost:8000/auth/cookie/logout axios . post ( 'http://localhost:8000/auth/cookie/logout' , null , { headers : { 'Cookie' : `fastapiusersauth= ${ TOKEN } ` , }, } ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_8","text":"You'll get an empty response.","title":"Response"},{"location":"usage/flow/#conclusion","text":"That's it! You now have a good overview of how you can manage the users through the API. Be sure to check the Routes page to have all the details about each endpoints.","title":"Conclusion"},{"location":"usage/routes/","text":"Routes \u00b6 You'll find here the routes exposed by FastAPI Users . Note that you can also review them through the interactive API docs . Auth router \u00b6 Each authentication backend you generate a router for will produce the following routes. Take care about the prefix you gave it, especially if you have several backends. POST /login \u00b6 Login a user against the method named name . Check the corresponding authentication method to view the success response. Payload ( application/x-www-form-urlencoded ) username=king.arthur@camelot.bt&password=guinevere 422 Validation Error 400 Bad Request Bad credentials or the user is inactive. { \"detail\" : \"LOGIN_BAD_CREDENTIALS\" } 400 Bad Request The user is not verified. { \"detail\" : \"LOGIN_USER_NOT_VERIFIED\" } POST /logout \u00b6 Logout the authenticated user against the method named name . Check the corresponding authentication method to view the success response. 401 Unauthorized Missing token or inactive user. 200 OK The logout process was successful. Register router \u00b6 POST /register \u00b6 Register a new user. Will call the on_after_register handler on successful registration. Payload { \"email\" : \"king.arthur@camelot.bt\" , \"password\" : \"guinevere\" } 201 Created { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 422 Validation Error 400 Bad Request A user already exists with this email. { \"detail\" : \"REGISTER_USER_ALREADY_EXISTS\" } 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"REGISTER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } } Reset password router \u00b6 POST /forgot-password \u00b6 Request a reset password procedure. Will generate a temporary token and call the on_after_forgot_password handler if the user exists. To prevent malicious users from guessing existing users in your database, the route will always return a 202 Accepted response, even if the user requested does not exist. Payload { \"email\" : \"king.arthur@camelot.bt\" } 202 Accepted POST /reset-password \u00b6 Reset a password. Requires the token generated by the /forgot-password route. Payload { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"password\" : \"merlin\" } 200 OK 422 Validation Error 400 Bad Request Bad or expired token. { \"detail\" : \"RESET_PASSWORD_BAD_TOKEN\" } 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"REGISTER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } } Verify router \u00b6 POST /request-verify-token \u00b6 Request a user to verify their e-mail. Will generate a temporary token and call the on_after_request_verify handler if the user exists , active and not already verified . To prevent malicious users from guessing existing users in your database, the route will always return a 202 Accepted response, even if the user requested does not exist, not active or already verified. Payload { \"email\" : \"king.arthur@camelot.bt\" } 202 Accepted POST /verify \u00b6 Verify a user. Requires the token generated by the /request-verify-token route. Will call the call the on_after_verify handler on success. Payload { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } 200 OK 422 Validation Error 400 Bad Request Bad token, not existing user or not the e-mail currently set for the user. { \"detail\" : \"VERIFY_USER_BAD_TOKEN\" } 400 Bad Request The user is already verified. { \"detail\" : \"VERIFY_USER_ALREADY_VERIFIED\" } OAuth router \u00b6 Each OAuth router you define will expose the two following routes. GET /authorize \u00b6 Return the authorization URL for the OAuth service where you should redirect your user. Query parameters scopes : Optional list of scopes to ask for. Expected format: scopes=a&scopes=b . 200 OK { \"authorization_url\" : \"https://www.tintagel.bt/oauth/authorize?client_id=CLIENT_ID&scopes=a+b&redirect_uri=https://www.camelot.bt/oauth/callback\" } 422 Validation Error Invalid parameters - e.g. unknown authentication backend. GET /callback \u00b6 Handle the OAuth callback. Query parameters code : OAuth callback code. state : State token. error : OAuth error. Depending on the situation, several things can happen: The OAuth account exists in database and is linked to a user: OAuth account is updated in database with fresh access token. The user is authenticated following the chosen authentication method . The OAuth account doesn't exist in database but a user with the same email address exists: OAuth account is linked to the user. The user is authenticated following the chosen authentication method . The OAuth account doesn't exist in database and no user with the email address exists: A new user is created and linked to the OAuth account. The user is authenticated following the chosen authentication method . 400 Bad Request Invalid token. 400 Bad Request User is inactive. { \"detail\" : \"LOGIN_BAD_CREDENTIALS\" } Users router \u00b6 GET /me \u00b6 Return the current authenticated active user. 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 401 Unauthorized Missing token or inactive user. PATCH /me \u00b6 Update the current authenticated active user. Payload { \"email\" : \"king.arthur@tintagel.bt\" , \"password\" : \"merlin\" } 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@tintagel.bt\" , \"is_active\" : true , \"is_superuser\" : false } 401 Unauthorized Missing token or inactive user. 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"UPDATE_USER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } } 400 Bad Request A user with this email already exists. { \"detail\" : \"UPDATE_USER_EMAIL_ALREADY_EXISTS\" } 422 Validation Error GET /{user_id} \u00b6 Return the user with id user_id . 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 401 Unauthorized Missing token or inactive user. 403 Forbidden Not a superuser. 404 Not found The user does not exist. PATCH /{user_id} \u00b6 Update the user with id user_id . Payload { \"email\" : \"king.arthur@tintagel.bt\" , \"password\" : \"merlin\" , \"is_active\" : false , \"is_superuser\" : true } 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : false , \"is_superuser\" : true } 401 Unauthorized Missing token or inactive user. 403 Forbidden Not a superuser. 404 Not found The user does not exist. 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"UPDATE_USER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } } 400 Bad Request A user with this email already exists. { \"detail\" : \"UPDATE_USER_EMAIL_ALREADY_EXISTS\" } DELETE /{user_id} \u00b6 Delete the user with id user_id . 204 No content 401 Unauthorized Missing token or inactive user. 403 Forbidden Not a superuser. 404 Not found The user does not exist.","title":"Routes"},{"location":"usage/routes/#routes","text":"You'll find here the routes exposed by FastAPI Users . Note that you can also review them through the interactive API docs .","title":"Routes"},{"location":"usage/routes/#auth-router","text":"Each authentication backend you generate a router for will produce the following routes. Take care about the prefix you gave it, especially if you have several backends.","title":"Auth router"},{"location":"usage/routes/#post-login","text":"Login a user against the method named name . Check the corresponding authentication method to view the success response. Payload ( application/x-www-form-urlencoded ) username=king.arthur@camelot.bt&password=guinevere 422 Validation Error 400 Bad Request Bad credentials or the user is inactive. { \"detail\" : \"LOGIN_BAD_CREDENTIALS\" } 400 Bad Request The user is not verified. { \"detail\" : \"LOGIN_USER_NOT_VERIFIED\" }","title":"POST /login"},{"location":"usage/routes/#post-logout","text":"Logout the authenticated user against the method named name . Check the corresponding authentication method to view the success response. 401 Unauthorized Missing token or inactive user. 200 OK The logout process was successful.","title":"POST /logout"},{"location":"usage/routes/#register-router","text":"","title":"Register router"},{"location":"usage/routes/#post-register","text":"Register a new user. Will call the on_after_register handler on successful registration. Payload { \"email\" : \"king.arthur@camelot.bt\" , \"password\" : \"guinevere\" } 201 Created { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 422 Validation Error 400 Bad Request A user already exists with this email. { \"detail\" : \"REGISTER_USER_ALREADY_EXISTS\" } 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"REGISTER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } }","title":"POST /register"},{"location":"usage/routes/#reset-password-router","text":"","title":"Reset password router"},{"location":"usage/routes/#post-forgot-password","text":"Request a reset password procedure. Will generate a temporary token and call the on_after_forgot_password handler if the user exists. To prevent malicious users from guessing existing users in your database, the route will always return a 202 Accepted response, even if the user requested does not exist. Payload { \"email\" : \"king.arthur@camelot.bt\" } 202 Accepted","title":"POST /forgot-password"},{"location":"usage/routes/#post-reset-password","text":"Reset a password. Requires the token generated by the /forgot-password route. Payload { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"password\" : \"merlin\" } 200 OK 422 Validation Error 400 Bad Request Bad or expired token. { \"detail\" : \"RESET_PASSWORD_BAD_TOKEN\" } 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"REGISTER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } }","title":"POST /reset-password"},{"location":"usage/routes/#verify-router","text":"","title":"Verify router"},{"location":"usage/routes/#post-request-verify-token","text":"Request a user to verify their e-mail. Will generate a temporary token and call the on_after_request_verify handler if the user exists , active and not already verified . To prevent malicious users from guessing existing users in your database, the route will always return a 202 Accepted response, even if the user requested does not exist, not active or already verified. Payload { \"email\" : \"king.arthur@camelot.bt\" } 202 Accepted","title":"POST /request-verify-token"},{"location":"usage/routes/#post-verify","text":"Verify a user. Requires the token generated by the /request-verify-token route. Will call the call the on_after_verify handler on success. Payload { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } 200 OK 422 Validation Error 400 Bad Request Bad token, not existing user or not the e-mail currently set for the user. { \"detail\" : \"VERIFY_USER_BAD_TOKEN\" } 400 Bad Request The user is already verified. { \"detail\" : \"VERIFY_USER_ALREADY_VERIFIED\" }","title":"POST /verify"},{"location":"usage/routes/#oauth-router","text":"Each OAuth router you define will expose the two following routes.","title":"OAuth router"},{"location":"usage/routes/#get-authorize","text":"Return the authorization URL for the OAuth service where you should redirect your user. Query parameters scopes : Optional list of scopes to ask for. Expected format: scopes=a&scopes=b . 200 OK { \"authorization_url\" : \"https://www.tintagel.bt/oauth/authorize?client_id=CLIENT_ID&scopes=a+b&redirect_uri=https://www.camelot.bt/oauth/callback\" } 422 Validation Error Invalid parameters - e.g. unknown authentication backend.","title":"GET /authorize"},{"location":"usage/routes/#get-callback","text":"Handle the OAuth callback. Query parameters code : OAuth callback code. state : State token. error : OAuth error. Depending on the situation, several things can happen: The OAuth account exists in database and is linked to a user: OAuth account is updated in database with fresh access token. The user is authenticated following the chosen authentication method . The OAuth account doesn't exist in database but a user with the same email address exists: OAuth account is linked to the user. The user is authenticated following the chosen authentication method . The OAuth account doesn't exist in database and no user with the email address exists: A new user is created and linked to the OAuth account. The user is authenticated following the chosen authentication method . 400 Bad Request Invalid token. 400 Bad Request User is inactive. { \"detail\" : \"LOGIN_BAD_CREDENTIALS\" }","title":"GET /callback"},{"location":"usage/routes/#users-router","text":"","title":"Users router"},{"location":"usage/routes/#get-me","text":"Return the current authenticated active user. 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 401 Unauthorized Missing token or inactive user.","title":"GET /me"},{"location":"usage/routes/#patch-me","text":"Update the current authenticated active user. Payload { \"email\" : \"king.arthur@tintagel.bt\" , \"password\" : \"merlin\" } 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@tintagel.bt\" , \"is_active\" : true , \"is_superuser\" : false } 401 Unauthorized Missing token or inactive user. 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"UPDATE_USER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } } 400 Bad Request A user with this email already exists. { \"detail\" : \"UPDATE_USER_EMAIL_ALREADY_EXISTS\" } 422 Validation Error","title":"PATCH /me"},{"location":"usage/routes/#get-user_id","text":"Return the user with id user_id . 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 401 Unauthorized Missing token or inactive user. 403 Forbidden Not a superuser. 404 Not found The user does not exist.","title":"GET /{user_id}"},{"location":"usage/routes/#patch-user_id","text":"Update the user with id user_id . Payload { \"email\" : \"king.arthur@tintagel.bt\" , \"password\" : \"merlin\" , \"is_active\" : false , \"is_superuser\" : true } 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : false , \"is_superuser\" : true } 401 Unauthorized Missing token or inactive user. 403 Forbidden Not a superuser. 404 Not found The user does not exist. 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"UPDATE_USER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } } 400 Bad Request A user with this email already exists. { \"detail\" : \"UPDATE_USER_EMAIL_ALREADY_EXISTS\" }","title":"PATCH /{user_id}"},{"location":"usage/routes/#delete-user_id","text":"Delete the user with id user_id . 204 No content 401 Unauthorized Missing token or inactive user. 403 Forbidden Not a superuser. 404 Not found The user does not exist.","title":"DELETE /{user_id}"}]} \ No newline at end of file +{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"FastAPI Users \u00b6 Ready-to-use and customizable users management for FastAPI Documentation : https://fastapi-users.github.io/fastapi-users/ Source Code : https://github.com/fastapi-users/fastapi-users Add quickly a registration and authentication system to your FastAPI project. FastAPI Users is designed to be as customizable and adaptable as possible. Features \u00b6 Extensible base user model Ready-to-use register, login, reset password and verify e-mail routes Ready-to-use social OAuth2 login flow Dependency callables to inject current user in route Pluggable password validation Customizable database backend SQLAlchemy ORM async backend included MongoDB async backend included thanks to mongodb/motor Tortoise ORM backend included ormar backend included Multiple customizable authentication backends Transports: Authorization header, Cookie Strategies: JWT, Database, Redis Full OpenAPI schema support, even with several authentication backends \ud83d\udcda Discover my book: Building Data Science Applications with FastAPI \u00b6 Develop, manage, and deploy efficient machine learning applications with Python What is this book about? \u00b6 This book covers the following exciting features: Explore the basics of modern Python and async I/O programming Get to grips with basic and advanced concepts of the FastAPI framework Implement a FastAPI dependency to efficiently run a machine learning model Integrate a simple face detection algorithm in a FastAPI backend Integrate common Python data science libraries in a web backend Deploy a performant and reliable web backend for a data science application If you feel this book is for you, get your copy today! Contributors and sponsors \u2728\u2615\ufe0f \u00b6 Thanks goes to these wonderful people ( emoji key ): Fran\u00e7ois Voron \ud83d\udea7 Paolo Dina \ud83d\udcb5 \ud83d\udcbb Dmytro Ohorodnik \ud83d\udc1b Matthew D. Scholefield \ud83d\udc1b roywes \ud83d\udc1b \ud83d\udcbb Satwik Kansal \ud83d\udcd6 Edd Salkield \ud83d\udcbb \ud83d\udcd6 mark-todd \ud83d\udcbb \ud83d\udcd6 lill74 \ud83d\udc1b \ud83d\udcbb \ud83d\udcd6 SelfhostedPro \ud83d\udee1\ufe0f \ud83d\udcbb Oskar Gmerek \ud83d\udcd6 Martin Collado \ud83d\udc1b \ud83d\udcbb Eric Lopes \ud83d\udcd6 \ud83d\udee1\ufe0f Beau Breon \ud83d\udcbb Niyas Mohammed \ud83d\udcd6 prostomarkeloff \ud83d\udcd6 \ud83d\udcbb Marius M\u00e9zerette \ud83d\udc1b \ud83e\udd14 Nickolas Grigoriadis \ud83d\udc1b Open Data Coder \ud83e\udd14 Mohammed Alshehri \ud83e\udd14 Tyler Renelle \ud83e\udd14 collerek \ud83d\udcbb Robert Bracco \ud83d\udcb5 Augusto Herrmann \ud83d\udcd6 Smithybrewer \ud83d\udc1b silllli \ud83d\udcd6 alexferrari88 \ud83d\udcb5 sandalwoodbox \ud83d\udc1b Vlad Hoi \ud83d\udcd6 Joe Nudell \ud83d\udc1b Ben \ud83d\udcbb BoYanZh \ud83d\udcd6 David Brochart \ud83d\udcd6 \ud83d\udcbb Daan Beverdam \ud83d\udcbb St\u00e9phane Raimbault \u26a0\ufe0f \ud83d\udc1b Sondre Lilleb\u00f8 Gundersen \ud83d\udcd6 Maxim \ud83d\udcd6 \ud83d\udc1b scottdavort \ud83d\udcb5 John Dukewich \ud83d\udcd6 Yasser Tahiri \ud83d\udcbb Brandon H. Goding \ud83d\udcbb PovilasK \ud83d\udcbb Just van den Broecke \ud83d\udcb5 jakemanger \ud83d\udc1b \ud83d\udcbb Ikko Ashimine \ud83d\udcbb Maty\u00e1\u0161 Richter \ud83d\udcbb Hazedd \ud83d\udc1b \ud83d\udcd6 Luis Roel \ud83d\udcb5 This project follows the all-contributors specification. Contributions of any kind welcome! Development \u00b6 Setup environment \u00b6 You should create a virtual environment and activate it: python -m venv venv/ source venv/bin/activate And then install the development dependencies: pip install -r requirements.dev.txt Run unit tests \u00b6 You can run all the tests with: make test The command will start a MongoDB container for the related unit tests. So you should have Docker installed. Alternatively, you can run pytest yourself. The MongoDB unit tests will be skipped if no server is available on your local machine: pytest There are quite a few unit tests, so you might run into ulimit issues where there are too many open file descriptors. You may be able to set a new, higher limit temporarily with: ulimit -n 2048 Format the code \u00b6 Execute the following command to apply isort and black formatting: make format License \u00b6 This project is licensed under the terms of the MIT license.","title":"About"},{"location":"#fastapi-users","text":"Ready-to-use and customizable users management for FastAPI Documentation : https://fastapi-users.github.io/fastapi-users/ Source Code : https://github.com/fastapi-users/fastapi-users Add quickly a registration and authentication system to your FastAPI project. FastAPI Users is designed to be as customizable and adaptable as possible.","title":"FastAPI Users"},{"location":"#features","text":"Extensible base user model Ready-to-use register, login, reset password and verify e-mail routes Ready-to-use social OAuth2 login flow Dependency callables to inject current user in route Pluggable password validation Customizable database backend SQLAlchemy ORM async backend included MongoDB async backend included thanks to mongodb/motor Tortoise ORM backend included ormar backend included Multiple customizable authentication backends Transports: Authorization header, Cookie Strategies: JWT, Database, Redis Full OpenAPI schema support, even with several authentication backends","title":"Features"},{"location":"#discover-my-book-building-data-science-applications-with-fastapi","text":"Develop, manage, and deploy efficient machine learning applications with Python","title":"\ud83d\udcda Discover my book: Building Data Science Applications with FastAPI"},{"location":"#what-is-this-book-about","text":"This book covers the following exciting features: Explore the basics of modern Python and async I/O programming Get to grips with basic and advanced concepts of the FastAPI framework Implement a FastAPI dependency to efficiently run a machine learning model Integrate a simple face detection algorithm in a FastAPI backend Integrate common Python data science libraries in a web backend Deploy a performant and reliable web backend for a data science application If you feel this book is for you, get your copy today!","title":"What is this book about?"},{"location":"#contributors-and-sponsors","text":"Thanks goes to these wonderful people ( emoji key ): Fran\u00e7ois Voron \ud83d\udea7 Paolo Dina \ud83d\udcb5 \ud83d\udcbb Dmytro Ohorodnik \ud83d\udc1b Matthew D. Scholefield \ud83d\udc1b roywes \ud83d\udc1b \ud83d\udcbb Satwik Kansal \ud83d\udcd6 Edd Salkield \ud83d\udcbb \ud83d\udcd6 mark-todd \ud83d\udcbb \ud83d\udcd6 lill74 \ud83d\udc1b \ud83d\udcbb \ud83d\udcd6 SelfhostedPro \ud83d\udee1\ufe0f \ud83d\udcbb Oskar Gmerek \ud83d\udcd6 Martin Collado \ud83d\udc1b \ud83d\udcbb Eric Lopes \ud83d\udcd6 \ud83d\udee1\ufe0f Beau Breon \ud83d\udcbb Niyas Mohammed \ud83d\udcd6 prostomarkeloff \ud83d\udcd6 \ud83d\udcbb Marius M\u00e9zerette \ud83d\udc1b \ud83e\udd14 Nickolas Grigoriadis \ud83d\udc1b Open Data Coder \ud83e\udd14 Mohammed Alshehri \ud83e\udd14 Tyler Renelle \ud83e\udd14 collerek \ud83d\udcbb Robert Bracco \ud83d\udcb5 Augusto Herrmann \ud83d\udcd6 Smithybrewer \ud83d\udc1b silllli \ud83d\udcd6 alexferrari88 \ud83d\udcb5 sandalwoodbox \ud83d\udc1b Vlad Hoi \ud83d\udcd6 Joe Nudell \ud83d\udc1b Ben \ud83d\udcbb BoYanZh \ud83d\udcd6 David Brochart \ud83d\udcd6 \ud83d\udcbb Daan Beverdam \ud83d\udcbb St\u00e9phane Raimbault \u26a0\ufe0f \ud83d\udc1b Sondre Lilleb\u00f8 Gundersen \ud83d\udcd6 Maxim \ud83d\udcd6 \ud83d\udc1b scottdavort \ud83d\udcb5 John Dukewich \ud83d\udcd6 Yasser Tahiri \ud83d\udcbb Brandon H. Goding \ud83d\udcbb PovilasK \ud83d\udcbb Just van den Broecke \ud83d\udcb5 jakemanger \ud83d\udc1b \ud83d\udcbb Ikko Ashimine \ud83d\udcbb Maty\u00e1\u0161 Richter \ud83d\udcbb Hazedd \ud83d\udc1b \ud83d\udcd6 Luis Roel \ud83d\udcb5 This project follows the all-contributors specification. Contributions of any kind welcome!","title":"Contributors and sponsors \u2728\u2615\ufe0f"},{"location":"#development","text":"","title":"Development"},{"location":"#setup-environment","text":"You should create a virtual environment and activate it: python -m venv venv/ source venv/bin/activate And then install the development dependencies: pip install -r requirements.dev.txt","title":"Setup environment"},{"location":"#run-unit-tests","text":"You can run all the tests with: make test The command will start a MongoDB container for the related unit tests. So you should have Docker installed. Alternatively, you can run pytest yourself. The MongoDB unit tests will be skipped if no server is available on your local machine: pytest There are quite a few unit tests, so you might run into ulimit issues where there are too many open file descriptors. You may be able to set a new, higher limit temporarily with: ulimit -n 2048","title":"Run unit tests"},{"location":"#format-the-code","text":"Execute the following command to apply isort and black formatting: make format","title":"Format the code"},{"location":"#license","text":"This project is licensed under the terms of the MIT license.","title":"License"},{"location":"installation/","text":"Installation \u00b6 You can add FastAPI Users to your FastAPI project in a few easy steps. First of all, install the dependency: With SQLAlchemy support \u00b6 pip install 'fastapi-users[sqlalchemy2]' With MongoDB support \u00b6 pip install 'fastapi-users[mongodb]' With Tortoise ORM support \u00b6 pip install 'fastapi-users[tortoise-orm]' With ormar support \u00b6 pip install 'fastapi-users[ormar]' That's it! Now, let's have a look at our User model .","title":"Installation"},{"location":"installation/#installation","text":"You can add FastAPI Users to your FastAPI project in a few easy steps. First of all, install the dependency:","title":"Installation"},{"location":"installation/#with-sqlalchemy-support","text":"pip install 'fastapi-users[sqlalchemy2]'","title":"With SQLAlchemy support"},{"location":"installation/#with-mongodb-support","text":"pip install 'fastapi-users[mongodb]'","title":"With MongoDB support"},{"location":"installation/#with-tortoise-orm-support","text":"pip install 'fastapi-users[tortoise-orm]'","title":"With Tortoise ORM support"},{"location":"installation/#with-ormar-support","text":"pip install 'fastapi-users[ormar]' That's it! Now, let's have a look at our User model .","title":"With ormar support"},{"location":"configuration/full-example/","text":"Full example \u00b6 Here is a full working example with JWT authentication to help get you started. Warning Notice that SECRET should be changed to a strong passphrase. Insecure passwords may give attackers full access to your database. SQLAlchemy \u00b6 Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[sqlalchemy] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import auth_backend , current_active_user , fastapi_users app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from app.models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import SQLAlchemyUserDatabase from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : SQLAlchemyUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True ) MongoDB \u00b6 Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[mongodb] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import auth_backend , current_active_user , fastapi_users app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } import os import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from app.models import UserDB DATABASE_URL = os . environ [ \"DATABASE_URL\" ] client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import MongoDBUserDatabase from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : MongoDBUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True ) Tortoise ORM \u00b6 Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[tortoise-orm] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from tortoise.contrib.fastapi import register_tortoise from app.db import DATABASE_URL from app.models import UserDB from app.users import auth_backend , current_active_user , fastapi_users app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"app.models\" ]}, generate_schemas = True , ) from fastapi_users.db import TortoiseUserDatabase from app.models import UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel ) from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import TortoiseUserDatabase from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : TortoiseUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True ) What now? \u00b6 You're ready to go! Be sure to check the Usage section to understand how to work with FastAPI Users .","title":"Full example"},{"location":"configuration/full-example/#full-example","text":"Here is a full working example with JWT authentication to help get you started. Warning Notice that SECRET should be changed to a strong passphrase. Insecure passwords may give attackers full access to your database.","title":"Full example"},{"location":"configuration/full-example/#sqlalchemy","text":"Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[sqlalchemy] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import auth_backend , current_active_user , fastapi_users app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from app.models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import SQLAlchemyUserDatabase from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : SQLAlchemyUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"SQLAlchemy"},{"location":"configuration/full-example/#mongodb","text":"Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[mongodb] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import auth_backend , current_active_user , fastapi_users app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } import os import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from app.models import UserDB DATABASE_URL = os . environ [ \"DATABASE_URL\" ] client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import MongoDBUserDatabase from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : MongoDBUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"MongoDB"},{"location":"configuration/full-example/#tortoise-orm","text":"Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[tortoise-orm] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from tortoise.contrib.fastapi import register_tortoise from app.db import DATABASE_URL from app.models import UserDB from app.users import auth_backend , current_active_user , fastapi_users app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"app.models\" ]}, generate_schemas = True , ) from fastapi_users.db import TortoiseUserDatabase from app.models import UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel ) from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import TortoiseUserDatabase from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : TortoiseUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"Tortoise ORM"},{"location":"configuration/full-example/#what-now","text":"You're ready to go! Be sure to check the Usage section to understand how to work with FastAPI Users .","title":"What now?"},{"location":"configuration/models/","text":"Models \u00b6 FastAPI Users defines a minimal User model for authentication purposes. It is structured like this: id ( UUID4 ) \u2013 Unique identifier of the user. Defaults to a UUID4 . email ( str ) \u2013 Email of the user. Validated by email-validator . is_active ( bool ) \u2013 Whether or not the user is active. If not, login and forgot password requests will be denied. Defaults to True . is_verified ( bool ) \u2013 Whether or not the user is verified. Optional but helpful with the verify router logic. Defaults to False . is_superuser ( bool ) \u2013 Whether or not the user is a superuser. Useful to implement administration logic. Defaults to False . Define your models \u00b6 There are four Pydantic models variations provided as mixins: BaseUser , which provides the basic fields and validation ; BaseCreateUser , dedicated to user registration, which consists of compulsory email and password fields ; BaseUpdateUser , dedicated to user profile update, which adds an optional password field ; BaseUserDB , which is a representation of the user in database, adding a hashed_password field. You should define each of those variations, inheriting from each mixin: from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass Adding your own fields \u00b6 You can of course add your own properties there to fit to your needs. In the example below, we add a required string property, first_name , and an optional date property, birthdate . import datetime from fastapi_users import models class User ( models . BaseUser ): first_name : str birthdate : Optional [ datetime . date ] class UserCreate ( models . BaseUserCreate ): first_name : str birthdate : Optional [ datetime . date ] class UserUpdate ( models . BaseUserUpdate ): first_name : Optional [ str ] birthdate : Optional [ datetime . date ] class UserDB ( User , models . BaseUserDB ): pass","title":"Models"},{"location":"configuration/models/#models","text":"FastAPI Users defines a minimal User model for authentication purposes. It is structured like this: id ( UUID4 ) \u2013 Unique identifier of the user. Defaults to a UUID4 . email ( str ) \u2013 Email of the user. Validated by email-validator . is_active ( bool ) \u2013 Whether or not the user is active. If not, login and forgot password requests will be denied. Defaults to True . is_verified ( bool ) \u2013 Whether or not the user is verified. Optional but helpful with the verify router logic. Defaults to False . is_superuser ( bool ) \u2013 Whether or not the user is a superuser. Useful to implement administration logic. Defaults to False .","title":"Models"},{"location":"configuration/models/#define-your-models","text":"There are four Pydantic models variations provided as mixins: BaseUser , which provides the basic fields and validation ; BaseCreateUser , dedicated to user registration, which consists of compulsory email and password fields ; BaseUpdateUser , dedicated to user profile update, which adds an optional password field ; BaseUserDB , which is a representation of the user in database, adding a hashed_password field. You should define each of those variations, inheriting from each mixin: from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass","title":"Define your models"},{"location":"configuration/models/#adding-your-own-fields","text":"You can of course add your own properties there to fit to your needs. In the example below, we add a required string property, first_name , and an optional date property, birthdate . import datetime from fastapi_users import models class User ( models . BaseUser ): first_name : str birthdate : Optional [ datetime . date ] class UserCreate ( models . BaseUserCreate ): first_name : str birthdate : Optional [ datetime . date ] class UserUpdate ( models . BaseUserUpdate ): first_name : Optional [ str ] birthdate : Optional [ datetime . date ] class UserDB ( User , models . BaseUserDB ): pass","title":"Adding your own fields"},{"location":"configuration/oauth/","text":"OAuth2 \u00b6 FastAPI Users provides an optional OAuth2 authentication support. It relies on HTTPX OAuth library , which is a pure-async implementation of OAuth2. Installation \u00b6 You should install the library with the optional dependencies for OAuth: pip install 'fastapi-users[sqlalchemy2,oauth]' pip install 'fastapi-users[mongodb,oauth]' pip install 'fastapi-users[tortoise-orm,oauth]' Configuration \u00b6 Instantiate an OAuth2 client \u00b6 You first need to get an HTTPX OAuth client instance. Read the documentation for more information. from httpx_oauth.clients.google import GoogleOAuth2 google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) Setup the models \u00b6 The user models differ a bit from the standard one as we have to have a way to store the OAuth information (access tokens, account ids...). from fastapi_users import models class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass Notice that we inherit from the BaseOAuthAccountMixin , which adds a List of BaseOAuthAccount objects. This object is structured like this: id ( UUID4 ) \u2013 Unique identifier of the OAuth account information. Defaults to a UUID4 . oauth_name ( str ) \u2013 Name of the OAuth service. It corresponds to the name property of the OAuth client. access_token ( str ) \u2013 Access token. expires_at ( Optional[int] ) - Timestamp at which the access token is expired. refresh_token ( Optional[str] ) \u2013 On services that support it, a token to get a fresh access token. account_id ( str ) - Identifier of the OAuth account on the corresponding service. account_email ( str ) - Email address of the OAuth account on the corresponding service. Setup the database adapter \u00b6 SQLAlchemy \u00b6 You'll need to define the SQLAlchemy model for storing OAuth accounts. We provide a base one for this: from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import relationship , sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): oauth_accounts = relationship ( \"OAuthAccountTable\" ) class OAuthAccountTable ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable , OAuthAccountTable ) Notice that we also manually added a relationship on the UserTable so that SQLAlchemy can properly retrieve the OAuth accounts of the user. When instantiating the database adapter, you should pass this SQLAlchemy model: from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import relationship , sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): oauth_accounts = relationship ( \"OAuthAccountTable\" ) class OAuthAccountTable ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable , OAuthAccountTable ) MongoDB \u00b6 Nothing to do, the basic configuration is enough. Tortoise ORM \u00b6 You'll need to define the Tortoise model for storing the OAuth account model. We provide a base one for this: from fastapi_users import models from fastapi_users.db import TortoiseBaseOAuthAccountModel , TortoiseBaseUserModel from tortoise import fields from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel class OAuthAccount ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"oauth_accounts\" ) Warning Note that you should define the foreign key yourself, so that you can point it the user model in your namespace. Then, you should declare it on the database adapter: from fastapi_users.db import TortoiseUserDatabase from .models import OAuthAccount , UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel , OAuthAccount ) Generate a router \u00b6 Once you have a FastAPIUsers instance, you can make it generate a single OAuth router for a given client and authentication backend. app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) Full example \u00b6 Warning Notice that SECRET should be changed to a strong passphrase. Insecure passwords may give attackers full access to your database. SQLAlchemy \u00b6 Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[sqlalchemy,oauth] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import ( auth_backend , current_active_user , fastapi_users , google_oauth_client , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import relationship , sessionmaker from app.models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): oauth_accounts = relationship ( \"OAuthAccount\" ) class OAuthAccountTable ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable , OAuthAccountTable ) from fastapi_users import models class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass import os from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import SQLAlchemyUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( os . environ [ \"GOOGLE_OAUTH_CLIENT_ID\" ], os . environ [ \"GOOGLE_OAUTH_CLIENT_SECRET\" ], ) class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : SQLAlchemyUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True ) MongoDB \u00b6 Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[mongodb,oauth] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import ( auth_backend , current_active_user , fastapi_users , google_oauth_client , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } import os import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from app.models import UserDB DATABASE_URL = os . environ [ \"DATABASE_URL\" ] client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass import os from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import MongoDBUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( os . environ [ \"GOOGLE_OAUTH_CLIENT_ID\" ], os . environ [ \"GOOGLE_OAUTH_CLIENT_SECRET\" ], ) class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : MongoDBUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True ) Tortoise ORM \u00b6 Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[tortoise-orm,oauth] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from tortoise.contrib.fastapi import register_tortoise from app.db import DATABASE_URL from app.models import UserDB from app.users import ( auth_backend , current_active_user , fastapi_users , google_oauth_client , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"app.models\" ]}, generate_schemas = True , ) from fastapi_users.db import TortoiseUserDatabase from app.models import OAuthAccount , UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel , OAuthAccount ) from fastapi_users import models from fastapi_users.db import TortoiseBaseOAuthAccountModel , TortoiseBaseUserModel from tortoise import fields from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel class OAuthAccount ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"oauth_accounts\" ) import os from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import TortoiseUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( os . environ [ \"GOOGLE_OAUTH_CLIENT_ID\" ], os . environ [ \"GOOGLE_OAUTH_CLIENT_SECRET\" ], ) class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : TortoiseUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"OAuth2"},{"location":"configuration/oauth/#oauth2","text":"FastAPI Users provides an optional OAuth2 authentication support. It relies on HTTPX OAuth library , which is a pure-async implementation of OAuth2.","title":"OAuth2"},{"location":"configuration/oauth/#installation","text":"You should install the library with the optional dependencies for OAuth: pip install 'fastapi-users[sqlalchemy2,oauth]' pip install 'fastapi-users[mongodb,oauth]' pip install 'fastapi-users[tortoise-orm,oauth]'","title":"Installation"},{"location":"configuration/oauth/#configuration","text":"","title":"Configuration"},{"location":"configuration/oauth/#instantiate-an-oauth2-client","text":"You first need to get an HTTPX OAuth client instance. Read the documentation for more information. from httpx_oauth.clients.google import GoogleOAuth2 google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" )","title":"Instantiate an OAuth2 client"},{"location":"configuration/oauth/#setup-the-models","text":"The user models differ a bit from the standard one as we have to have a way to store the OAuth information (access tokens, account ids...). from fastapi_users import models class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass Notice that we inherit from the BaseOAuthAccountMixin , which adds a List of BaseOAuthAccount objects. This object is structured like this: id ( UUID4 ) \u2013 Unique identifier of the OAuth account information. Defaults to a UUID4 . oauth_name ( str ) \u2013 Name of the OAuth service. It corresponds to the name property of the OAuth client. access_token ( str ) \u2013 Access token. expires_at ( Optional[int] ) - Timestamp at which the access token is expired. refresh_token ( Optional[str] ) \u2013 On services that support it, a token to get a fresh access token. account_id ( str ) - Identifier of the OAuth account on the corresponding service. account_email ( str ) - Email address of the OAuth account on the corresponding service.","title":"Setup the models"},{"location":"configuration/oauth/#setup-the-database-adapter","text":"","title":"Setup the database adapter"},{"location":"configuration/oauth/#sqlalchemy","text":"You'll need to define the SQLAlchemy model for storing OAuth accounts. We provide a base one for this: from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import relationship , sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): oauth_accounts = relationship ( \"OAuthAccountTable\" ) class OAuthAccountTable ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable , OAuthAccountTable ) Notice that we also manually added a relationship on the UserTable so that SQLAlchemy can properly retrieve the OAuth accounts of the user. When instantiating the database adapter, you should pass this SQLAlchemy model: from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import relationship , sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): oauth_accounts = relationship ( \"OAuthAccountTable\" ) class OAuthAccountTable ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable , OAuthAccountTable )","title":"SQLAlchemy"},{"location":"configuration/oauth/#mongodb","text":"Nothing to do, the basic configuration is enough.","title":"MongoDB"},{"location":"configuration/oauth/#tortoise-orm","text":"You'll need to define the Tortoise model for storing the OAuth account model. We provide a base one for this: from fastapi_users import models from fastapi_users.db import TortoiseBaseOAuthAccountModel , TortoiseBaseUserModel from tortoise import fields from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel class OAuthAccount ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"oauth_accounts\" ) Warning Note that you should define the foreign key yourself, so that you can point it the user model in your namespace. Then, you should declare it on the database adapter: from fastapi_users.db import TortoiseUserDatabase from .models import OAuthAccount , UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel , OAuthAccount )","title":"Tortoise ORM"},{"location":"configuration/oauth/#generate-a-router","text":"Once you have a FastAPIUsers instance, you can make it generate a single OAuth router for a given client and authentication backend. app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], )","title":"Generate a router"},{"location":"configuration/oauth/#full-example","text":"Warning Notice that SECRET should be changed to a strong passphrase. Insecure passwords may give attackers full access to your database.","title":"Full example"},{"location":"configuration/oauth/#sqlalchemy_1","text":"Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[sqlalchemy,oauth] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import ( auth_backend , current_active_user , fastapi_users , google_oauth_client , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import relationship , sessionmaker from app.models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): oauth_accounts = relationship ( \"OAuthAccount\" ) class OAuthAccountTable ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable , OAuthAccountTable ) from fastapi_users import models class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass import os from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import SQLAlchemyUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( os . environ [ \"GOOGLE_OAUTH_CLIENT_ID\" ], os . environ [ \"GOOGLE_OAUTH_CLIENT_SECRET\" ], ) class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : SQLAlchemyUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"SQLAlchemy"},{"location":"configuration/oauth/#mongodb_1","text":"Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[mongodb,oauth] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from app.models import UserDB from app.users import ( auth_backend , current_active_user , fastapi_users , google_oauth_client , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } import os import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from app.models import UserDB DATABASE_URL = os . environ [ \"DATABASE_URL\" ] client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) from fastapi_users import models class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass import os from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import MongoDBUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( os . environ [ \"GOOGLE_OAUTH_CLIENT_ID\" ], os . environ [ \"GOOGLE_OAUTH_CLIENT_SECRET\" ], ) class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : MongoDBUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"MongoDB"},{"location":"configuration/oauth/#tortoise-orm_1","text":"Open requirements.txt main.py app/app.py app/db.py app/models.py app/users.py fastapi fastapi-users[tortoise-orm,oauth] uvicorn[standard] import uvicorn if __name__ == \"__main__\" : uvicorn . run ( \"app.app:app\" , host = \"0.0.0.0\" , port = 5000 , log_level = \"info\" ) from fastapi import Depends , FastAPI from tortoise.contrib.fastapi import register_tortoise from app.db import DATABASE_URL from app.models import UserDB from app.users import ( auth_backend , current_active_user , fastapi_users , google_oauth_client , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ]) app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) @app . get ( \"/authenticated-route\" ) async def authenticated_route ( user : UserDB = Depends ( current_active_user )): return { \"message\" : f \"Hello { user . email } !\" } register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"app.models\" ]}, generate_schemas = True , ) from fastapi_users.db import TortoiseUserDatabase from app.models import OAuthAccount , UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel , OAuthAccount ) from fastapi_users import models from fastapi_users.db import TortoiseBaseOAuthAccountModel , TortoiseBaseUserModel from tortoise import fields from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel class OAuthAccount ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"oauth_accounts\" ) import os from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager , FastAPIUsers from fastapi_users.authentication import ( AuthenticationBackend , BearerTransport , JWTStrategy , ) from fastapi_users.db import TortoiseUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 from app.db import get_user_db from app.models import User , UserCreate , UserDB , UserUpdate SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( os . environ [ \"GOOGLE_OAUTH_CLIENT_ID\" ], os . environ [ \"GOOGLE_OAUTH_CLIENT_SECRET\" ], ) class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db : TortoiseUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) current_active_user = fastapi_users . current_user ( active = True )","title":"Tortoise ORM"},{"location":"configuration/overview/","text":"Overview \u00b6 The schema below shows you how the library is structured and how each part fit together. flowchart LR FASTAPI_USERS{FastAPIUsers} USER_MANAGER{UserManager} DATABASE_DEPENDENCY[[get_user_db]] USER_MANAGER_DEPENDENCY[[get_user_manager]] CURRENT_USER[[current_user]] subgraph MODELS[Models] direction RL USER[User] USER_CREATE[UserCreate] USER_UPDATE[UserUpdate] USER_DB[UserDB] end subgraph DATABASE[Database adapters] direction RL SQLALCHEMY[SQLAlchemy] MONGODB[MongoDB] TORTOISE[Tortoise ORM] ORMAR[Ormar] end subgraph ROUTERS[Routers] direction RL AUTH[[get_auth_router]] OAUTH[[get_oauth_router]] REGISTER[[get_register_router]] VERIFY[[get_verify_router]] RESET[[get_reset_password_router]] USERS[[get_users_router]] end subgraph AUTH_BACKENDS[Authentication] direction RL subgraph TRANSPORTS[Transports] direction RL COOKIE[CookieTransport] BEARER[BearerTransport] end subgraph STRATEGIES[Strategies] direction RL JWT[JWTStrategy] end AUTH_BACKEND{AuthenticationBackend} end DATABASE --> DATABASE_DEPENDENCY DATABASE_DEPENDENCY --> USER_MANAGER MODELS --> USER_MANAGER MODELS --> FASTAPI_USERS USER_MANAGER --> USER_MANAGER_DEPENDENCY USER_MANAGER_DEPENDENCY --> FASTAPI_USERS FASTAPI_USERS --> ROUTERS TRANSPORTS --> AUTH_BACKEND STRATEGIES --> AUTH_BACKEND AUTH_BACKEND --> AUTH AUTH_BACKEND --> OAUTH AUTH_BACKEND --> FASTAPI_USERS FASTAPI_USERS --> CURRENT_USER Models \u00b6 Pydantic models representing the data structure of a user. Base classes are provided with the required fields to make authentication work. You should sub-class each of them and add your own fields there. \u27a1\ufe0f Configure the models Database adapters \u00b6 FastAPI Users is compatible with various databases and ORM. To build the interface between those database tools and the library, we provide database adapters classes that you need to instantiate and configure. \u27a1\ufe0f I'm using SQLAlchemy \u27a1\ufe0f I'm using MongoDB \u27a1\ufe0f I'm using Tortoise ORM \u27a1\ufe0f I'm using ormar Authentication backends \u00b6 Authentication backends define the way users sessions are managed in your app, like access tokens or cookies. They are composed of two parts: a transport , which is how the token will be carried over the requests (e.g. cookies, headers...) and a strategy , which is how the token will be generated and secured (e.g. a JWT, a token in database...). \u27a1\ufe0f Configure the authentication backends UserManager \u00b6 The UserManager object bears most of the logic of FastAPI Users: registration, verification, password reset... We provide a BaseUserManager with this common logic; which you should overload to define how to validate passwords or handle events. This UserManager object should be provided through a FastAPI dependency, get_user_manager . \u27a1\ufe0f Configure UserManager FastAPIUsers and routers \u00b6 Finally, FastAPIUsers object is the main class from which you'll be able to generate routers for classic routes like registration or login, but also get the current_user dependency factory to inject the authenticated user in your own routes. \u27a1\ufe0f Configure FastAPIUsers and routers","title":"Overview"},{"location":"configuration/overview/#overview","text":"The schema below shows you how the library is structured and how each part fit together. flowchart LR FASTAPI_USERS{FastAPIUsers} USER_MANAGER{UserManager} DATABASE_DEPENDENCY[[get_user_db]] USER_MANAGER_DEPENDENCY[[get_user_manager]] CURRENT_USER[[current_user]] subgraph MODELS[Models] direction RL USER[User] USER_CREATE[UserCreate] USER_UPDATE[UserUpdate] USER_DB[UserDB] end subgraph DATABASE[Database adapters] direction RL SQLALCHEMY[SQLAlchemy] MONGODB[MongoDB] TORTOISE[Tortoise ORM] ORMAR[Ormar] end subgraph ROUTERS[Routers] direction RL AUTH[[get_auth_router]] OAUTH[[get_oauth_router]] REGISTER[[get_register_router]] VERIFY[[get_verify_router]] RESET[[get_reset_password_router]] USERS[[get_users_router]] end subgraph AUTH_BACKENDS[Authentication] direction RL subgraph TRANSPORTS[Transports] direction RL COOKIE[CookieTransport] BEARER[BearerTransport] end subgraph STRATEGIES[Strategies] direction RL JWT[JWTStrategy] end AUTH_BACKEND{AuthenticationBackend} end DATABASE --> DATABASE_DEPENDENCY DATABASE_DEPENDENCY --> USER_MANAGER MODELS --> USER_MANAGER MODELS --> FASTAPI_USERS USER_MANAGER --> USER_MANAGER_DEPENDENCY USER_MANAGER_DEPENDENCY --> FASTAPI_USERS FASTAPI_USERS --> ROUTERS TRANSPORTS --> AUTH_BACKEND STRATEGIES --> AUTH_BACKEND AUTH_BACKEND --> AUTH AUTH_BACKEND --> OAUTH AUTH_BACKEND --> FASTAPI_USERS FASTAPI_USERS --> CURRENT_USER","title":"Overview"},{"location":"configuration/overview/#models","text":"Pydantic models representing the data structure of a user. Base classes are provided with the required fields to make authentication work. You should sub-class each of them and add your own fields there. \u27a1\ufe0f Configure the models","title":"Models"},{"location":"configuration/overview/#database-adapters","text":"FastAPI Users is compatible with various databases and ORM. To build the interface between those database tools and the library, we provide database adapters classes that you need to instantiate and configure. \u27a1\ufe0f I'm using SQLAlchemy \u27a1\ufe0f I'm using MongoDB \u27a1\ufe0f I'm using Tortoise ORM \u27a1\ufe0f I'm using ormar","title":"Database adapters"},{"location":"configuration/overview/#authentication-backends","text":"Authentication backends define the way users sessions are managed in your app, like access tokens or cookies. They are composed of two parts: a transport , which is how the token will be carried over the requests (e.g. cookies, headers...) and a strategy , which is how the token will be generated and secured (e.g. a JWT, a token in database...). \u27a1\ufe0f Configure the authentication backends","title":"Authentication backends"},{"location":"configuration/overview/#usermanager","text":"The UserManager object bears most of the logic of FastAPI Users: registration, verification, password reset... We provide a BaseUserManager with this common logic; which you should overload to define how to validate passwords or handle events. This UserManager object should be provided through a FastAPI dependency, get_user_manager . \u27a1\ufe0f Configure UserManager","title":"UserManager"},{"location":"configuration/overview/#fastapiusers-and-routers","text":"Finally, FastAPIUsers object is the main class from which you'll be able to generate routers for classic routes like registration or login, but also get the current_user dependency factory to inject the authenticated user in your own routes. \u27a1\ufe0f Configure FastAPIUsers and routers","title":"FastAPIUsers and routers"},{"location":"configuration/user-manager/","text":"UserManager \u00b6 The UserManager class is the core logic of FastAPI Users. We provide the BaseUserManager class which you should extend to set some parameters and define logic, for example when a user just registered or forgot its password. It's designed to be easily extensible and customizable so that you can integrate less generic logic. Create your UserManager class \u00b6 You should define your own version of the UserManager class to set various parameters. from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager from .db import get_user_db from .models import UserCreate , UserDB SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db = Depends ( get_user_db )): yield UserManager ( user_db ) As you can see, you have to define here various attributes and methods. You can find the complete list of those below. Create get_user_manager dependency \u00b6 The UserManager class will be injected at runtime using a FastAPI dependency. This way, you can run it in a database session or swap it with a mock during testing. from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager from .db import get_user_db from .models import UserCreate , UserDB SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db = Depends ( get_user_db )): yield UserManager ( user_db ) Notice that we use the get_user_db dependency we defined earlier to inject the database instance. Customize attributes and methods \u00b6 Attributes \u00b6 user_db_model : Pydantic model of a DB representation of a user. reset_password_token_secret : Secret to encode reset password token. Use a strong passphrase and keep it secure. reset_password_token_lifetime_seconds : Lifetime of reset password token. Defaults to 3600. reset_password_token_audience : JWT audience of reset password token. Defaults to fastapi-users:reset . verification_token_secret : Secret to encode verification token. Use a strong passphrase and keep it secure. verification_token_lifetime_seconds : Lifetime of verification token. Defaults to 3600. verification_token_audience : JWT audience of verification token. Defaults to fastapi-users:verify . Methods \u00b6 validate_password \u00b6 Validate a password. Arguments password ( str ): the password to validate. user ( Union[UserCreate, User] ): user model which we are currently validating the password. Useful if you want to check that the password doesn't contain the name or the birthdate of the user for example. Output This function should return None if the password is valid or raise InvalidPasswordException if not. This exception expects an argument reason telling why the password is invalid. It'll be part of the error response. Example from fastapi_users import BaseUserManager , InvalidPasswordException class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def validate_password ( self , password : str , user : Union [ UserCreate , UserDB ], ) -> None : if len ( password ) < 8 : raise InvalidPasswordException ( reason = \"Password should be at least 8 characters\" ) if user . email in password : raise InvalidPasswordException ( reason = \"Password should not contain e-mail\" ) on_after_register \u00b6 Perform logic after successful user registration. Typically, you'll want to send a welcome e-mail or add it to your marketing analytics pipeline. Arguments user ( UserDB ): the registered user. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) on_after_update \u00b6 Perform logic after successful user update. It may be useful, for example, if you wish to update your user in a data analytics or customer success platform. Arguments user ( UserDB ): the updated user. update_dict ( Dict[str, Any] ): dictionary with the updated user fields. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_update ( self , user : UserDB , update_dict : Dict [ str , Any ], request : Optional [ Request ] = None , ): print ( f \"User { user . id } has been updated with { update_dict } .\" ) on_after_request_verify \u00b6 Perform logic after successful verification request. Typically, you'll want to send an e-mail with the link (and the token) that allows the user to verify their e-mail. Arguments user ( UserDB ): the user to verify. token ( str ): the verification token. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) on_after_verify \u00b6 Perform logic after successful user verification. This may be useful if you wish to send another e-mail or store this information in a data analytics or customer success platform. Arguments user ( UserDB ): the verified user. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_verify ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has been verified\" ) on_after_forgot_password \u00b6 Perform logic after successful forgot password request. Typically, you'll want to send an e-mail with the link (and the token) that allows the user to reset their password. Arguments user ( UserDB ): the user that forgot its password. token ( str ): the forgot password token request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) on_after_reset_password \u00b6 Perform logic after successful password reset. For example, you may want to send an e-mail to the concerned user to warn him that their password has been changed and that they should take action if they think they have been hacked. Arguments user ( UserDB ): the user that reset its password. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_reset_password ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has reset their password.\" )","title":"UserManager"},{"location":"configuration/user-manager/#usermanager","text":"The UserManager class is the core logic of FastAPI Users. We provide the BaseUserManager class which you should extend to set some parameters and define logic, for example when a user just registered or forgot its password. It's designed to be easily extensible and customizable so that you can integrate less generic logic.","title":"UserManager"},{"location":"configuration/user-manager/#create-your-usermanager-class","text":"You should define your own version of the UserManager class to set various parameters. from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager from .db import get_user_db from .models import UserCreate , UserDB SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db = Depends ( get_user_db )): yield UserManager ( user_db ) As you can see, you have to define here various attributes and methods. You can find the complete list of those below.","title":"Create your UserManager class"},{"location":"configuration/user-manager/#create-get_user_manager-dependency","text":"The UserManager class will be injected at runtime using a FastAPI dependency. This way, you can run it in a database session or swap it with a mock during testing. from typing import Optional from fastapi import Depends , Request from fastapi_users import BaseUserManager from .db import get_user_db from .models import UserCreate , UserDB SECRET = \"SECRET\" class UserManager ( BaseUserManager [ UserCreate , UserDB ]): user_db_model = UserDB reset_password_token_secret = SECRET verification_token_secret = SECRET async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" ) async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) async def get_user_manager ( user_db = Depends ( get_user_db )): yield UserManager ( user_db ) Notice that we use the get_user_db dependency we defined earlier to inject the database instance.","title":"Create get_user_manager dependency"},{"location":"configuration/user-manager/#customize-attributes-and-methods","text":"","title":"Customize attributes and methods"},{"location":"configuration/user-manager/#attributes","text":"user_db_model : Pydantic model of a DB representation of a user. reset_password_token_secret : Secret to encode reset password token. Use a strong passphrase and keep it secure. reset_password_token_lifetime_seconds : Lifetime of reset password token. Defaults to 3600. reset_password_token_audience : JWT audience of reset password token. Defaults to fastapi-users:reset . verification_token_secret : Secret to encode verification token. Use a strong passphrase and keep it secure. verification_token_lifetime_seconds : Lifetime of verification token. Defaults to 3600. verification_token_audience : JWT audience of verification token. Defaults to fastapi-users:verify .","title":"Attributes"},{"location":"configuration/user-manager/#methods","text":"","title":"Methods"},{"location":"configuration/user-manager/#validate_password","text":"Validate a password. Arguments password ( str ): the password to validate. user ( Union[UserCreate, User] ): user model which we are currently validating the password. Useful if you want to check that the password doesn't contain the name or the birthdate of the user for example. Output This function should return None if the password is valid or raise InvalidPasswordException if not. This exception expects an argument reason telling why the password is invalid. It'll be part of the error response. Example from fastapi_users import BaseUserManager , InvalidPasswordException class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def validate_password ( self , password : str , user : Union [ UserCreate , UserDB ], ) -> None : if len ( password ) < 8 : raise InvalidPasswordException ( reason = \"Password should be at least 8 characters\" ) if user . email in password : raise InvalidPasswordException ( reason = \"Password should not contain e-mail\" )","title":"validate_password"},{"location":"configuration/user-manager/#on_after_register","text":"Perform logic after successful user registration. Typically, you'll want to send a welcome e-mail or add it to your marketing analytics pipeline. Arguments user ( UserDB ): the registered user. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_register ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has registered.\" )","title":"on_after_register"},{"location":"configuration/user-manager/#on_after_update","text":"Perform logic after successful user update. It may be useful, for example, if you wish to update your user in a data analytics or customer success platform. Arguments user ( UserDB ): the updated user. update_dict ( Dict[str, Any] ): dictionary with the updated user fields. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_update ( self , user : UserDB , update_dict : Dict [ str , Any ], request : Optional [ Request ] = None , ): print ( f \"User { user . id } has been updated with { update_dict } .\" )","title":"on_after_update"},{"location":"configuration/user-manager/#on_after_request_verify","text":"Perform logic after successful verification request. Typically, you'll want to send an e-mail with the link (and the token) that allows the user to verify their e-mail. Arguments user ( UserDB ): the user to verify. token ( str ): the verification token. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_request_verify ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" )","title":"on_after_request_verify"},{"location":"configuration/user-manager/#on_after_verify","text":"Perform logic after successful user verification. This may be useful if you wish to send another e-mail or store this information in a data analytics or customer success platform. Arguments user ( UserDB ): the verified user. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_verify ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has been verified\" )","title":"on_after_verify"},{"location":"configuration/user-manager/#on_after_forgot_password","text":"Perform logic after successful forgot password request. Typically, you'll want to send an e-mail with the link (and the token) that allows the user to reset their password. Arguments user ( UserDB ): the user that forgot its password. token ( str ): the forgot password token request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_forgot_password ( self , user : UserDB , token : str , request : Optional [ Request ] = None ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" )","title":"on_after_forgot_password"},{"location":"configuration/user-manager/#on_after_reset_password","text":"Perform logic after successful password reset. For example, you may want to send an e-mail to the concerned user to warn him that their password has been changed and that they should take action if they think they have been hacked. Arguments user ( UserDB ): the user that reset its password. request ( Optional[Request] ): optional FastAPI request object that triggered the operation. Defaults to None. Example from fastapi_users import BaseUserManager class UserManager ( BaseUserManager [ UserCreate , UserDB ]): # ... async def on_after_reset_password ( self , user : UserDB , request : Optional [ Request ] = None ): print ( f \"User { user . id } has reset their password.\" )","title":"on_after_reset_password"},{"location":"configuration/authentication/","text":"Authentication \u00b6 FastAPI Users allows you to plug in several authentication methods. How it works? \u00b6 You can have several authentication methods, e.g. a cookie authentication for browser-based queries and a JWT token authentication for pure API queries. When checking authentication, each method is run one after the other. The first method yielding a user wins. If no method yields a user, an HTTPException is raised. For each backend, you'll be able to add a router with the corresponding /login and /logout . More on this in the routers documentation . Transport + Strategy = Authentication backend \u00b6 An authentication backend is composed of two parts: Transport \u00b6 It manages how the token will be carried over the request. We currently provide two methods: Bearer \u00b6 The token will be send through an Authorization: Bearer header. Pros and cons \u2705 Easy to read and set in every requests. \u274c Needs to be stored manually somewhere in the client. \u27a1\ufe0f Use it if you want to implement a mobile application or a pure REST API. Cookie \u00b6 The token will be send through a cookie. Pros and cons \u2705 Automatically stored and sent securely by web browsers in every requests. \u2705 Automatically removed at expiration by web browsers. \u274c Needs a CSRF protection for maximum security. \u274c Harder to work with outside a browser, like a mobile app or a server. \u27a1\ufe0f Use it if you want to implement a web frontend. Strategy \u00b6 It manages how the token is generated and secured. We currently provide two methods: JWT \u00b6 The token is self-contained in a JSON Web Token. Pros and cons \u2705 Self-contained: it doesn't need to be stored in a database. \u274c Can't be invalidated on the server-side: it's valid until it expires. \u27a1\ufe0f Use it if you want to get up-and-running quickly. Database \u00b6 The token is stored in a table (or collection) in your database. Pros and cons \u2705 Secure and performant. \u2705 Tokens can be invalidated server-side by removing them from the database. \u2705 Highly customizable: add your own fields, create an API to retrieve the active sessions of your users, etc. \u274c Configuration is a bit more complex. \u27a1\ufe0f Use it if you want maximum flexibility in your token management. Redis \u00b6 The token is stored in a Redis key-store. Pros and cons \u2705 Secure and performant. \u2705 Tokens can be invalidated server-side by removing them from Redis. \u274c A Redis server is needed. \u27a1\ufe0f Use it if you want maximum performance while being able to invalidate tokens.","title":"Introduction"},{"location":"configuration/authentication/#authentication","text":"FastAPI Users allows you to plug in several authentication methods.","title":"Authentication"},{"location":"configuration/authentication/#how-it-works","text":"You can have several authentication methods, e.g. a cookie authentication for browser-based queries and a JWT token authentication for pure API queries. When checking authentication, each method is run one after the other. The first method yielding a user wins. If no method yields a user, an HTTPException is raised. For each backend, you'll be able to add a router with the corresponding /login and /logout . More on this in the routers documentation .","title":"How it works?"},{"location":"configuration/authentication/#transport-strategy-authentication-backend","text":"An authentication backend is composed of two parts:","title":"Transport + Strategy = Authentication backend"},{"location":"configuration/authentication/#transport","text":"It manages how the token will be carried over the request. We currently provide two methods:","title":"Transport"},{"location":"configuration/authentication/#bearer","text":"The token will be send through an Authorization: Bearer header. Pros and cons \u2705 Easy to read and set in every requests. \u274c Needs to be stored manually somewhere in the client. \u27a1\ufe0f Use it if you want to implement a mobile application or a pure REST API.","title":"Bearer"},{"location":"configuration/authentication/#cookie","text":"The token will be send through a cookie. Pros and cons \u2705 Automatically stored and sent securely by web browsers in every requests. \u2705 Automatically removed at expiration by web browsers. \u274c Needs a CSRF protection for maximum security. \u274c Harder to work with outside a browser, like a mobile app or a server. \u27a1\ufe0f Use it if you want to implement a web frontend.","title":"Cookie"},{"location":"configuration/authentication/#strategy","text":"It manages how the token is generated and secured. We currently provide two methods:","title":"Strategy"},{"location":"configuration/authentication/#jwt","text":"The token is self-contained in a JSON Web Token. Pros and cons \u2705 Self-contained: it doesn't need to be stored in a database. \u274c Can't be invalidated on the server-side: it's valid until it expires. \u27a1\ufe0f Use it if you want to get up-and-running quickly.","title":"JWT"},{"location":"configuration/authentication/#database","text":"The token is stored in a table (or collection) in your database. Pros and cons \u2705 Secure and performant. \u2705 Tokens can be invalidated server-side by removing them from the database. \u2705 Highly customizable: add your own fields, create an API to retrieve the active sessions of your users, etc. \u274c Configuration is a bit more complex. \u27a1\ufe0f Use it if you want maximum flexibility in your token management.","title":"Database"},{"location":"configuration/authentication/#redis","text":"The token is stored in a Redis key-store. Pros and cons \u2705 Secure and performant. \u2705 Tokens can be invalidated server-side by removing them from Redis. \u274c A Redis server is needed. \u27a1\ufe0f Use it if you want maximum performance while being able to invalidate tokens.","title":"Redis"},{"location":"configuration/authentication/backend/","text":"Create a backend \u00b6 As we said, a backend is the combination of a transport and a strategy. That way, you can create a complete strategy exactly fitting your needs. For this, you have to use the AuthenticationBackend class. from fastapi_users.authentication import AuthenticationBackend , BearerTransport , JWTStrategy SECRET = \"SECRET\" bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) As you can see, instantiation is quite simple. It accepts the following arguments: name ( str ): Name of the backend. Each backend should have a unique name. transport ( Transport ): An instance of a Transport class. get_strategy ( Callable[..., Strategy] ): A dependency callable returning an instance of a Strategy class. Next steps \u00b6 You can have as many authentication backends as you wish. You'll then have to pass those backends to your FastAPIUsers instance and generate an auth router for each one of them.","title":"Create a backend"},{"location":"configuration/authentication/backend/#create-a-backend","text":"As we said, a backend is the combination of a transport and a strategy. That way, you can create a complete strategy exactly fitting your needs. For this, you have to use the AuthenticationBackend class. from fastapi_users.authentication import AuthenticationBackend , BearerTransport , JWTStrategy SECRET = \"SECRET\" bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) As you can see, instantiation is quite simple. It accepts the following arguments: name ( str ): Name of the backend. Each backend should have a unique name. transport ( Transport ): An instance of a Transport class. get_strategy ( Callable[..., Strategy] ): A dependency callable returning an instance of a Strategy class.","title":"Create a backend"},{"location":"configuration/authentication/backend/#next-steps","text":"You can have as many authentication backends as you wish. You'll then have to pass those backends to your FastAPIUsers instance and generate an auth router for each one of them.","title":"Next steps"},{"location":"configuration/authentication/strategies/database/","text":"Database \u00b6 The most natural way for storing tokens is of course the very same database you're using for your application. In this strategy, we set up a table (or collection) for storing those tokens with the associated user id. On each request, we try to retrive this token from the database to get the corresponding user id. Configuration \u00b6 The configuration of this strategy is a bit more complex than the others as it requires you to configure models and a database adapter, exactly like we did for users . Model \u00b6 You should define an AccessToken Pydantic model inheriting from BaseAccessToken . from fastapi_users.authentication.strategy.db import BaseAccessToken class AccessToken ( BaseAccessToken ): pass It is structured like this: token ( str ) \u2013 Unique identifier of the token. It's generated automatically upon login by the strategy. user_id ( UUID4 ) \u2013 User id. of the user associated to this token. created_at ( datetime ) \u2013 Date and time of creation of the token. It's used to determine if the token is expired or not. Database adapter \u00b6 SQLAlchemy Tortoise ORM MongoDB from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from fastapi_users_db_sqlalchemy.access_token import ( SQLAlchemyAccessTokenDatabase , SQLAlchemyBaseAccessTokenTable , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import AccessToken , UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass class AccessTokenTable ( SQLAlchemyBaseAccessTokenTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) async def get_access_token_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyAccessTokenDatabase ( AccessToken , session , AccessTokenTable ) With Tortoise ORM, you need to define a proper Tortoise model for AccessToken and manually specify the user foreign key. Besides, you need to modify the Pydantic model a bit so that it works well with this Tortoise model. model.py adapter.py from fastapi_users import models from fastapi_users.authentication.strategy.db.models import BaseAccessToken from fastapi_users.db import TortoiseBaseUserModel from fastapi_users_db_tortoise.access_token import TortoiseBaseAccessTokenModel from tortoise import fields from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel class AccessTokenModel ( TortoiseBaseAccessTokenModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"access_tokens\" ) class AccessToken ( BaseAccessToken , PydanticModel ): class Config : orm_mode = True orig_model = AccessTokenModel from fastapi_users.db import TortoiseUserDatabase from fastapi_users_db_tortoise.access_token import TortoiseAccessTokenDatabase from .models import AccessToken , AccessTokenModel , UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel ) async def get_access_token_db (): yield TortoiseAccessTokenDatabase ( AccessToken , AccessTokenModel ) import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from fastapi_users_db_mongodb.access_token import MongoDBAccessTokenDatabase from .models import AccessToken , UserDB DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] users_collection = db [ \"users\" ] access_tokens_collection = db [ \"access_tokens\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , users_collection ) async def get_access_token_db (): yield MongoDBAccessTokenDatabase ( AccessToken , access_tokens_collection ) Strategy \u00b6 from fastapi import Depends from fastapi_users.authentication.db import AccessTokenDatabase , DatabaseStrategy from .models import AccessToken , UserCreate , UserDB def get_database_strategy ( access_token_db : AccessTokenDatabase [ AccessToken ] = Depends ( get_access_token_db ), ) -> DatabaseStrategy [ UserCreate , UserDB , AccessToken ]: return DatabaseStrategy ( access_token_db , lifetime_seconds = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: database ( AccessTokenDatabase ): A database adapter instance for AccessToken table, like we defined above. lifetime_seconds ( int ): The lifetime of the token in seconds. Why it's inside a function? To allow strategies to be instantiated dynamically with other dependencies, they have to be provided as a callable to the authentication backend. As you can see here, this pattern allows us to dynamically inject a connection to the database. Logout \u00b6 On logout, this strategy will delete the token from the database.","title":"Database"},{"location":"configuration/authentication/strategies/database/#database","text":"The most natural way for storing tokens is of course the very same database you're using for your application. In this strategy, we set up a table (or collection) for storing those tokens with the associated user id. On each request, we try to retrive this token from the database to get the corresponding user id.","title":"Database"},{"location":"configuration/authentication/strategies/database/#configuration","text":"The configuration of this strategy is a bit more complex than the others as it requires you to configure models and a database adapter, exactly like we did for users .","title":"Configuration"},{"location":"configuration/authentication/strategies/database/#model","text":"You should define an AccessToken Pydantic model inheriting from BaseAccessToken . from fastapi_users.authentication.strategy.db import BaseAccessToken class AccessToken ( BaseAccessToken ): pass It is structured like this: token ( str ) \u2013 Unique identifier of the token. It's generated automatically upon login by the strategy. user_id ( UUID4 ) \u2013 User id. of the user associated to this token. created_at ( datetime ) \u2013 Date and time of creation of the token. It's used to determine if the token is expired or not.","title":"Model"},{"location":"configuration/authentication/strategies/database/#database-adapter","text":"SQLAlchemy Tortoise ORM MongoDB from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from fastapi_users_db_sqlalchemy.access_token import ( SQLAlchemyAccessTokenDatabase , SQLAlchemyBaseAccessTokenTable , ) from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import AccessToken , UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass class AccessTokenTable ( SQLAlchemyBaseAccessTokenTable , Base ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) async def get_access_token_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyAccessTokenDatabase ( AccessToken , session , AccessTokenTable ) With Tortoise ORM, you need to define a proper Tortoise model for AccessToken and manually specify the user foreign key. Besides, you need to modify the Pydantic model a bit so that it works well with this Tortoise model. model.py adapter.py from fastapi_users import models from fastapi_users.authentication.strategy.db.models import BaseAccessToken from fastapi_users.db import TortoiseBaseUserModel from fastapi_users_db_tortoise.access_token import TortoiseBaseAccessTokenModel from tortoise import fields from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel class AccessTokenModel ( TortoiseBaseAccessTokenModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"access_tokens\" ) class AccessToken ( BaseAccessToken , PydanticModel ): class Config : orm_mode = True orig_model = AccessTokenModel from fastapi_users.db import TortoiseUserDatabase from fastapi_users_db_tortoise.access_token import TortoiseAccessTokenDatabase from .models import AccessToken , AccessTokenModel , UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel ) async def get_access_token_db (): yield TortoiseAccessTokenDatabase ( AccessToken , AccessTokenModel ) import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from fastapi_users_db_mongodb.access_token import MongoDBAccessTokenDatabase from .models import AccessToken , UserDB DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] users_collection = db [ \"users\" ] access_tokens_collection = db [ \"access_tokens\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , users_collection ) async def get_access_token_db (): yield MongoDBAccessTokenDatabase ( AccessToken , access_tokens_collection )","title":"Database adapter"},{"location":"configuration/authentication/strategies/database/#strategy","text":"from fastapi import Depends from fastapi_users.authentication.db import AccessTokenDatabase , DatabaseStrategy from .models import AccessToken , UserCreate , UserDB def get_database_strategy ( access_token_db : AccessTokenDatabase [ AccessToken ] = Depends ( get_access_token_db ), ) -> DatabaseStrategy [ UserCreate , UserDB , AccessToken ]: return DatabaseStrategy ( access_token_db , lifetime_seconds = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: database ( AccessTokenDatabase ): A database adapter instance for AccessToken table, like we defined above. lifetime_seconds ( int ): The lifetime of the token in seconds. Why it's inside a function? To allow strategies to be instantiated dynamically with other dependencies, they have to be provided as a callable to the authentication backend. As you can see here, this pattern allows us to dynamically inject a connection to the database.","title":"Strategy"},{"location":"configuration/authentication/strategies/database/#logout","text":"On logout, this strategy will delete the token from the database.","title":"Logout"},{"location":"configuration/authentication/strategies/jwt/","text":"JWT \u00b6 JSON Web Token (JWT) is an internet standard for creating access tokens based on JSON. They don't need to be stored in a database: the data is self-contained inside and cryptographically signed. Configuration \u00b6 from fastapi_users.authentication import JWTStrategy SECRET = \"SECRET\" def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: secret ( Union[str, pydantic.SecretStr] ): A constant secret which is used to encode the token. Use a strong passphrase and keep it secure. lifetime_seconds ( Optional[int] ): The lifetime of the token in seconds. Can be set to None but in this case the token will be valid forever ; which may raise serious security concerns. token_audience ( Optional[List[str]] ): A list of valid audiences for the JWT token. Defaults to [\"fastapi-users:auth\"] . Why it's inside a function? To allow strategies to be instantiated dynamically with other dependencies, they have to be provided as a callable to the authentication backend. For JWTStrategy , since it doesn't require dependencies, it can be as simple as the function above. Logout \u00b6 On logout, this strategy won't do anything . Indeed, a JWT can't be invalidated on the server-side: it's valid until it expires.","title":"JWT"},{"location":"configuration/authentication/strategies/jwt/#jwt","text":"JSON Web Token (JWT) is an internet standard for creating access tokens based on JSON. They don't need to be stored in a database: the data is self-contained inside and cryptographically signed.","title":"JWT"},{"location":"configuration/authentication/strategies/jwt/#configuration","text":"from fastapi_users.authentication import JWTStrategy SECRET = \"SECRET\" def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: secret ( Union[str, pydantic.SecretStr] ): A constant secret which is used to encode the token. Use a strong passphrase and keep it secure. lifetime_seconds ( Optional[int] ): The lifetime of the token in seconds. Can be set to None but in this case the token will be valid forever ; which may raise serious security concerns. token_audience ( Optional[List[str]] ): A list of valid audiences for the JWT token. Defaults to [\"fastapi-users:auth\"] . Why it's inside a function? To allow strategies to be instantiated dynamically with other dependencies, they have to be provided as a callable to the authentication backend. For JWTStrategy , since it doesn't require dependencies, it can be as simple as the function above.","title":"Configuration"},{"location":"configuration/authentication/strategies/jwt/#logout","text":"On logout, this strategy won't do anything . Indeed, a JWT can't be invalidated on the server-side: it's valid until it expires.","title":"Logout"},{"location":"configuration/authentication/strategies/redis/","text":"Redis \u00b6 Redis is an ultra-fast key-store database. As such, it's a good candidate for token management. In this strategy, a token is generated and associated with the user id. in the database. On each request, we try to retrieve this token from Redis to get the corresponding user id. Configuration \u00b6 import aioredis from fastapi_users.authentication import RedisStrategy redis = aioredis . from_url ( \"redis://localhost:6379\" , decode_responses = True ) def get_redis_strategy () -> RedisStrategy : return RedisStrategy ( redis , lifetime_seconds = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: redis ( aioredis.Redis ): An instance of aioredis.Redis . Note that the decode_responses flag set to True is necessary. lifetime_seconds ( Optional[int] ): The lifetime of the token in seconds. Defaults to None , which means the token doesn't expire. Why it's inside a function? To allow strategies to be instantiated dynamically with other dependencies, they have to be provided as a callable to the authentication backend. Logout \u00b6 On logout, this strategy will delete the token from the Redis store.","title":"Redis"},{"location":"configuration/authentication/strategies/redis/#redis","text":"Redis is an ultra-fast key-store database. As such, it's a good candidate for token management. In this strategy, a token is generated and associated with the user id. in the database. On each request, we try to retrieve this token from Redis to get the corresponding user id.","title":"Redis"},{"location":"configuration/authentication/strategies/redis/#configuration","text":"import aioredis from fastapi_users.authentication import RedisStrategy redis = aioredis . from_url ( \"redis://localhost:6379\" , decode_responses = True ) def get_redis_strategy () -> RedisStrategy : return RedisStrategy ( redis , lifetime_seconds = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: redis ( aioredis.Redis ): An instance of aioredis.Redis . Note that the decode_responses flag set to True is necessary. lifetime_seconds ( Optional[int] ): The lifetime of the token in seconds. Defaults to None , which means the token doesn't expire. Why it's inside a function? To allow strategies to be instantiated dynamically with other dependencies, they have to be provided as a callable to the authentication backend.","title":"Configuration"},{"location":"configuration/authentication/strategies/redis/#logout","text":"On logout, this strategy will delete the token from the Redis store.","title":"Logout"},{"location":"configuration/authentication/transports/bearer/","text":"Bearer \u00b6 With this transport, the token is expected inside the Authorization header of the HTTP request with the Bearer scheme. It's particularly suited for pure API interaction or mobile apps. Configuration \u00b6 from fastapi_users.authentication import BearerTransport bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) As you can see, instantiation is quite simple. It accepts the following arguments: tokenUrl ( str ): The exact path of your login endpoint. It'll allow the interactive documentation to automatically discover it and get a working Authorize button. In most cases, you'll probably need a relative path, not absolute. You can read more details about this in the FastAPI documentation . Login \u00b6 This method will return the in the following form upon successful login: 200 OK { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"token_type\" : \"bearer\" } Check documentation about login route . Logout \u00b6 The logout method with this transport returns nothing. Authentication \u00b6 This method expects that you provide a Bearer authentication with a valid token corresponding to your strategy. curl http://localhost:9000/protected-route -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI'","title":"Bearer"},{"location":"configuration/authentication/transports/bearer/#bearer","text":"With this transport, the token is expected inside the Authorization header of the HTTP request with the Bearer scheme. It's particularly suited for pure API interaction or mobile apps.","title":"Bearer"},{"location":"configuration/authentication/transports/bearer/#configuration","text":"from fastapi_users.authentication import BearerTransport bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) As you can see, instantiation is quite simple. It accepts the following arguments: tokenUrl ( str ): The exact path of your login endpoint. It'll allow the interactive documentation to automatically discover it and get a working Authorize button. In most cases, you'll probably need a relative path, not absolute. You can read more details about this in the FastAPI documentation .","title":"Configuration"},{"location":"configuration/authentication/transports/bearer/#login","text":"This method will return the in the following form upon successful login: 200 OK { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"token_type\" : \"bearer\" } Check documentation about login route .","title":"Login"},{"location":"configuration/authentication/transports/bearer/#logout","text":"The logout method with this transport returns nothing.","title":"Logout"},{"location":"configuration/authentication/transports/bearer/#authentication","text":"This method expects that you provide a Bearer authentication with a valid token corresponding to your strategy. curl http://localhost:9000/protected-route -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI'","title":"Authentication"},{"location":"configuration/authentication/transports/cookie/","text":"Cookie \u00b6 Cookies are an easy way to store stateful information into the user browser. Thus, it is more useful for browser-based navigation (e.g. a front-end app making API requests) rather than pure API interaction. Configuration \u00b6 from fastapi_users.authentication import CookieTransport cookie_transport = CookieTransport ( cookie_max_age = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: cookie_name ( fastapiusersauth ): Name of the cookie. cookie_max_age ( Optional[int] ): The lifetime of the cookie in seconds. None by default, which means it's a session cookie. cookie_path ( / ): Cookie path. cookie_domain ( None ): Cookie domain. cookie_secure ( True ): Whether to only send the cookie to the server via SSL request. cookie_httponly ( True ): Whether to prevent access to the cookie via JavaScript. cookie_samesite ( lax ): A string that specifies the samesite strategy for the cookie. Valid values are lax , strict and none . Defaults to lax . Login \u00b6 This method will return a response with a valid set-cookie header upon successful login: 200 OK Check documentation about login route . Logout \u00b6 This method will remove the authentication cookie: 200 OK Check documentation about logout route . Authentication \u00b6 This method expects that you provide a valid cookie in the headers.","title":"Cookie"},{"location":"configuration/authentication/transports/cookie/#cookie","text":"Cookies are an easy way to store stateful information into the user browser. Thus, it is more useful for browser-based navigation (e.g. a front-end app making API requests) rather than pure API interaction.","title":"Cookie"},{"location":"configuration/authentication/transports/cookie/#configuration","text":"from fastapi_users.authentication import CookieTransport cookie_transport = CookieTransport ( cookie_max_age = 3600 ) As you can see, instantiation is quite simple. It accepts the following arguments: cookie_name ( fastapiusersauth ): Name of the cookie. cookie_max_age ( Optional[int] ): The lifetime of the cookie in seconds. None by default, which means it's a session cookie. cookie_path ( / ): Cookie path. cookie_domain ( None ): Cookie domain. cookie_secure ( True ): Whether to only send the cookie to the server via SSL request. cookie_httponly ( True ): Whether to prevent access to the cookie via JavaScript. cookie_samesite ( lax ): A string that specifies the samesite strategy for the cookie. Valid values are lax , strict and none . Defaults to lax .","title":"Configuration"},{"location":"configuration/authentication/transports/cookie/#login","text":"This method will return a response with a valid set-cookie header upon successful login: 200 OK Check documentation about login route .","title":"Login"},{"location":"configuration/authentication/transports/cookie/#logout","text":"This method will remove the authentication cookie: 200 OK Check documentation about logout route .","title":"Logout"},{"location":"configuration/authentication/transports/cookie/#authentication","text":"This method expects that you provide a valid cookie in the headers.","title":"Authentication"},{"location":"configuration/databases/mongodb/","text":"MongoDB \u00b6 FastAPI Users provides the necessary tools to work with MongoDB databases thanks to mongodb/motor package for full async support. Setup database connection and collection \u00b6 Let's create a MongoDB connection and instantiate a collection. import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from .models import UserDB DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) You can choose any name for the database and the collection. Warning You may have noticed the uuidRepresentation parameter. It controls how the UUID values will be encoded in the database. By default, it's set to pythonLegacy but new applications should consider setting this to standard for cross language compatibility. Read more about this . Create the database adapter \u00b6 The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from .models import UserDB DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) Notice that we pass a reference to your UserDB model . Info The database adapter will automatically create a unique index on id and email . Warning FastAPI Users will use its defined id UUID as unique identifier for the user, rather than the builtin MongoDB _id .","title":"MongoDB"},{"location":"configuration/databases/mongodb/#mongodb","text":"FastAPI Users provides the necessary tools to work with MongoDB databases thanks to mongodb/motor package for full async support.","title":"MongoDB"},{"location":"configuration/databases/mongodb/#setup-database-connection-and-collection","text":"Let's create a MongoDB connection and instantiate a collection. import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from .models import UserDB DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) You can choose any name for the database and the collection. Warning You may have noticed the uuidRepresentation parameter. It controls how the UUID values will be encoded in the database. By default, it's set to pythonLegacy but new applications should consider setting this to standard for cross language compatibility. Read more about this .","title":"Setup database connection and collection"},{"location":"configuration/databases/mongodb/#create-the-database-adapter","text":"The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. import motor.motor_asyncio from fastapi_users.db import MongoDBUserDatabase from .models import UserDB DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] async def get_user_db (): yield MongoDBUserDatabase ( UserDB , collection ) Notice that we pass a reference to your UserDB model . Info The database adapter will automatically create a unique index on id and email . Warning FastAPI Users will use its defined id UUID as unique identifier for the user, rather than the builtin MongoDB _id .","title":"Create the database adapter"},{"location":"configuration/databases/ormar/","text":"Ormar \u00b6 FastAPI Users provides the necessary tools to work with ormar. Installation \u00b6 Install the database driver that corresponds to your DBMS: pip install asyncpg psycopg2 pip install aiomysql pymysql pip install aiosqlite For the sake of this tutorial from now on, we'll use a simple SQLite database. Setup User table \u00b6 Let's declare our User ORM model. import databases import sqlalchemy from fastapi_users.db import OrmarBaseUserModel , OrmarUserDatabase from .models import UserDB DATABASE_URL = \"sqlite:///test.db\" metadata = sqlalchemy . MetaData () database = databases . Database ( DATABASE_URL ) class UserModel ( OrmarBaseUserModel ): class Meta : tablename = \"users\" metadata = metadata database = database engine = sqlalchemy . create_engine ( DATABASE_URL ) metadata . create_all ( engine ) async def get_user_db (): yield OrmarUserDatabase ( UserDB , UserModel ) As you can see, FastAPI Users provides an abstract model that will include base fields for our User table. You can of course add you own fields there to fit to your needs! Create the database adapter \u00b6 The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. import databases import sqlalchemy from fastapi_users.db import OrmarBaseUserModel , OrmarUserDatabase from .models import UserDB DATABASE_URL = \"sqlite:///test.db\" metadata = sqlalchemy . MetaData () database = databases . Database ( DATABASE_URL ) class UserModel ( OrmarBaseUserModel ): class Meta : tablename = \"users\" metadata = metadata database = database engine = sqlalchemy . create_engine ( DATABASE_URL ) metadata . create_all ( engine ) async def get_user_db (): yield OrmarUserDatabase ( UserDB , UserModel ) Notice that we pass a reference to your UserDB model . Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See Alembic .","title":"Ormar"},{"location":"configuration/databases/ormar/#ormar","text":"FastAPI Users provides the necessary tools to work with ormar.","title":"Ormar"},{"location":"configuration/databases/ormar/#installation","text":"Install the database driver that corresponds to your DBMS: pip install asyncpg psycopg2 pip install aiomysql pymysql pip install aiosqlite For the sake of this tutorial from now on, we'll use a simple SQLite database.","title":"Installation"},{"location":"configuration/databases/ormar/#setup-user-table","text":"Let's declare our User ORM model. import databases import sqlalchemy from fastapi_users.db import OrmarBaseUserModel , OrmarUserDatabase from .models import UserDB DATABASE_URL = \"sqlite:///test.db\" metadata = sqlalchemy . MetaData () database = databases . Database ( DATABASE_URL ) class UserModel ( OrmarBaseUserModel ): class Meta : tablename = \"users\" metadata = metadata database = database engine = sqlalchemy . create_engine ( DATABASE_URL ) metadata . create_all ( engine ) async def get_user_db (): yield OrmarUserDatabase ( UserDB , UserModel ) As you can see, FastAPI Users provides an abstract model that will include base fields for our User table. You can of course add you own fields there to fit to your needs!","title":"Setup User table"},{"location":"configuration/databases/ormar/#create-the-database-adapter","text":"The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. import databases import sqlalchemy from fastapi_users.db import OrmarBaseUserModel , OrmarUserDatabase from .models import UserDB DATABASE_URL = \"sqlite:///test.db\" metadata = sqlalchemy . MetaData () database = databases . Database ( DATABASE_URL ) class UserModel ( OrmarBaseUserModel ): class Meta : tablename = \"users\" metadata = metadata database = database engine = sqlalchemy . create_engine ( DATABASE_URL ) metadata . create_all ( engine ) async def get_user_db (): yield OrmarUserDatabase ( UserDB , UserModel ) Notice that we pass a reference to your UserDB model . Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See Alembic .","title":"Create the database adapter"},{"location":"configuration/databases/sqlalchemy/","text":"SQLAlchemy \u00b6 FastAPI Users provides the necessary tools to work with SQL databases thanks to SQLAlchemy ORM with asyncio . Warning The previous adapter using encode/databases is now deprecated but can still be installed using fastapi-users[sqlalchemy] . Asynchronous driver \u00b6 To work with your DBMS, you'll need to install the corresponding asyncio driver. The common choices are: For PostgreSQL: pip install asyncpg For SQLite: pip install aiosqlite For the sake of this tutorial from now on, we'll use a simple SQLite databse. Setup User table \u00b6 Let's declare our SQLAlchemy User table. from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) As you can see, FastAPI Users provides a mixin that will include base fields for our User table. You can of course add you own fields there to fit to your needs! Implement a function to create the tables \u00b6 We'll now create an utility function to create all the defined tables. from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) This function can be called, for example, during the initialization of your FastAPI app. Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See Alembic . Create the database adapter dependency \u00b6 The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) Notice that we define first a get_async_session dependency returning us a fresh SQLAlchemy session to interact with the database. It's then used inside the get_user_db dependency to generate our adapter. Notice that we pass it three things: A reference to your UserDB model . The session instance we just injected. The UserTable variable, which is the actual SQLAlchemy model.","title":"SQLAlchemy"},{"location":"configuration/databases/sqlalchemy/#sqlalchemy","text":"FastAPI Users provides the necessary tools to work with SQL databases thanks to SQLAlchemy ORM with asyncio . Warning The previous adapter using encode/databases is now deprecated but can still be installed using fastapi-users[sqlalchemy] .","title":"SQLAlchemy"},{"location":"configuration/databases/sqlalchemy/#asynchronous-driver","text":"To work with your DBMS, you'll need to install the corresponding asyncio driver. The common choices are: For PostgreSQL: pip install asyncpg For SQLite: pip install aiosqlite For the sake of this tutorial from now on, we'll use a simple SQLite databse.","title":"Asynchronous driver"},{"location":"configuration/databases/sqlalchemy/#setup-user-table","text":"Let's declare our SQLAlchemy User table. from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) As you can see, FastAPI Users provides a mixin that will include base fields for our User table. You can of course add you own fields there to fit to your needs!","title":"Setup User table"},{"location":"configuration/databases/sqlalchemy/#implement-a-function-to-create-the-tables","text":"We'll now create an utility function to create all the defined tables. from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) This function can be called, for example, during the initialization of your FastAPI app. Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See Alembic .","title":"Implement a function to create the tables"},{"location":"configuration/databases/sqlalchemy/#create-the-database-adapter-dependency","text":"The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. from typing import AsyncGenerator from fastapi import Depends from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.asyncio import AsyncSession , create_async_engine from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base from sqlalchemy.orm import sessionmaker from .models import UserDB DATABASE_URL = \"sqlite+aiosqlite:///./test.db\" Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = create_async_engine ( DATABASE_URL ) async_session_maker = sessionmaker ( engine , class_ = AsyncSession , expire_on_commit = False ) async def create_db_and_tables (): async with engine . begin () as conn : await conn . run_sync ( Base . metadata . create_all ) async def get_async_session () -> AsyncGenerator [ AsyncSession , None ]: async with async_session_maker () as session : yield session async def get_user_db ( session : AsyncSession = Depends ( get_async_session )): yield SQLAlchemyUserDatabase ( UserDB , session , UserTable ) Notice that we define first a get_async_session dependency returning us a fresh SQLAlchemy session to interact with the database. It's then used inside the get_user_db dependency to generate our adapter. Notice that we pass it three things: A reference to your UserDB model . The session instance we just injected. The UserTable variable, which is the actual SQLAlchemy model.","title":"Create the database adapter dependency"},{"location":"configuration/databases/tortoise/","text":"Tortoise ORM \u00b6 FastAPI Users provides the necessary tools to work with Tortoise ORM. Installation \u00b6 Install the database driver that corresponds to your DBMS: pip install asyncpg pip install aiomysql pip install aiosqlite For the sake of this tutorial from now on, we'll use a simple SQLite databse. Setup User table and model \u00b6 Let's declare our User ORM model. from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel As you can see, FastAPI Users provides an abstract model that will include base fields for our User table. You can of course add you own fields there to fit to your needs! In order to make the Pydantic model and the Tortoise ORM model working well together, you'll have to add a mixin and some configuration options to your UserDB model. Tortoise ORM provides utilities to ease the integration with Pydantic and we'll use them here. from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel The PydanticModel mixin adds methods used internally by Tortoise ORM to the Pydantic model so that it can easily transform it back to an ORM model. It expects then that you provide the property orig_model which should point to the User ORM model we defined just above . Create the database adapter \u00b6 The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. from fastapi_users.db import TortoiseUserDatabase from .models import UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel ) Notice that we pass a reference to your UserDB model . Register Tortoise \u00b6 For using Tortoise ORM we must register our models and database. Tortoise ORM supports integration with FastAPI out-of-the-box. It will automatically bind startup and shutdown events. from tortoise.contrib.fastapi import register_tortoise register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"models\" ]}, generate_schemas = True , ) Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See https://tortoise-orm.readthedocs.io/en/latest/migration.html .","title":"Tortoise ORM"},{"location":"configuration/databases/tortoise/#tortoise-orm","text":"FastAPI Users provides the necessary tools to work with Tortoise ORM.","title":"Tortoise ORM"},{"location":"configuration/databases/tortoise/#installation","text":"Install the database driver that corresponds to your DBMS: pip install asyncpg pip install aiomysql pip install aiosqlite For the sake of this tutorial from now on, we'll use a simple SQLite databse.","title":"Installation"},{"location":"configuration/databases/tortoise/#setup-user-table-and-model","text":"Let's declare our User ORM model. from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel As you can see, FastAPI Users provides an abstract model that will include base fields for our User table. You can of course add you own fields there to fit to your needs! In order to make the Pydantic model and the Tortoise ORM model working well together, you'll have to add a mixin and some configuration options to your UserDB model. Tortoise ORM provides utilities to ease the integration with Pydantic and we'll use them here. from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel from tortoise.contrib.pydantic import PydanticModel class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( models . BaseUserUpdate ): pass class UserModel ( TortoiseBaseUserModel ): pass class UserDB ( User , models . BaseUserDB , PydanticModel ): class Config : orm_mode = True orig_model = UserModel The PydanticModel mixin adds methods used internally by Tortoise ORM to the Pydantic model so that it can easily transform it back to an ORM model. It expects then that you provide the property orig_model which should point to the User ORM model we defined just above .","title":"Setup User table and model"},{"location":"configuration/databases/tortoise/#create-the-database-adapter","text":"The database adapter of FastAPI Users makes the link between your database configuration and the users logic. It should be generated by a FastAPI dependency. from fastapi_users.db import TortoiseUserDatabase from .models import UserDB , UserModel DATABASE_URL = \"sqlite://./test.db\" async def get_user_db (): yield TortoiseUserDatabase ( UserDB , UserModel ) Notice that we pass a reference to your UserDB model .","title":"Create the database adapter"},{"location":"configuration/databases/tortoise/#register-tortoise","text":"For using Tortoise ORM we must register our models and database. Tortoise ORM supports integration with FastAPI out-of-the-box. It will automatically bind startup and shutdown events. from tortoise.contrib.fastapi import register_tortoise register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"models\" ]}, generate_schemas = True , ) Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See https://tortoise-orm.readthedocs.io/en/latest/migration.html .","title":"Register Tortoise"},{"location":"configuration/routers/","text":"Routers \u00b6 We're almost there! The last step is to configure the FastAPIUsers object that will wire the user manager, the authentication classes and let us generate the actual API routes . Configure FastAPIUsers \u00b6 Configure FastAPIUsers object with all the elements we defined before. More precisely: get_user_manager : Dependency callable getter to inject the user manager class instance. See UserManager . auth_backends : List of authentication backends. See Authentication . user_model : Pydantic model of a user. user_create_model : Pydantic model for creating a user. user_update_model : Pydantic model for updating a user. user_db_model : Pydantic model of a DB representation of a user. from fastapi_users import FastAPIUsers fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) Available routers \u00b6 This helper class will let you generate useful routers to setup the authentication system. Each of them is optional , so you can pick only the one that you are interested in! Here are the routers provided: Auth router : Provides /login and /logout routes for a given authentication backend . Register router : Provides /register routes to allow a user to create a new account. Reset password router : Provides /forgot-password and /reset-password routes to allow a user to reset its password. Verify router : Provides /request-verify-token and /verify routes to manage user e-mail verification. Users router : Provides routes to manage users. OAuth router : Provides routes to perform an OAuth authentication against a service provider (like Google or Facebook). You should check out each of them to understand how to use them.","title":"Introduction"},{"location":"configuration/routers/#routers","text":"We're almost there! The last step is to configure the FastAPIUsers object that will wire the user manager, the authentication classes and let us generate the actual API routes .","title":"Routers"},{"location":"configuration/routers/#configure-fastapiusers","text":"Configure FastAPIUsers object with all the elements we defined before. More precisely: get_user_manager : Dependency callable getter to inject the user manager class instance. See UserManager . auth_backends : List of authentication backends. See Authentication . user_model : Pydantic model of a user. user_create_model : Pydantic model for creating a user. user_update_model : Pydantic model for updating a user. user_db_model : Pydantic model of a DB representation of a user. from fastapi_users import FastAPIUsers fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , )","title":"Configure FastAPIUsers"},{"location":"configuration/routers/#available-routers","text":"This helper class will let you generate useful routers to setup the authentication system. Each of them is optional , so you can pick only the one that you are interested in! Here are the routers provided: Auth router : Provides /login and /logout routes for a given authentication backend . Register router : Provides /register routes to allow a user to create a new account. Reset password router : Provides /forgot-password and /reset-password routes to allow a user to reset its password. Verify router : Provides /request-verify-token and /verify routes to manage user e-mail verification. Users router : Provides routes to manage users. OAuth router : Provides routes to perform an OAuth authentication against a service provider (like Google or Facebook). You should check out each of them to understand how to use them.","title":"Available routers"},{"location":"configuration/routers/auth/","text":"Auth router \u00b6 The auth router will generate /login and /logout routes for a given authentication backend . Check the routes usage to learn how to use them. Setup \u00b6 from fastapi import FastAPI from fastapi_users import FastAPIUsers fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ], ) Optional: user verification \u00b6 You can require the user to be verified (i.e. is_verified property set to True ) to allow login. You have to set the requires_verification parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_auth_router ( auth_backend , requires_verification = True ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ], )","title":"Auth router"},{"location":"configuration/routers/auth/#auth-router","text":"The auth router will generate /login and /logout routes for a given authentication backend . Check the routes usage to learn how to use them.","title":"Auth router"},{"location":"configuration/routers/auth/#setup","text":"from fastapi import FastAPI from fastapi_users import FastAPIUsers fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( auth_backend ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ], )","title":"Setup"},{"location":"configuration/routers/auth/#optional-user-verification","text":"You can require the user to be verified (i.e. is_verified property set to True ) to allow login. You have to set the requires_verification parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_auth_router ( auth_backend , requires_verification = True ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ], )","title":"Optional: user verification"},{"location":"configuration/routers/register/","text":"Register routes \u00b6 The register router will generate a /register route to allow a user to create a new account. Check the routes usage to learn how to use them. Setup \u00b6 from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Register routes"},{"location":"configuration/routers/register/#register-routes","text":"The register router will generate a /register route to allow a user to create a new account. Check the routes usage to learn how to use them.","title":"Register routes"},{"location":"configuration/routers/register/#setup","text":"from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Setup"},{"location":"configuration/routers/reset/","text":"Reset password router \u00b6 The reset password router will generate /forgot-password (the user asks for a token to reset its password) and /reset-password (the user changes its password given the token) routes. Check the routes usage to learn how to use them. Setup \u00b6 from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Reset password router"},{"location":"configuration/routers/reset/#reset-password-router","text":"The reset password router will generate /forgot-password (the user asks for a token to reset its password) and /reset-password (the user changes its password given the token) routes. Check the routes usage to learn how to use them.","title":"Reset password router"},{"location":"configuration/routers/reset/#setup","text":"from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_reset_password_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Setup"},{"location":"configuration/routers/users/","text":"Users router \u00b6 This router provides routes to manage users. Check the routes usage to learn how to use them. Setup \u00b6 from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ], ) Optional: user verification \u00b6 You can require the user to be verified (i.e. is_verified property set to True ) to access those routes. You have to set the requires_verification parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_users_router ( requires_verification = True ), prefix = \"/users\" , tags = [ \"users\" ], )","title":"Users router"},{"location":"configuration/routers/users/#users-router","text":"This router provides routes to manage users. Check the routes usage to learn how to use them.","title":"Users router"},{"location":"configuration/routers/users/#setup","text":"from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ], )","title":"Setup"},{"location":"configuration/routers/users/#optional-user-verification","text":"You can require the user to be verified (i.e. is_verified property set to True ) to access those routes. You have to set the requires_verification parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_users_router ( requires_verification = True ), prefix = \"/users\" , tags = [ \"users\" ], )","title":"Optional: user verification"},{"location":"configuration/routers/verify/","text":"Verify router \u00b6 This router provides routes to manage user email verification. Check the routes usage to learn how to use them. \ud83d\udc4f\ud83d\udc4f\ud83d\udc4f A big thank you to Edd Salkield and Mark Todd who worked hard on this feature! Setup \u00b6 from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Verify router"},{"location":"configuration/routers/verify/#verify-router","text":"This router provides routes to manage user email verification. Check the routes usage to learn how to use them. \ud83d\udc4f\ud83d\udc4f\ud83d\udc4f A big thank you to Edd Salkield and Mark Todd who worked hard on this feature!","title":"Verify router"},{"location":"configuration/routers/verify/#setup","text":"from fastapi import FastAPI from fastapi_users import FastAPIUsers SECRET = \"SECRET\" fastapi_users = FastAPIUsers ( get_user_manager , [ auth_backend ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_verify_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Setup"},{"location":"cookbook/create-user-programmatically/","text":"Create a user programmatically \u00b6 Sometimes, you'll need to create a user programmatically in the code rather than passing by the REST API endpoint. To do this, we'll create a function that you can call from your code. In this context, we are outside the dependency injection mechanism of FastAPI, so we have to take care of instantiating the UserManager class and all other dependent objects manually . For this cookbook, we'll consider you are starting from the SQLAlchemy full example , but it'll be rather similar for other DBMS. 1. Define dependencies as context managers \u00b6 Generally, FastAPI dependencies are defined as generators , using the yield keyword. FastAPI knows very well to handle them inside its dependency injection system. For example, here is the definition of the get_user_manager dependency: async def get_user_manager ( user_db : SQLAlchemyUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) In Python, when we want to use a generator, we have to use a for loop, which would be a bit unnatural in this context since we have only one value to get, the user manager instance. To avoid this, we'll transform them into context managers , so we can call them using the with..as syntax. Fortunately, the standard library provides tools to automatically transform generators into context managers. In the following sample, we import our dependencies and create a context manager version using contextlib.asynccontextmanager : import contextlib from app.db import get_async_session , get_user_db from app.models import UserCreate from app.users import get_user_manager from fastapi_users.manager import UserAlreadyExists get_async_session_context = contextlib . asynccontextmanager ( get_async_session ) get_user_db_context = contextlib . asynccontextmanager ( get_user_db ) get_user_manager_context = contextlib . asynccontextmanager ( get_user_manager ) async def create_user ( email : str , password : str , is_superuser : bool = False ): try : async with get_async_session_context () as session : async with get_user_db_context ( session ) as user_db : async with get_user_manager_context ( user_db ) as user_manager : user = await user_manager . create ( UserCreate ( email = email , password = password , is_superuser = is_superuser ) ) print ( f \"User created { user } \" ) except UserAlreadyExists : print ( f \"User { email } already exists\" ) I have other dependencies Since FastAPI Users fully embraces dependency injection, you may have more arguments passed to your database or user manager dependencies. It's important then to not forget anyone. Once again, outside the dependency injection system, you are responsible of instantiating everything yourself. 2. Write a function \u00b6 We are now ready to write a function. The example below shows you a basic example but you can of course adapt it to your own needs. The key part here is once again to take care of opening every context managers and pass them every required arguments , as the dependency manager would do. import contextlib from app.db import get_async_session , get_user_db from app.models import UserCreate from app.users import get_user_manager from fastapi_users.manager import UserAlreadyExists get_async_session_context = contextlib . asynccontextmanager ( get_async_session ) get_user_db_context = contextlib . asynccontextmanager ( get_user_db ) get_user_manager_context = contextlib . asynccontextmanager ( get_user_manager ) async def create_user ( email : str , password : str , is_superuser : bool = False ): try : async with get_async_session_context () as session : async with get_user_db_context ( session ) as user_db : async with get_user_manager_context ( user_db ) as user_manager : user = await user_manager . create ( UserCreate ( email = email , password = password , is_superuser = is_superuser ) ) print ( f \"User created { user } \" ) except UserAlreadyExists : print ( f \"User { email } already exists\" ) 3. Use it \u00b6 You can now easily use it in a script. For example: import asyncio if __name__ == \"__main__\" : asyncio . run ( create_user ( \"king.arthur@camelot.bt\" , \"guinevere\" ))","title":"Create a user programmatically"},{"location":"cookbook/create-user-programmatically/#create-a-user-programmatically","text":"Sometimes, you'll need to create a user programmatically in the code rather than passing by the REST API endpoint. To do this, we'll create a function that you can call from your code. In this context, we are outside the dependency injection mechanism of FastAPI, so we have to take care of instantiating the UserManager class and all other dependent objects manually . For this cookbook, we'll consider you are starting from the SQLAlchemy full example , but it'll be rather similar for other DBMS.","title":"Create a user programmatically"},{"location":"cookbook/create-user-programmatically/#1-define-dependencies-as-context-managers","text":"Generally, FastAPI dependencies are defined as generators , using the yield keyword. FastAPI knows very well to handle them inside its dependency injection system. For example, here is the definition of the get_user_manager dependency: async def get_user_manager ( user_db : SQLAlchemyUserDatabase = Depends ( get_user_db )): yield UserManager ( user_db ) In Python, when we want to use a generator, we have to use a for loop, which would be a bit unnatural in this context since we have only one value to get, the user manager instance. To avoid this, we'll transform them into context managers , so we can call them using the with..as syntax. Fortunately, the standard library provides tools to automatically transform generators into context managers. In the following sample, we import our dependencies and create a context manager version using contextlib.asynccontextmanager : import contextlib from app.db import get_async_session , get_user_db from app.models import UserCreate from app.users import get_user_manager from fastapi_users.manager import UserAlreadyExists get_async_session_context = contextlib . asynccontextmanager ( get_async_session ) get_user_db_context = contextlib . asynccontextmanager ( get_user_db ) get_user_manager_context = contextlib . asynccontextmanager ( get_user_manager ) async def create_user ( email : str , password : str , is_superuser : bool = False ): try : async with get_async_session_context () as session : async with get_user_db_context ( session ) as user_db : async with get_user_manager_context ( user_db ) as user_manager : user = await user_manager . create ( UserCreate ( email = email , password = password , is_superuser = is_superuser ) ) print ( f \"User created { user } \" ) except UserAlreadyExists : print ( f \"User { email } already exists\" ) I have other dependencies Since FastAPI Users fully embraces dependency injection, you may have more arguments passed to your database or user manager dependencies. It's important then to not forget anyone. Once again, outside the dependency injection system, you are responsible of instantiating everything yourself.","title":"1. Define dependencies as context managers"},{"location":"cookbook/create-user-programmatically/#2-write-a-function","text":"We are now ready to write a function. The example below shows you a basic example but you can of course adapt it to your own needs. The key part here is once again to take care of opening every context managers and pass them every required arguments , as the dependency manager would do. import contextlib from app.db import get_async_session , get_user_db from app.models import UserCreate from app.users import get_user_manager from fastapi_users.manager import UserAlreadyExists get_async_session_context = contextlib . asynccontextmanager ( get_async_session ) get_user_db_context = contextlib . asynccontextmanager ( get_user_db ) get_user_manager_context = contextlib . asynccontextmanager ( get_user_manager ) async def create_user ( email : str , password : str , is_superuser : bool = False ): try : async with get_async_session_context () as session : async with get_user_db_context ( session ) as user_db : async with get_user_manager_context ( user_db ) as user_manager : user = await user_manager . create ( UserCreate ( email = email , password = password , is_superuser = is_superuser ) ) print ( f \"User created { user } \" ) except UserAlreadyExists : print ( f \"User { email } already exists\" )","title":"2. Write a function"},{"location":"cookbook/create-user-programmatically/#3-use-it","text":"You can now easily use it in a script. For example: import asyncio if __name__ == \"__main__\" : asyncio . run ( create_user ( \"king.arthur@camelot.bt\" , \"guinevere\" ))","title":"3. Use it"},{"location":"migration/08_to_1x/","text":"0.8.x \u27a1\ufe0f 1.x.x \u00b6 1.0 version introduces major breaking changes that need you to update some of your code and migrate your data. Id. are UUID \u00b6 Users and OAuth accounts id. are now represented as real UUID objects instead of plain strings. This change was introduced to leverage efficient storage and indexing for DBMS that supports UUID (especially PostgreSQL and Mongo). In Python code \u00b6 If you were doing comparison betwen a user id. and a string (in unit tests for example), you should now cast the id. to string: # Before assert \"d35d213e-f3d8-4f08-954a-7e0d1bea286f\" == user . id # Now assert \"d35d213e-f3d8-4f08-954a-7e0d1bea286f\" == str ( user . id ) If you were refering to user id. in your Pydantic models, the field should now be of UUID4 type instead of str : from pydantic import BaseModel , UUID4 # Before class Model ( BaseModel ): user_id : str # After class Model ( BaseModel ): user_id : UUID4 MongoDB \u00b6 To avoid any issues, it's recommended to use the standard UUID representation when instantiating the MongoDB client: DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) This parameter controls how the UUID values will be encoded in the database. By default, it's set to pythonLegacy but new applications should consider setting this to standard for cross language compatibility. Read more about this . In database \u00b6 Id. were before stored as strings in the database. You should make a migration to convert string data to UUID data. Danger Scripts below are provided as guidelines. Please review them carefully , adapt them and check that they are working on a test database before applying them to production. BE CAREFUL. THEY CAN DESTROY YOUR DATA. . PostgreSQL \u00b6 PostgreSQL supports UUID type. If not already, you should enable the uuid-ossp extension: CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\" ; To convert the existing id. string column, we can: Create a new column with UUID type. Fill it with the id. converted to UUID. Drop the original id. column. Make the new column a primary key and rename it. ALTER TABLE \"user\" ADD uuid_id UUID ; UPDATE \"user\" SET uuid_id = uuid ( id ); ALTER TABLE \"user\" DROP id ; ALTER TABLE \"user\" ADD PRIMARY KEY ( uuid_id ); ALTER TABLE \"user\" RENAME COLUMN uuid_id TO id ; MySQL \u00b6 MySQL doesn't support UUID type. We'll just convert the column to CHAR(36) type: ALTER TABLE \"user\" MODIFY id CHAR ( 36 ); MongoDB \u00b6 Mongo shell \u00b6 For MongoDB, we can use a forEach iterator to convert the id. for each document: db . getCollection ( 'users' ). find (). forEach ( function ( user ) { var uuid = UUID ( user . id ); db . getCollection ( 'users' ). update ({ _id : user . _id }, [{ $set : { id : uuid }}]); }); Python \u00b6 import uuid import motor.motor_asyncio async def migrate_uuid (): client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] users = db [ \"users\" ] async for user in users . find ({}): await users . update_one ( { \"_id\" : user [ \"_id\" ]}, { \"$set\" : { \"id\" : uuid . UUID ( user [ \"id\" ])}}, ) Splitted routers \u00b6 You now have the responsibility to wire the routers . FastAPI Users doesn't give a bloated users router anymore. Event handlers are also removed. You have to provide your \"after-\" logic as a parameter of the router generator. Before \u00b6 jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) @fastapi_users . on_after_register () def on_after_register ( user : User , request : Request ): print ( f \"User { user . id } has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str , request : Request ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) After \u00b6 def on_after_register ( user : UserDB , request : Request ): print ( f \"User { user . id } has registered.\" ) def on_after_forgot_password ( user : UserDB , token : str , request : Request ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app . include_router ( fastapi_users . get_auth_router ( jwt_authentication ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router ( on_after_register ), prefix = \"/auth\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_reset_password_router ( SECRET , after_forgot_password = on_after_forgot_password ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) Important things to notice: FastAPIUsers takes two arguments less ( reset_password_token_secret and reset_password_token_lifetime_seconds ). You have more flexibility to choose the prefix and tags of the routers. The /login / /logout are now your responsibility to include for each backend. The path will change (before /login/jwt , after /jwt/login ). If you don't care about some of those routers, you can discard them.","title":"0.8.x \u27a1\ufe0f 1.x.x"},{"location":"migration/08_to_1x/#08x-1xx","text":"1.0 version introduces major breaking changes that need you to update some of your code and migrate your data.","title":"0.8.x \u27a1\ufe0f 1.x.x"},{"location":"migration/08_to_1x/#id-are-uuid","text":"Users and OAuth accounts id. are now represented as real UUID objects instead of plain strings. This change was introduced to leverage efficient storage and indexing for DBMS that supports UUID (especially PostgreSQL and Mongo).","title":"Id. are UUID"},{"location":"migration/08_to_1x/#in-python-code","text":"If you were doing comparison betwen a user id. and a string (in unit tests for example), you should now cast the id. to string: # Before assert \"d35d213e-f3d8-4f08-954a-7e0d1bea286f\" == user . id # Now assert \"d35d213e-f3d8-4f08-954a-7e0d1bea286f\" == str ( user . id ) If you were refering to user id. in your Pydantic models, the field should now be of UUID4 type instead of str : from pydantic import BaseModel , UUID4 # Before class Model ( BaseModel ): user_id : str # After class Model ( BaseModel ): user_id : UUID4","title":"In Python code"},{"location":"migration/08_to_1x/#mongodb","text":"To avoid any issues, it's recommended to use the standard UUID representation when instantiating the MongoDB client: DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) This parameter controls how the UUID values will be encoded in the database. By default, it's set to pythonLegacy but new applications should consider setting this to standard for cross language compatibility. Read more about this .","title":"MongoDB"},{"location":"migration/08_to_1x/#in-database","text":"Id. were before stored as strings in the database. You should make a migration to convert string data to UUID data. Danger Scripts below are provided as guidelines. Please review them carefully , adapt them and check that they are working on a test database before applying them to production. BE CAREFUL. THEY CAN DESTROY YOUR DATA. .","title":"In database"},{"location":"migration/08_to_1x/#postgresql","text":"PostgreSQL supports UUID type. If not already, you should enable the uuid-ossp extension: CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\" ; To convert the existing id. string column, we can: Create a new column with UUID type. Fill it with the id. converted to UUID. Drop the original id. column. Make the new column a primary key and rename it. ALTER TABLE \"user\" ADD uuid_id UUID ; UPDATE \"user\" SET uuid_id = uuid ( id ); ALTER TABLE \"user\" DROP id ; ALTER TABLE \"user\" ADD PRIMARY KEY ( uuid_id ); ALTER TABLE \"user\" RENAME COLUMN uuid_id TO id ;","title":"PostgreSQL"},{"location":"migration/08_to_1x/#mysql","text":"MySQL doesn't support UUID type. We'll just convert the column to CHAR(36) type: ALTER TABLE \"user\" MODIFY id CHAR ( 36 );","title":"MySQL"},{"location":"migration/08_to_1x/#mongodb_1","text":"","title":"MongoDB"},{"location":"migration/08_to_1x/#mongo-shell","text":"For MongoDB, we can use a forEach iterator to convert the id. for each document: db . getCollection ( 'users' ). find (). forEach ( function ( user ) { var uuid = UUID ( user . id ); db . getCollection ( 'users' ). update ({ _id : user . _id }, [{ $set : { id : uuid }}]); });","title":"Mongo shell"},{"location":"migration/08_to_1x/#python","text":"import uuid import motor.motor_asyncio async def migrate_uuid (): client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] users = db [ \"users\" ] async for user in users . find ({}): await users . update_one ( { \"_id\" : user [ \"_id\" ]}, { \"$set\" : { \"id\" : uuid . UUID ( user [ \"id\" ])}}, )","title":"Python"},{"location":"migration/08_to_1x/#splitted-routers","text":"You now have the responsibility to wire the routers . FastAPI Users doesn't give a bloated users router anymore. Event handlers are also removed. You have to provide your \"after-\" logic as a parameter of the router generator.","title":"Splitted routers"},{"location":"migration/08_to_1x/#before","text":"jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) @fastapi_users . on_after_register () def on_after_register ( user : User , request : Request ): print ( f \"User { user . id } has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str , request : Request ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" )","title":"Before"},{"location":"migration/08_to_1x/#after","text":"def on_after_register ( user : UserDB , request : Request ): print ( f \"User { user . id } has registered.\" ) def on_after_forgot_password ( user : UserDB , token : str , request : Request ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app . include_router ( fastapi_users . get_auth_router ( jwt_authentication ), prefix = \"/auth/jwt\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_register_router ( on_after_register ), prefix = \"/auth\" , tags = [ \"auth\" ] ) app . include_router ( fastapi_users . get_reset_password_router ( SECRET , after_forgot_password = on_after_forgot_password ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) Important things to notice: FastAPIUsers takes two arguments less ( reset_password_token_secret and reset_password_token_lifetime_seconds ). You have more flexibility to choose the prefix and tags of the routers. The /login / /logout are now your responsibility to include for each backend. The path will change (before /login/jwt , after /jwt/login ). If you don't care about some of those routers, you can discard them.","title":"After"},{"location":"migration/1x_to_2x/","text":"1.x.x \u27a1\ufe0f 2.x.x \u00b6 JWT authentication backend \u00b6 To be fully compatible with Swagger authentication, the output of a successful login operation with the JWT authentication backend has changed: Before { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } After { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"token_type\" : \"bearer\" } Make sure to update your clients to read the token in the right property.","title":"1.x.x \u27a1\ufe0f 2.x.x"},{"location":"migration/1x_to_2x/#1xx-2xx","text":"","title":"1.x.x \u27a1\ufe0f 2.x.x"},{"location":"migration/1x_to_2x/#jwt-authentication-backend","text":"To be fully compatible with Swagger authentication, the output of a successful login operation with the JWT authentication backend has changed: Before { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } After { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"token_type\" : \"bearer\" } Make sure to update your clients to read the token in the right property.","title":"JWT authentication backend"},{"location":"migration/2x_to_3x/","text":"2.x.x \u27a1\ufe0f 3.x.x \u00b6 Emails are now case-insensitive \u00b6 Before 3.x.x, the local part (before the @) of the email address was case-sensitive. Therefore, king.arthur@camelot.bt and King.Arthur@camelot.bt were considered as two different users . This behaviour was a bit confusing and not consistent with 99% of web services out there. After 3.x.x, users are fetched from the database with a case-insensitive email search. Bear in mind though that if the user registers with the email King.Arthur@camelot.bt , it will be stored exactly like this in the database (with casing) ; but he will be able to login as king.arthur@camelot.bt . Danger It's super important then, before you upgrade to 3.x.x that you check if there are several users with the same email with different cases ; and that you merge or delete those accounts .","title":"2.x.x \u27a1\ufe0f 3.x.x"},{"location":"migration/2x_to_3x/#2xx-3xx","text":"","title":"2.x.x \u27a1\ufe0f 3.x.x"},{"location":"migration/2x_to_3x/#emails-are-now-case-insensitive","text":"Before 3.x.x, the local part (before the @) of the email address was case-sensitive. Therefore, king.arthur@camelot.bt and King.Arthur@camelot.bt were considered as two different users . This behaviour was a bit confusing and not consistent with 99% of web services out there. After 3.x.x, users are fetched from the database with a case-insensitive email search. Bear in mind though that if the user registers with the email King.Arthur@camelot.bt , it will be stored exactly like this in the database (with casing) ; but he will be able to login as king.arthur@camelot.bt . Danger It's super important then, before you upgrade to 3.x.x that you check if there are several users with the same email with different cases ; and that you merge or delete those accounts .","title":"Emails are now case-insensitive"},{"location":"migration/3x_to_4x/","text":"3.x.x \u27a1\ufe0f 4.x.x \u00b6 expires_at property in OAuthAccount is now optional \u00b6 Before 4.x.x, the expires_at property in OAuthAccount model was mandatory. It was causing issues with some services that don't have such expiration property. If you use SQLAlchemy or Tortoise databases adapters, you'll have to make a migration to update your database schema.","title":"3.x.x \u27a1\ufe0f 4.x.x"},{"location":"migration/3x_to_4x/#3xx-4xx","text":"","title":"3.x.x \u27a1\ufe0f 4.x.x"},{"location":"migration/3x_to_4x/#expires_at-property-in-oauthaccount-is-now-optional","text":"Before 4.x.x, the expires_at property in OAuthAccount model was mandatory. It was causing issues with some services that don't have such expiration property. If you use SQLAlchemy or Tortoise databases adapters, you'll have to make a migration to update your database schema.","title":"expires_at property in OAuthAccount is now optional"},{"location":"migration/4x_to_5x/","text":"4.x.x \u27a1\ufe0f 5.x.x \u00b6 New property is_verified in User model. \u00b6 Starting 5.x.x., there is a new e-mail verification feature . Even if optional, the is_verified property has been added to the User model. If you use SQLAlchemy or Tortoise databases adapters, you'll have to make a migration to update your database schema.","title":"4.x.x \u27a1\ufe0f 5.x.x"},{"location":"migration/4x_to_5x/#4xx-5xx","text":"","title":"4.x.x \u27a1\ufe0f 5.x.x"},{"location":"migration/4x_to_5x/#new-property-is_verified-in-user-model","text":"Starting 5.x.x., there is a new e-mail verification feature . Even if optional, the is_verified property has been added to the User model. If you use SQLAlchemy or Tortoise databases adapters, you'll have to make a migration to update your database schema.","title":"New property is_verified in User model."},{"location":"migration/6x_to_7x/","text":"6.x.x \u27a1\ufe0f 7.x.x \u00b6 The deprecated dependencies to retrieve current user have been removed. Use the current_user factory instead. [ Documentation ] When trying to authenticate a not verified user, a status code 403 is raised instead of status code 401. Thanks @daanbeverdam \ud83c\udf89 [ Documentation ] Your UserUpdate model shouldn't inherit from the base User class. If you have custom fields, you should repeat them in this model. [ Documentation ] Database adapters now live in their own repositories and packages . When upgrading to v7.0.0, the dependency for your database adapter should automatically be installed. The import statements remain unchanged.","title":"6.x.x \u27a1\ufe0f 7.x.x"},{"location":"migration/6x_to_7x/#6xx-7xx","text":"The deprecated dependencies to retrieve current user have been removed. Use the current_user factory instead. [ Documentation ] When trying to authenticate a not verified user, a status code 403 is raised instead of status code 401. Thanks @daanbeverdam \ud83c\udf89 [ Documentation ] Your UserUpdate model shouldn't inherit from the base User class. If you have custom fields, you should repeat them in this model. [ Documentation ] Database adapters now live in their own repositories and packages . When upgrading to v7.0.0, the dependency for your database adapter should automatically be installed. The import statements remain unchanged.","title":"6.x.x \u27a1\ufe0f 7.x.x"},{"location":"migration/7x_to_8x/","text":"7.x.x \u27a1\ufe0f 8.x.x \u00b6 Version 8 includes the biggest code changes since version 1. We reorganized lot of parts of the code to make it even more modular and integrate more into the dependency injection system of FastAPI. Most importantly, you need now to implement a UserManager class and a associated dependency to create an instance of this class. Event handlers should live in the UserManager \u00b6 Before, event handlers like on_after_register or on_after_forgot_password were defined in their own functions that were passed as arguments of router generators. Now, they should be methods of the UserManager class. You can read more in the UserManager documentation . Password validation should live in the UserManager \u00b6 Before, password validation was defined in its own function that was passed as argument of FastAPIUsers . Now, it should be a method of the UserManager class. You can read more in the UserManager documentation . Verify token secret and lifetime parameters are attributes of UserManager \u00b6 Before, verify token and lifetime parameters were passed as argument of get_verify_router . Now, they should be defined as attributes of the UserManager class. You can read more in the UserManager documentation . Reset password token secret and lifetime parameters are attributes of UserManager \u00b6 Before, reset password token and lifetime parameters were passed as argument of get_verify_router . Now, they should be defined as attributes of the UserManager class. You can read more in the UserManager documentation . Database adapter should be provided in a dependency \u00b6 Before, we advised to directly instantiate the database adapter class. Now, it should be instantiated inside a dependency that you define yourself. The benefit of this is that it lives in the dependency injection system of FastAPI, allowing you to have more dynamic logic to create your instance. \u27a1\ufe0f I'm using SQLAlchemy \u27a1\ufe0f I'm using MongoDB \u27a1\ufe0f I'm using Tortoise ORM \u27a1\ufe0f I'm using ormar FastAPIUsers now expect a get_user_manager dependency \u00b6 Before, the database adapter instance was passed as argument of FastAPIUsers . Now, you should define a get_user_manager dependency returning an instance of your UserManager class. This dependency will be dependent of the database adapter dependency. You can read more in the UserManager documentation and FastAPIUsers documentation Lost? \u00b6 If you're unsure or a bit lost, make sure to check the full working examples .","title":"7.x.x \u27a1\ufe0f 8.x.x"},{"location":"migration/7x_to_8x/#7xx-8xx","text":"Version 8 includes the biggest code changes since version 1. We reorganized lot of parts of the code to make it even more modular and integrate more into the dependency injection system of FastAPI. Most importantly, you need now to implement a UserManager class and a associated dependency to create an instance of this class.","title":"7.x.x \u27a1\ufe0f 8.x.x"},{"location":"migration/7x_to_8x/#event-handlers-should-live-in-the-usermanager","text":"Before, event handlers like on_after_register or on_after_forgot_password were defined in their own functions that were passed as arguments of router generators. Now, they should be methods of the UserManager class. You can read more in the UserManager documentation .","title":"Event handlers should live in the UserManager"},{"location":"migration/7x_to_8x/#password-validation-should-live-in-the-usermanager","text":"Before, password validation was defined in its own function that was passed as argument of FastAPIUsers . Now, it should be a method of the UserManager class. You can read more in the UserManager documentation .","title":"Password validation should live in the UserManager"},{"location":"migration/7x_to_8x/#verify-token-secret-and-lifetime-parameters-are-attributes-of-usermanager","text":"Before, verify token and lifetime parameters were passed as argument of get_verify_router . Now, they should be defined as attributes of the UserManager class. You can read more in the UserManager documentation .","title":"Verify token secret and lifetime parameters are attributes of UserManager"},{"location":"migration/7x_to_8x/#reset-password-token-secret-and-lifetime-parameters-are-attributes-of-usermanager","text":"Before, reset password token and lifetime parameters were passed as argument of get_verify_router . Now, they should be defined as attributes of the UserManager class. You can read more in the UserManager documentation .","title":"Reset password token secret and lifetime parameters are attributes of UserManager"},{"location":"migration/7x_to_8x/#database-adapter-should-be-provided-in-a-dependency","text":"Before, we advised to directly instantiate the database adapter class. Now, it should be instantiated inside a dependency that you define yourself. The benefit of this is that it lives in the dependency injection system of FastAPI, allowing you to have more dynamic logic to create your instance. \u27a1\ufe0f I'm using SQLAlchemy \u27a1\ufe0f I'm using MongoDB \u27a1\ufe0f I'm using Tortoise ORM \u27a1\ufe0f I'm using ormar","title":"Database adapter should be provided in a dependency"},{"location":"migration/7x_to_8x/#fastapiusers-now-expect-a-get_user_manager-dependency","text":"Before, the database adapter instance was passed as argument of FastAPIUsers . Now, you should define a get_user_manager dependency returning an instance of your UserManager class. This dependency will be dependent of the database adapter dependency. You can read more in the UserManager documentation and FastAPIUsers documentation","title":"FastAPIUsers now expect a get_user_manager dependency"},{"location":"migration/7x_to_8x/#lost","text":"If you're unsure or a bit lost, make sure to check the full working examples .","title":"Lost?"},{"location":"migration/8x_to_9x/","text":"8.x.x \u27a1\ufe0f 9.x.x \u00b6 Version 9 revamps the authentication backends: we splitted the logic of a backend into two: the transport , which is how the token will be carried over the request and the strategy , which is how the token is generated and secured. The benefit of this is that we'll soon be able to propose new strategies, like database session tokens, without having to repeat the transport logic which remains the same. Convert the authentication backend \u00b6 You now have to generate an authentication backend with a transport and a strategy. I used JWTAuthentication \u00b6 Before After from fastapi_users.authentication import JWTAuthentication jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"auth/jwt/login\" ) from fastapi_users.authentication import AuthenticationBackend , BearerTransport , JWTStrategy SECRET = \"SECRET\" bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) Warning There is no default name anymore: you need to provide it yourself for each of your backends. I used CookieAuthentication \u00b6 Before After from fastapi_users.authentication import CookieAuthentication cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) from fastapi_users.authentication import AuthenticationBackend , CookieTransport , JWTStrategy SECRET = \"SECRET\" cookie_transport = CookieTransport ( cookie_max_age = 3600 ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"cookie\" , transport = cookie_transport , get_strategy = get_jwt_strategy , ) Warning There is no default name anymore: you need to provide it yourself for each of your backends. Tip Notice that the strategy is the same for both authentication backends. That's the beauty of this approach: the token generation is decoupled from its transport. OAuth: one router for each backend \u00b6 Before, a single OAuth router was enough to login with any of your authentication backend. Now, you need to generate a router for each of your backends. Before After app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) authentication_backend is not needed on /authorize \u00b6 The consequence of this is that you don't need to specify the authentication backend when making a request to /authorize . Before After curl \\ -H \"Content-Type: application/json\" \\ -X GET \\ http://localhost:8000/auth/google/authorize?authentication_backend = jwt curl \\ -H \"Content-Type: application/json\" \\ -X GET \\ http://localhost:8000/auth/google/authorize Lost? \u00b6 If you're unsure or a bit lost, make sure to check the full working examples .","title":"8.x.x \u27a1\ufe0f 9.x.x"},{"location":"migration/8x_to_9x/#8xx-9xx","text":"Version 9 revamps the authentication backends: we splitted the logic of a backend into two: the transport , which is how the token will be carried over the request and the strategy , which is how the token is generated and secured. The benefit of this is that we'll soon be able to propose new strategies, like database session tokens, without having to repeat the transport logic which remains the same.","title":"8.x.x \u27a1\ufe0f 9.x.x"},{"location":"migration/8x_to_9x/#convert-the-authentication-backend","text":"You now have to generate an authentication backend with a transport and a strategy.","title":"Convert the authentication backend"},{"location":"migration/8x_to_9x/#i-used-jwtauthentication","text":"Before After from fastapi_users.authentication import JWTAuthentication jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"auth/jwt/login\" ) from fastapi_users.authentication import AuthenticationBackend , BearerTransport , JWTStrategy SECRET = \"SECRET\" bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) Warning There is no default name anymore: you need to provide it yourself for each of your backends.","title":"I used JWTAuthentication"},{"location":"migration/8x_to_9x/#i-used-cookieauthentication","text":"Before After from fastapi_users.authentication import CookieAuthentication cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) from fastapi_users.authentication import AuthenticationBackend , CookieTransport , JWTStrategy SECRET = \"SECRET\" cookie_transport = CookieTransport ( cookie_max_age = 3600 ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) auth_backend = AuthenticationBackend ( name = \"cookie\" , transport = cookie_transport , get_strategy = get_jwt_strategy , ) Warning There is no default name anymore: you need to provide it yourself for each of your backends. Tip Notice that the strategy is the same for both authentication backends. That's the beauty of this approach: the token generation is decoupled from its transport.","title":"I used CookieAuthentication"},{"location":"migration/8x_to_9x/#oauth-one-router-for-each-backend","text":"Before, a single OAuth router was enough to login with any of your authentication backend. Now, you need to generate a router for each of your backends. Before After app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_oauth_router ( google_oauth_client , auth_backend , \"SECRET\" ), prefix = \"/auth/google\" , tags = [ \"auth\" ], )","title":"OAuth: one router for each backend"},{"location":"migration/8x_to_9x/#authentication_backend-is-not-needed-on-authorize","text":"The consequence of this is that you don't need to specify the authentication backend when making a request to /authorize . Before After curl \\ -H \"Content-Type: application/json\" \\ -X GET \\ http://localhost:8000/auth/google/authorize?authentication_backend = jwt curl \\ -H \"Content-Type: application/json\" \\ -X GET \\ http://localhost:8000/auth/google/authorize","title":"authentication_backend is not needed on /authorize"},{"location":"migration/8x_to_9x/#lost","text":"If you're unsure or a bit lost, make sure to check the full working examples .","title":"Lost?"},{"location":"usage/current-user/","text":"Get current user \u00b6 FastAPI Users provides a dependency callable to easily inject authenticated user in your routes. They are available from your FastAPIUsers instance. Tip For more information about how to make an authenticated request to your API, check the documentation of your Authentication method . current_user \u00b6 Return a dependency callable to retrieve currently authenticated user, passing the following parameters: optional : If True , None is returned if there is no authenticated user or if it doesn't pass the other requirements. Otherwise, throw 401 Unauthorized . Defaults to False . active : If True , throw 401 Unauthorized if the authenticated user is inactive. Defaults to False . verified : If True , throw 403 Forbidden if the authenticated user is not verified. Defaults to False . superuser : If True , throw 403 Forbidden if the authenticated user is not a superuser. Defaults to False . get_enabled_backends : Optional dependency callable returning a list of enabled authentication backends. Useful if you want to dynamically enable some authentication backends based on external logic, like a configuration in database. By default, all specified authentication backends are enabled. Please not however that every backends will appear in the OpenAPI documentation, as FastAPI resolves it statically. Create it once and reuse it This function is a factory , a function returning another function \ud83e\udd2f It's this returned function that will be the dependency called by FastAPI in your API routes. To avoid having to generate it on each route and avoid issues when unit testing, it's strongly recommended that you assign the result in a variable and reuse it at will in your routes. The examples below demonstrate this pattern. Examples \u00b6 Get the current user ( active or not ) \u00b6 current_user = fastapi_users . current_user () @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_user )): return f \"Hello, { user . email } \" Get the current active user \u00b6 current_active_user = fastapi_users . current_user ( active = True ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_active_user )): return f \"Hello, { user . email } \" Get the current active and verified user \u00b6 current_active_verified_user = fastapi_users . current_user ( active = True , verified = True ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_active_verified_user )): return f \"Hello, { user . email } \" Get the current active superuser \u00b6 current_superuser = fastapi_users . current_user ( active = True , superuser = True ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_superuser )): return f \"Hello, { user . email } \" Dynamically enable authentication backends \u00b6 Warning This is an advanced feature for cases where you have several authentication backends that are enabled conditionally. In most cases, you won't need this option. from fastapi import Request from fastapi_users.authentication import AuthenticationBackend , BearerTransport , CookieTransport , JWTStrategy SECRET = \"SECRET\" bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) cookie_transport = CookieTransport ( cookie_max_age = 3600 ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) jwt_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) cookie_backend = AuthenticationBackend ( name = \"jwt\" , transport = cookie_transport , get_strategy = get_jwt_strategy , ) async def get_enabled_backends ( request : Request ): \"\"\"Return the enabled dependencies following custom logic.\"\"\" if request . url . path == \"/protected-route-only-jwt\" : return [ jwt_backend ] else : return [ cookie_backend , jwt_backend ] current_active_user = fastapi_users . current_user ( active = True , get_enabled_backends = get_enabled_backends ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_active_user )): return f \"Hello, { user . email } . You are authenticated with a cookie or a JWT.\" @app . get ( \"/protected-route-only-jwt\" ) def protected_route ( user : User = Depends ( current_active_user )): return f \"Hello, { user . email } . You are authenticated with a JWT.\" In a path operation \u00b6 If you don't need the user in the route logic, you can use this syntax: @app . get ( \"/protected-route\" , dependencies = [ Depends ( current_superuser )]) def protected_route (): return \"Hello, some user.\" You can read more about this in FastAPI docs .","title":"Get current user"},{"location":"usage/current-user/#get-current-user","text":"FastAPI Users provides a dependency callable to easily inject authenticated user in your routes. They are available from your FastAPIUsers instance. Tip For more information about how to make an authenticated request to your API, check the documentation of your Authentication method .","title":"Get current user"},{"location":"usage/current-user/#current_user","text":"Return a dependency callable to retrieve currently authenticated user, passing the following parameters: optional : If True , None is returned if there is no authenticated user or if it doesn't pass the other requirements. Otherwise, throw 401 Unauthorized . Defaults to False . active : If True , throw 401 Unauthorized if the authenticated user is inactive. Defaults to False . verified : If True , throw 403 Forbidden if the authenticated user is not verified. Defaults to False . superuser : If True , throw 403 Forbidden if the authenticated user is not a superuser. Defaults to False . get_enabled_backends : Optional dependency callable returning a list of enabled authentication backends. Useful if you want to dynamically enable some authentication backends based on external logic, like a configuration in database. By default, all specified authentication backends are enabled. Please not however that every backends will appear in the OpenAPI documentation, as FastAPI resolves it statically. Create it once and reuse it This function is a factory , a function returning another function \ud83e\udd2f It's this returned function that will be the dependency called by FastAPI in your API routes. To avoid having to generate it on each route and avoid issues when unit testing, it's strongly recommended that you assign the result in a variable and reuse it at will in your routes. The examples below demonstrate this pattern.","title":"current_user"},{"location":"usage/current-user/#examples","text":"","title":"Examples"},{"location":"usage/current-user/#get-the-current-user-active-or-not","text":"current_user = fastapi_users . current_user () @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_user )): return f \"Hello, { user . email } \"","title":"Get the current user (active or not)"},{"location":"usage/current-user/#get-the-current-active-user","text":"current_active_user = fastapi_users . current_user ( active = True ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_active_user )): return f \"Hello, { user . email } \"","title":"Get the current active user"},{"location":"usage/current-user/#get-the-current-active-and-verified-user","text":"current_active_verified_user = fastapi_users . current_user ( active = True , verified = True ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_active_verified_user )): return f \"Hello, { user . email } \"","title":"Get the current active and verified user"},{"location":"usage/current-user/#get-the-current-active-superuser","text":"current_superuser = fastapi_users . current_user ( active = True , superuser = True ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_superuser )): return f \"Hello, { user . email } \"","title":"Get the current active superuser"},{"location":"usage/current-user/#dynamically-enable-authentication-backends","text":"Warning This is an advanced feature for cases where you have several authentication backends that are enabled conditionally. In most cases, you won't need this option. from fastapi import Request from fastapi_users.authentication import AuthenticationBackend , BearerTransport , CookieTransport , JWTStrategy SECRET = \"SECRET\" bearer_transport = BearerTransport ( tokenUrl = \"auth/jwt/login\" ) cookie_transport = CookieTransport ( cookie_max_age = 3600 ) def get_jwt_strategy () -> JWTStrategy : return JWTStrategy ( secret = SECRET , lifetime_seconds = 3600 ) jwt_backend = AuthenticationBackend ( name = \"jwt\" , transport = bearer_transport , get_strategy = get_jwt_strategy , ) cookie_backend = AuthenticationBackend ( name = \"jwt\" , transport = cookie_transport , get_strategy = get_jwt_strategy , ) async def get_enabled_backends ( request : Request ): \"\"\"Return the enabled dependencies following custom logic.\"\"\" if request . url . path == \"/protected-route-only-jwt\" : return [ jwt_backend ] else : return [ cookie_backend , jwt_backend ] current_active_user = fastapi_users . current_user ( active = True , get_enabled_backends = get_enabled_backends ) @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( current_active_user )): return f \"Hello, { user . email } . You are authenticated with a cookie or a JWT.\" @app . get ( \"/protected-route-only-jwt\" ) def protected_route ( user : User = Depends ( current_active_user )): return f \"Hello, { user . email } . You are authenticated with a JWT.\"","title":"Dynamically enable authentication backends"},{"location":"usage/current-user/#in-a-path-operation","text":"If you don't need the user in the route logic, you can use this syntax: @app . get ( \"/protected-route\" , dependencies = [ Depends ( current_superuser )]) def protected_route (): return \"Hello, some user.\" You can read more about this in FastAPI docs .","title":"In a path operation"},{"location":"usage/flow/","text":"Flow \u00b6 This page will present you a complete registration and authentication flow once you've setup FastAPI Users . Each example will be presented with a cURL and an axios example. 1. Registration \u00b6 First step, of course, is to register as a user. Request \u00b6 cURL axios curl \\ -H \"Content-Type: application/json\" \\ -X POST \\ -d \"{\\\"email\\\": \\\"king.arthur@camelot.bt\\\",\\\"password\\\": \\\"guinevere\\\"}\" \\ http://localhost:8000/auth/register axios . post ( 'http://localhost:8000/auth/register' , { email : 'king.arthur@camelot.bt' , password : 'guinevere' , }) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } Info Several things to bear in mind: If you have defined other required fields in your User model (like a first name or a birthdate), you'll have to provide them in the payload. The user is active by default. The user cannot set is_active or is_superuser itself at registration. Only a superuser can do it by PATCHing the user. 2. Login \u00b6 Now, you can login as this new user. You can generate a login route for each authentication backend . Each backend will have a different response. Bearer + JWT \u00b6 Request \u00b6 cURL axios curl \\ -H \"Content-Type: multipart/form-data\" \\ -X POST \\ -F \"username=king.arthur@camelot.bt\" \\ -F \"password=guinevere\" \\ http://localhost:8000/auth/jwt/login const formData = new FormData (); formData . set ( 'username' , 'king.arthur@camelot.bt' ); formData . set ( 'password' , 'guinevere' ); axios . post ( 'http://localhost:8000/auth/jwt/login' , formData , { headers : { 'Content-Type' : 'multipart/form-data' , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Warning Notice that we don't send it as a JSON payload here but with form data instead. Also, the email is provided by a field named username . Response \u00b6 You'll get a JSON response looking like this: { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM\" , \"token_type\" : \"bearer\" } You can use this token to make authenticated requests as the user king.arthur@camelot.bt . We'll see how in the next section. Cookie + JWT \u00b6 Request \u00b6 cURL axios curl \\ -v \\ -H \"Content-Type: multipart/form-data\" \\ -X POST \\ -F \"username=king.arthur@camelot.bt\" \\ -F \"password=guinevere\" \\ http://localhost:8000/auth/cookie/login const formData = new FormData (); formData . set ( 'username' , 'king.arthur@camelot.bt' ); formData . set ( 'password' , 'guinevere' ); axios . post ( 'http://localhost:8000/auth/cookie/login' , formData , { headers : { 'Content-Type' : 'multipart/form-data' , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Warning Notice that we don't send it as a JSON payload here but with form data instead. Also, the email is provided by a field named username . Response \u00b6 You'll get an empty response. However, the response will come with a Set-Cookie header (that's why we added the -v option in cURL to see them). set-cookie: fastapiusersauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiYzYwNjBmMTEtNTM0OS00YTI0LThiNGEtYTJhODc1ZGM1Mzk1IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4OTQ3fQ.qNA4oPVYhoqrJIk-zvAyEfEVoEnP156G30H_SWEU0sU; HttpOnly; Max-Age=3600; Path=/; Secure You can make authenticated requests as the user king.arthur@camelot.bt by setting a Cookie header with this cookie. Tip The cookie backend is more suited for browsers, as they handle them automatically. This means that if you make a login request in the browser, it will automatically store the cookie and automatically send it in subsequent requests. 3. Get my profile \u00b6 Now that we can authenticate, we can get our own profile data. Depending on your authentication backend , the method to authenticate the request will vary. We'll stick with JWT from now on. Request \u00b6 cURL axios export TOKEN = \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM\" ; curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X GET \\ http://localhost:8000/users/me const TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM' ; axios . get ( 'http://localhost:8000/users/me' , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } Tip If you use one of the dependency callable to protect one of your own endpoint, you'll have to authenticate exactly in the same way. 4. Update my profile \u00b6 We can also update our own profile. For example, we can change our password like this. Request \u00b6 cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X PATCH \\ -d \"{\\\"password\\\": \\\"lancelot\\\"}\" \\ http://localhost:8000/users/me axios . patch ( 'http://localhost:8000/users/me' , { password : 'lancelot' , }, { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } Info Once again, the user cannot set is_active or is_superuser itself. Only a superuser can do it by PATCHing the user. 5. Become a superuser \ud83e\uddb8\ud83c\udffb\u200d\u2642\ufe0f \u00b6 If you want to manage the users of your application, you'll have to become a superuser . The very first superuser can only be set at database level : open it through a CLI or a GUI, find your user and set the is_superuser column/property to true . 5.1. Get the profile of any user \u00b6 Now that you are a superuser, you can leverage the power of superuser routes . You can for example get the profile of any user in the database given its id. Request \u00b6 cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X GET \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios . get ( 'http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476' , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 5.1. Update any user \u00b6 We can now update the profile of any user. For example, we can promote it as superuser. Request \u00b6 cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X PATCH \\ -d \"{\\\"is_superuser\\\": true}\" \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios . patch ( 'http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476' , { is_superuser : true , }, { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : true } 5.2. Delete any user \u00b6 Finally, we can delete a user. Request \u00b6 cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X DELETE \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios . delete ( 'http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476' , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get an empty response. 6. Logout \u00b6 We can also end the session. Request \u00b6 cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Cookie: fastapiusersauth= $TOKEN \" \\ -X POST \\ http://localhost:8000/auth/cookie/logout axios . post ( 'http://localhost:8000/auth/cookie/logout' , null , { headers : { 'Cookie' : `fastapiusersauth= ${ TOKEN } ` , }, } ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Response \u00b6 You'll get an empty response. Conclusion \u00b6 That's it! You now have a good overview of how you can manage the users through the API. Be sure to check the Routes page to have all the details about each endpoints.","title":"Flow"},{"location":"usage/flow/#flow","text":"This page will present you a complete registration and authentication flow once you've setup FastAPI Users . Each example will be presented with a cURL and an axios example.","title":"Flow"},{"location":"usage/flow/#1-registration","text":"First step, of course, is to register as a user.","title":"1. Registration"},{"location":"usage/flow/#request","text":"cURL axios curl \\ -H \"Content-Type: application/json\" \\ -X POST \\ -d \"{\\\"email\\\": \\\"king.arthur@camelot.bt\\\",\\\"password\\\": \\\"guinevere\\\"}\" \\ http://localhost:8000/auth/register axios . post ( 'http://localhost:8000/auth/register' , { email : 'king.arthur@camelot.bt' , password : 'guinevere' , }) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response","text":"You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } Info Several things to bear in mind: If you have defined other required fields in your User model (like a first name or a birthdate), you'll have to provide them in the payload. The user is active by default. The user cannot set is_active or is_superuser itself at registration. Only a superuser can do it by PATCHing the user.","title":"Response"},{"location":"usage/flow/#2-login","text":"Now, you can login as this new user. You can generate a login route for each authentication backend . Each backend will have a different response.","title":"2. Login"},{"location":"usage/flow/#bearer-jwt","text":"","title":"Bearer + JWT"},{"location":"usage/flow/#request_1","text":"cURL axios curl \\ -H \"Content-Type: multipart/form-data\" \\ -X POST \\ -F \"username=king.arthur@camelot.bt\" \\ -F \"password=guinevere\" \\ http://localhost:8000/auth/jwt/login const formData = new FormData (); formData . set ( 'username' , 'king.arthur@camelot.bt' ); formData . set ( 'password' , 'guinevere' ); axios . post ( 'http://localhost:8000/auth/jwt/login' , formData , { headers : { 'Content-Type' : 'multipart/form-data' , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Warning Notice that we don't send it as a JSON payload here but with form data instead. Also, the email is provided by a field named username .","title":"Request"},{"location":"usage/flow/#response_1","text":"You'll get a JSON response looking like this: { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM\" , \"token_type\" : \"bearer\" } You can use this token to make authenticated requests as the user king.arthur@camelot.bt . We'll see how in the next section.","title":"Response"},{"location":"usage/flow/#cookie-jwt","text":"","title":"Cookie + JWT"},{"location":"usage/flow/#request_2","text":"cURL axios curl \\ -v \\ -H \"Content-Type: multipart/form-data\" \\ -X POST \\ -F \"username=king.arthur@camelot.bt\" \\ -F \"password=guinevere\" \\ http://localhost:8000/auth/cookie/login const formData = new FormData (); formData . set ( 'username' , 'king.arthur@camelot.bt' ); formData . set ( 'password' , 'guinevere' ); axios . post ( 'http://localhost:8000/auth/cookie/login' , formData , { headers : { 'Content-Type' : 'multipart/form-data' , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error )); Warning Notice that we don't send it as a JSON payload here but with form data instead. Also, the email is provided by a field named username .","title":"Request"},{"location":"usage/flow/#response_2","text":"You'll get an empty response. However, the response will come with a Set-Cookie header (that's why we added the -v option in cURL to see them). set-cookie: fastapiusersauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiYzYwNjBmMTEtNTM0OS00YTI0LThiNGEtYTJhODc1ZGM1Mzk1IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4OTQ3fQ.qNA4oPVYhoqrJIk-zvAyEfEVoEnP156G30H_SWEU0sU; HttpOnly; Max-Age=3600; Path=/; Secure You can make authenticated requests as the user king.arthur@camelot.bt by setting a Cookie header with this cookie. Tip The cookie backend is more suited for browsers, as they handle them automatically. This means that if you make a login request in the browser, it will automatically store the cookie and automatically send it in subsequent requests.","title":"Response"},{"location":"usage/flow/#3-get-my-profile","text":"Now that we can authenticate, we can get our own profile data. Depending on your authentication backend , the method to authenticate the request will vary. We'll stick with JWT from now on.","title":"3. Get my profile"},{"location":"usage/flow/#request_3","text":"cURL axios export TOKEN = \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM\" ; curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X GET \\ http://localhost:8000/users/me const TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM' ; axios . get ( 'http://localhost:8000/users/me' , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_3","text":"You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } Tip If you use one of the dependency callable to protect one of your own endpoint, you'll have to authenticate exactly in the same way.","title":"Response"},{"location":"usage/flow/#4-update-my-profile","text":"We can also update our own profile. For example, we can change our password like this.","title":"4. Update my profile"},{"location":"usage/flow/#request_4","text":"cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X PATCH \\ -d \"{\\\"password\\\": \\\"lancelot\\\"}\" \\ http://localhost:8000/users/me axios . patch ( 'http://localhost:8000/users/me' , { password : 'lancelot' , }, { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_4","text":"You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } Info Once again, the user cannot set is_active or is_superuser itself. Only a superuser can do it by PATCHing the user.","title":"Response"},{"location":"usage/flow/#5-become-a-superuser","text":"If you want to manage the users of your application, you'll have to become a superuser . The very first superuser can only be set at database level : open it through a CLI or a GUI, find your user and set the is_superuser column/property to true .","title":"5. Become a superuser \ud83e\uddb8\ud83c\udffb\u200d\u2642\ufe0f"},{"location":"usage/flow/#51-get-the-profile-of-any-user","text":"Now that you are a superuser, you can leverage the power of superuser routes . You can for example get the profile of any user in the database given its id.","title":"5.1. Get the profile of any user"},{"location":"usage/flow/#request_5","text":"cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X GET \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios . get ( 'http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476' , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_5","text":"You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false }","title":"Response"},{"location":"usage/flow/#51-update-any-user","text":"We can now update the profile of any user. For example, we can promote it as superuser.","title":"5.1. Update any user"},{"location":"usage/flow/#request_6","text":"cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X PATCH \\ -d \"{\\\"is_superuser\\\": true}\" \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios . patch ( 'http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476' , { is_superuser : true , }, { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_6","text":"You'll get a JSON response looking like this: { \"id\" : \"4fd3477b-eccf-4ee3-8f7d-68ad72261476\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : true }","title":"Response"},{"location":"usage/flow/#52-delete-any-user","text":"Finally, we can delete a user.","title":"5.2. Delete any user"},{"location":"usage/flow/#request_7","text":"cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X DELETE \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios . delete ( 'http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476' , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, }, ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_7","text":"You'll get an empty response.","title":"Response"},{"location":"usage/flow/#6-logout","text":"We can also end the session.","title":"6. Logout"},{"location":"usage/flow/#request_8","text":"cURL axios curl \\ -H \"Content-Type: application/json\" \\ -H \"Cookie: fastapiusersauth= $TOKEN \" \\ -X POST \\ http://localhost:8000/auth/cookie/logout axios . post ( 'http://localhost:8000/auth/cookie/logout' , null , { headers : { 'Cookie' : `fastapiusersauth= ${ TOKEN } ` , }, } ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_8","text":"You'll get an empty response.","title":"Response"},{"location":"usage/flow/#conclusion","text":"That's it! You now have a good overview of how you can manage the users through the API. Be sure to check the Routes page to have all the details about each endpoints.","title":"Conclusion"},{"location":"usage/routes/","text":"Routes \u00b6 You'll find here the routes exposed by FastAPI Users . Note that you can also review them through the interactive API docs . Auth router \u00b6 Each authentication backend you generate a router for will produce the following routes. Take care about the prefix you gave it, especially if you have several backends. POST /login \u00b6 Login a user against the method named name . Check the corresponding authentication method to view the success response. Payload ( application/x-www-form-urlencoded ) username=king.arthur@camelot.bt&password=guinevere 422 Validation Error 400 Bad Request Bad credentials or the user is inactive. { \"detail\" : \"LOGIN_BAD_CREDENTIALS\" } 400 Bad Request The user is not verified. { \"detail\" : \"LOGIN_USER_NOT_VERIFIED\" } POST /logout \u00b6 Logout the authenticated user against the method named name . Check the corresponding authentication method to view the success response. 401 Unauthorized Missing token or inactive user. 200 OK The logout process was successful. Register router \u00b6 POST /register \u00b6 Register a new user. Will call the on_after_register handler on successful registration. Payload { \"email\" : \"king.arthur@camelot.bt\" , \"password\" : \"guinevere\" } 201 Created { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 422 Validation Error 400 Bad Request A user already exists with this email. { \"detail\" : \"REGISTER_USER_ALREADY_EXISTS\" } 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"REGISTER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } } Reset password router \u00b6 POST /forgot-password \u00b6 Request a reset password procedure. Will generate a temporary token and call the on_after_forgot_password handler if the user exists. To prevent malicious users from guessing existing users in your database, the route will always return a 202 Accepted response, even if the user requested does not exist. Payload { \"email\" : \"king.arthur@camelot.bt\" } 202 Accepted POST /reset-password \u00b6 Reset a password. Requires the token generated by the /forgot-password route. Payload { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"password\" : \"merlin\" } 200 OK 422 Validation Error 400 Bad Request Bad or expired token. { \"detail\" : \"RESET_PASSWORD_BAD_TOKEN\" } 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"REGISTER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } } Verify router \u00b6 POST /request-verify-token \u00b6 Request a user to verify their e-mail. Will generate a temporary token and call the on_after_request_verify handler if the user exists , active and not already verified . To prevent malicious users from guessing existing users in your database, the route will always return a 202 Accepted response, even if the user requested does not exist, not active or already verified. Payload { \"email\" : \"king.arthur@camelot.bt\" } 202 Accepted POST /verify \u00b6 Verify a user. Requires the token generated by the /request-verify-token route. Will call the call the on_after_verify handler on success. Payload { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } 200 OK 422 Validation Error 400 Bad Request Bad token, not existing user or not the e-mail currently set for the user. { \"detail\" : \"VERIFY_USER_BAD_TOKEN\" } 400 Bad Request The user is already verified. { \"detail\" : \"VERIFY_USER_ALREADY_VERIFIED\" } OAuth router \u00b6 Each OAuth router you define will expose the two following routes. GET /authorize \u00b6 Return the authorization URL for the OAuth service where you should redirect your user. Query parameters scopes : Optional list of scopes to ask for. Expected format: scopes=a&scopes=b . 200 OK { \"authorization_url\" : \"https://www.tintagel.bt/oauth/authorize?client_id=CLIENT_ID&scopes=a+b&redirect_uri=https://www.camelot.bt/oauth/callback\" } 422 Validation Error Invalid parameters - e.g. unknown authentication backend. GET /callback \u00b6 Handle the OAuth callback. Query parameters code : OAuth callback code. state : State token. error : OAuth error. Depending on the situation, several things can happen: The OAuth account exists in database and is linked to a user: OAuth account is updated in database with fresh access token. The user is authenticated following the chosen authentication method . The OAuth account doesn't exist in database but a user with the same email address exists: OAuth account is linked to the user. The user is authenticated following the chosen authentication method . The OAuth account doesn't exist in database and no user with the email address exists: A new user is created and linked to the OAuth account. The user is authenticated following the chosen authentication method . 400 Bad Request Invalid token. 400 Bad Request User is inactive. { \"detail\" : \"LOGIN_BAD_CREDENTIALS\" } Users router \u00b6 GET /me \u00b6 Return the current authenticated active user. 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 401 Unauthorized Missing token or inactive user. PATCH /me \u00b6 Update the current authenticated active user. Payload { \"email\" : \"king.arthur@tintagel.bt\" , \"password\" : \"merlin\" } 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@tintagel.bt\" , \"is_active\" : true , \"is_superuser\" : false } 401 Unauthorized Missing token or inactive user. 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"UPDATE_USER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } } 400 Bad Request A user with this email already exists. { \"detail\" : \"UPDATE_USER_EMAIL_ALREADY_EXISTS\" } 422 Validation Error GET /{user_id} \u00b6 Return the user with id user_id . 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 401 Unauthorized Missing token or inactive user. 403 Forbidden Not a superuser. 404 Not found The user does not exist. PATCH /{user_id} \u00b6 Update the user with id user_id . Payload { \"email\" : \"king.arthur@tintagel.bt\" , \"password\" : \"merlin\" , \"is_active\" : false , \"is_superuser\" : true } 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : false , \"is_superuser\" : true } 401 Unauthorized Missing token or inactive user. 403 Forbidden Not a superuser. 404 Not found The user does not exist. 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"UPDATE_USER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } } 400 Bad Request A user with this email already exists. { \"detail\" : \"UPDATE_USER_EMAIL_ALREADY_EXISTS\" } DELETE /{user_id} \u00b6 Delete the user with id user_id . 204 No content 401 Unauthorized Missing token or inactive user. 403 Forbidden Not a superuser. 404 Not found The user does not exist.","title":"Routes"},{"location":"usage/routes/#routes","text":"You'll find here the routes exposed by FastAPI Users . Note that you can also review them through the interactive API docs .","title":"Routes"},{"location":"usage/routes/#auth-router","text":"Each authentication backend you generate a router for will produce the following routes. Take care about the prefix you gave it, especially if you have several backends.","title":"Auth router"},{"location":"usage/routes/#post-login","text":"Login a user against the method named name . Check the corresponding authentication method to view the success response. Payload ( application/x-www-form-urlencoded ) username=king.arthur@camelot.bt&password=guinevere 422 Validation Error 400 Bad Request Bad credentials or the user is inactive. { \"detail\" : \"LOGIN_BAD_CREDENTIALS\" } 400 Bad Request The user is not verified. { \"detail\" : \"LOGIN_USER_NOT_VERIFIED\" }","title":"POST /login"},{"location":"usage/routes/#post-logout","text":"Logout the authenticated user against the method named name . Check the corresponding authentication method to view the success response. 401 Unauthorized Missing token or inactive user. 200 OK The logout process was successful.","title":"POST /logout"},{"location":"usage/routes/#register-router","text":"","title":"Register router"},{"location":"usage/routes/#post-register","text":"Register a new user. Will call the on_after_register handler on successful registration. Payload { \"email\" : \"king.arthur@camelot.bt\" , \"password\" : \"guinevere\" } 201 Created { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 422 Validation Error 400 Bad Request A user already exists with this email. { \"detail\" : \"REGISTER_USER_ALREADY_EXISTS\" } 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"REGISTER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } }","title":"POST /register"},{"location":"usage/routes/#reset-password-router","text":"","title":"Reset password router"},{"location":"usage/routes/#post-forgot-password","text":"Request a reset password procedure. Will generate a temporary token and call the on_after_forgot_password handler if the user exists. To prevent malicious users from guessing existing users in your database, the route will always return a 202 Accepted response, even if the user requested does not exist. Payload { \"email\" : \"king.arthur@camelot.bt\" } 202 Accepted","title":"POST /forgot-password"},{"location":"usage/routes/#post-reset-password","text":"Reset a password. Requires the token generated by the /forgot-password route. Payload { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"password\" : \"merlin\" } 200 OK 422 Validation Error 400 Bad Request Bad or expired token. { \"detail\" : \"RESET_PASSWORD_BAD_TOKEN\" } 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"REGISTER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } }","title":"POST /reset-password"},{"location":"usage/routes/#verify-router","text":"","title":"Verify router"},{"location":"usage/routes/#post-request-verify-token","text":"Request a user to verify their e-mail. Will generate a temporary token and call the on_after_request_verify handler if the user exists , active and not already verified . To prevent malicious users from guessing existing users in your database, the route will always return a 202 Accepted response, even if the user requested does not exist, not active or already verified. Payload { \"email\" : \"king.arthur@camelot.bt\" } 202 Accepted","title":"POST /request-verify-token"},{"location":"usage/routes/#post-verify","text":"Verify a user. Requires the token generated by the /request-verify-token route. Will call the call the on_after_verify handler on success. Payload { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } 200 OK 422 Validation Error 400 Bad Request Bad token, not existing user or not the e-mail currently set for the user. { \"detail\" : \"VERIFY_USER_BAD_TOKEN\" } 400 Bad Request The user is already verified. { \"detail\" : \"VERIFY_USER_ALREADY_VERIFIED\" }","title":"POST /verify"},{"location":"usage/routes/#oauth-router","text":"Each OAuth router you define will expose the two following routes.","title":"OAuth router"},{"location":"usage/routes/#get-authorize","text":"Return the authorization URL for the OAuth service where you should redirect your user. Query parameters scopes : Optional list of scopes to ask for. Expected format: scopes=a&scopes=b . 200 OK { \"authorization_url\" : \"https://www.tintagel.bt/oauth/authorize?client_id=CLIENT_ID&scopes=a+b&redirect_uri=https://www.camelot.bt/oauth/callback\" } 422 Validation Error Invalid parameters - e.g. unknown authentication backend.","title":"GET /authorize"},{"location":"usage/routes/#get-callback","text":"Handle the OAuth callback. Query parameters code : OAuth callback code. state : State token. error : OAuth error. Depending on the situation, several things can happen: The OAuth account exists in database and is linked to a user: OAuth account is updated in database with fresh access token. The user is authenticated following the chosen authentication method . The OAuth account doesn't exist in database but a user with the same email address exists: OAuth account is linked to the user. The user is authenticated following the chosen authentication method . The OAuth account doesn't exist in database and no user with the email address exists: A new user is created and linked to the OAuth account. The user is authenticated following the chosen authentication method . 400 Bad Request Invalid token. 400 Bad Request User is inactive. { \"detail\" : \"LOGIN_BAD_CREDENTIALS\" }","title":"GET /callback"},{"location":"usage/routes/#users-router","text":"","title":"Users router"},{"location":"usage/routes/#get-me","text":"Return the current authenticated active user. 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 401 Unauthorized Missing token or inactive user.","title":"GET /me"},{"location":"usage/routes/#patch-me","text":"Update the current authenticated active user. Payload { \"email\" : \"king.arthur@tintagel.bt\" , \"password\" : \"merlin\" } 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@tintagel.bt\" , \"is_active\" : true , \"is_superuser\" : false } 401 Unauthorized Missing token or inactive user. 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"UPDATE_USER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } } 400 Bad Request A user with this email already exists. { \"detail\" : \"UPDATE_USER_EMAIL_ALREADY_EXISTS\" } 422 Validation Error","title":"PATCH /me"},{"location":"usage/routes/#get-user_id","text":"Return the user with id user_id . 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : true , \"is_superuser\" : false } 401 Unauthorized Missing token or inactive user. 403 Forbidden Not a superuser. 404 Not found The user does not exist.","title":"GET /{user_id}"},{"location":"usage/routes/#patch-user_id","text":"Update the user with id user_id . Payload { \"email\" : \"king.arthur@tintagel.bt\" , \"password\" : \"merlin\" , \"is_active\" : false , \"is_superuser\" : true } 200 OK { \"id\" : \"57cbb51a-ab71-4009-8802-3f54b4f2e23\" , \"email\" : \"king.arthur@camelot.bt\" , \"is_active\" : false , \"is_superuser\" : true } 401 Unauthorized Missing token or inactive user. 403 Forbidden Not a superuser. 404 Not found The user does not exist. 400 Bad Request Password validation failed. { \"detail\" : { \"code\" : \"UPDATE_USER_INVALID_PASSWORD\" , \"reason\" : \"Password should be at least 3 characters\" } } 400 Bad Request A user with this email already exists. { \"detail\" : \"UPDATE_USER_EMAIL_ALREADY_EXISTS\" }","title":"PATCH /{user_id}"},{"location":"usage/routes/#delete-user_id","text":"Delete the user with id user_id . 204 No content 401 Unauthorized Missing token or inactive user. 403 Forbidden Not a superuser. 404 Not found The user does not exist.","title":"DELETE /{user_id}"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index 289fa8c6..0428608a 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,182 +2,182 @@ None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily None - 2022-01-07 + 2022-01-09 daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 43dee72f..877fda66 100644 Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ diff --git a/src/db_sqlalchemy_oauth.py b/src/db_sqlalchemy_oauth.py index 0169d626..7ed34081 100644 --- a/src/db_sqlalchemy_oauth.py +++ b/src/db_sqlalchemy_oauth.py @@ -17,7 +17,7 @@ Base: DeclarativeMeta = declarative_base() class UserTable(Base, SQLAlchemyBaseUserTable): - oauth_accounts = relationship("OAuthAccount") + oauth_accounts = relationship("OAuthAccountTable") class OAuthAccountTable(SQLAlchemyBaseOAuthAccountTable, Base):