diff --git a/configuration/routers/reset/index.html b/configuration/routers/reset/index.html
index bb882c59..2a314b0c 100644
--- a/configuration/routers/reset/index.html
+++ b/configuration/routers/reset/index.html
@@ -509,6 +509,13 @@
After forgot password
+
+
+
+
+ After reset password
+
+
@@ -778,6 +785,13 @@
After forgot password
+
+
+
+
+ After reset password
+
+
@@ -841,6 +855,24 @@
tags=["auth"],
)
+After reset password
+You can provide a custom function to be called after a successful password reset. It is called with two arguments:
+
+- The user which has reset their password.
+- The original
Request
object.
+
+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.
+You can define it as an async
or standard method.
+Example:
+def on_after_reset_password(user: UserDB, request: Request):
+ print(f"User {user.id} has reset their password.")
+
+app.include_router(
+ fastapi_users.get_reset_password_router("SECRET", after_reset_password=on_after_reset_password),
+ prefix="/auth",
+ tags=["auth"],
+)
+
diff --git a/search/search_index.json b/search/search_index.json
index 406ec3fc..e8cb02ee 100644
--- a/search/search_index.json
+++ b/search/search_index.json
@@ -1 +1 @@
-{"config":{"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://frankie567.github.io/fastapi-users/ Source Code : https://github.com/frankie567/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 OAuth2 flow Dependency callables to inject current user in route Customizable database backend SQLAlchemy async backend included thanks to encode/databases MongoDB async backend included thanks to mongodb/motor Tortoise ORM backend included Multiple customizable authentication backends JWT authentication backend included Cookie authentication backend included Full OpenAPI schema support, even with several authentication backends Development \u00b6 Setup environement \u00b6 You should have Pipenv installed. Then, you can install the dependencies with: pipenv install --dev After that, activate the virtual environment: pipenv shell 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://frankie567.github.io/fastapi-users/ Source Code : https://github.com/frankie567/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 OAuth2 flow Dependency callables to inject current user in route Customizable database backend SQLAlchemy async backend included thanks to encode/databases MongoDB async backend included thanks to mongodb/motor Tortoise ORM backend included Multiple customizable authentication backends JWT authentication backend included Cookie authentication backend included Full OpenAPI schema support, even with several authentication backends","title":"Features"},{"location":"#development","text":"","title":"Development"},{"location":"#setup-environement","text":"You should have Pipenv installed. Then, you can install the dependencies with: pipenv install --dev After that, activate the virtual environment: pipenv shell","title":"Setup environement"},{"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 [ sqlalchemy ] With MongoDB support \u00b6 pip install fastapi-users [ mongodb ] With Tortoise ORM support \u00b6 pip install fastapi-users [ tortoise-orm ] 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 [ sqlalchemy ]","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 ] That's it! Now, let's have a look at our User model .","title":"With Tortoise ORM 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 import databases import sqlalchemy from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () MongoDB \u00b6 import motor.motor_asyncio from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) Tortoise ORM \u00b6 from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) What now? \u00b6 You're ready to go! Be sure to check the Usage section to understand how yo 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":"import databases import sqlalchemy from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect ()","title":"SQLAlchemy"},{"location":"configuration/full_example/#mongodb","text":"import motor.motor_asyncio from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ])","title":"MongoDB"},{"location":"configuration/full_example/#tortoise-orm","text":"from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ])","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 yo work with FastAPI Users .","title":"What now?"},{"location":"configuration/model/","text":"User model \u00b6 FastAPI Users defines a minimal User model for authentication purposes. It is structured like this: id ( UUID4 ) \u2013 Unique identifier of the user. Default 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. Default to True . is_verified ( bool ) \u2013 Whether or not the user is verified. Optional but helpful with the verify router logic. Default to False . is_superuser ( bool ) \u2013 Whether or not the user is a superuser. Useful to implement administration logic. Default 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 ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass You can of course add your own properties there to fit to your needs! Password validation \u00b6 FastAPI Users doesn't provide a default password validation, but you can implement it easily with a Pydantic validator on the UserCreate class. Here is a simple example to check if the password is at least six characters long: from fastapi_users import models from pydantic import validator class UserCreate ( models . BaseUserCreate ): @validator ( 'password' ) def valid_password ( cls , v : str ): if len ( v ) < 6 : raise ValueError ( 'Password should be at least 6 characters' ) return v Next steps \u00b6 Depending on your database backend, the database configuration will differ a bit. I'm using SQLAlchemy I'm using MongoDB I'm using Tortoise ORM","title":"User model"},{"location":"configuration/model/#user-model","text":"FastAPI Users defines a minimal User model for authentication purposes. It is structured like this: id ( UUID4 ) \u2013 Unique identifier of the user. Default 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. Default to True . is_verified ( bool ) \u2013 Whether or not the user is verified. Optional but helpful with the verify router logic. Default to False . is_superuser ( bool ) \u2013 Whether or not the user is a superuser. Useful to implement administration logic. Default to False .","title":"User model"},{"location":"configuration/model/#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 ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass You can of course add your own properties there to fit to your needs!","title":"Define your models"},{"location":"configuration/model/#password-validation","text":"FastAPI Users doesn't provide a default password validation, but you can implement it easily with a Pydantic validator on the UserCreate class. Here is a simple example to check if the password is at least six characters long: from fastapi_users import models from pydantic import validator class UserCreate ( models . BaseUserCreate ): @validator ( 'password' ) def valid_password ( cls , v : str ): if len ( v ) < 6 : raise ValueError ( 'Password should be at least 6 characters' ) return v","title":"Password validation"},{"location":"configuration/model/#next-steps","text":"Depending on your database backend, the database configuration will differ a bit. I'm using SQLAlchemy I'm using MongoDB I'm using Tortoise ORM","title":"Next steps"},{"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 [ sqlalchemy,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 ( User , 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. Default 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 table for storing the OAuth account model. We provide a base one for this: from fastapi_users.db.sqlalchemy import SQLAlchemyBaseOAuthAccountTable class OAuthAccount ( SQLAlchemyBaseOAuthAccountTable , Base ): pass Then, you should declare it on the database adapter: user_db = SQLAlchemyUserDatabase ( UserDB , database , User . __table__ , OAuthAccount . __table__ ) 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.db.tortoise import TortoiseBaseOAuthAccountModel class OAuthAccount ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.User\" , 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: user_db = TortoiseUserDatabase ( UserDB , User , OAuthAccount ) Generate a router \u00b6 Once you have a FastAPIUsers instance, you can make it generate a single OAuth router for the given client. from fastapi import FastAPI from fastapi_users import FastAPIUsers from httpx_oauth.clients.google import GoogleOAuth2 google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB ) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ]) After register \u00b6 You can provide a custom function to be called after a successful registration. It is called with two argument : the user that has just registered, and the original Request object . Typically, you'll want to send a welcome e-mail or add it to your marketing analytics pipeline. You can define it as an async or standard method. Example: from fastapi import FastAPI from fastapi_users import FastAPIUsers from httpx_oauth.clients.google import GoogleOAuth2 def on_after_register ( user : UserDB , request : Request ): print ( f \"User { user . id } has registered.\" ) google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB ) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , 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 import databases import sqlalchemy from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from httpx_oauth.clients.google import GoogleOAuth2 from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass class OAuthAccount ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ oauth_accounts = OAuthAccount . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users , oauth_accounts ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ]) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () MongoDB \u00b6 import motor.motor_asyncio from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ]) Tortoise ORM \u00b6 from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import ( TortoiseBaseOAuthAccountModel , TortoiseBaseUserModel , TortoiseUserDatabase , ) from httpx_oauth.clients.google import GoogleOAuth2 from tortoise import fields from tortoise.contrib.fastapi import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass class UserModel ( TortoiseBaseUserModel ): pass class OAuthAccountModel ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"oauth_accounts\" ) user_db = TortoiseUserDatabase ( UserDB , UserModel , OAuthAccountModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ])","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 [ sqlalchemy,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 ( User , 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. Default 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 table for storing the OAuth account model. We provide a base one for this: from fastapi_users.db.sqlalchemy import SQLAlchemyBaseOAuthAccountTable class OAuthAccount ( SQLAlchemyBaseOAuthAccountTable , Base ): pass Then, you should declare it on the database adapter: user_db = SQLAlchemyUserDatabase ( UserDB , database , User . __table__ , OAuthAccount . __table__ )","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.db.tortoise import TortoiseBaseOAuthAccountModel class OAuthAccount ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.User\" , 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: user_db = TortoiseUserDatabase ( UserDB , User , 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 the given client. from fastapi import FastAPI from fastapi_users import FastAPIUsers from httpx_oauth.clients.google import GoogleOAuth2 google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB ) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ])","title":"Generate a router"},{"location":"configuration/oauth/#after-register","text":"You can provide a custom function to be called after a successful registration. It is called with two argument : the user that has just registered, and the original Request object . Typically, you'll want to send a welcome e-mail or add it to your marketing analytics pipeline. You can define it as an async or standard method. Example: from fastapi import FastAPI from fastapi_users import FastAPIUsers from httpx_oauth.clients.google import GoogleOAuth2 def on_after_register ( user : UserDB , request : Request ): print ( f \"User { user . id } has registered.\" ) google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB ) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ])","title":"After register"},{"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":"import databases import sqlalchemy from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from httpx_oauth.clients.google import GoogleOAuth2 from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass class OAuthAccount ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ oauth_accounts = OAuthAccount . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users , oauth_accounts ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ]) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect ()","title":"SQLAlchemy"},{"location":"configuration/oauth/#mongodb_1","text":"import motor.motor_asyncio from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ])","title":"MongoDB"},{"location":"configuration/oauth/#tortoise-orm_1","text":"from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import ( TortoiseBaseOAuthAccountModel , TortoiseBaseUserModel , TortoiseUserDatabase , ) from httpx_oauth.clients.google import GoogleOAuth2 from tortoise import fields from tortoise.contrib.fastapi import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass class UserModel ( TortoiseBaseUserModel ): pass class OAuthAccountModel ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"oauth_accounts\" ) user_db = TortoiseUserDatabase ( UserDB , UserModel , OAuthAccountModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ])","title":"Tortoise ORM"},{"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 (if applicable routes). More on this in the routers documentation . Provided methods \u00b6 JWT authentication Cookie authentication","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 (if applicable routes). More on this in the routers documentation .","title":"How it works?"},{"location":"configuration/authentication/#provided-methods","text":"JWT authentication Cookie authentication","title":"Provided methods"},{"location":"configuration/authentication/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 CookieAuthentication SECRET = \"SECRET\" auth_backends = [] cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) auth_backends . append ( cookie_authentication ) As you can see, instantiation is quite simple. You just have to define a constant SECRET which is used to encode the token and the lifetime of the cookie (in seconds). You can also define the parameters for the generated cookie: cookie_name ( fastapiusersauth ): Name of the 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'. Tip You can also optionally define the name . It's useful in the case you wish to have several backends of the same class. Each backend should have a unique name. Defaults to cookie . cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 , name = \"my-cookie\" , ) Tip The value of the cookie is actually a JWT. This authentication backend shares most of its logic with the JWT one. 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. Next steps \u00b6 We will now configure the main FastAPI Users object that will expose the routers .","title":"Cookie"},{"location":"configuration/authentication/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/cookie/#configuration","text":"from fastapi_users.authentication import CookieAuthentication SECRET = \"SECRET\" auth_backends = [] cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) auth_backends . append ( cookie_authentication ) As you can see, instantiation is quite simple. You just have to define a constant SECRET which is used to encode the token and the lifetime of the cookie (in seconds). You can also define the parameters for the generated cookie: cookie_name ( fastapiusersauth ): Name of the 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'. Tip You can also optionally define the name . It's useful in the case you wish to have several backends of the same class. Each backend should have a unique name. Defaults to cookie . cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 , name = \"my-cookie\" , ) Tip The value of the cookie is actually a JWT. This authentication backend shares most of its logic with the JWT one.","title":"Configuration"},{"location":"configuration/authentication/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/cookie/#logout","text":"This method will remove the authentication cookie: 200 OK Check documentation about logout route .","title":"Logout"},{"location":"configuration/authentication/cookie/#authentication","text":"This method expects that you provide a valid cookie in the headers.","title":"Authentication"},{"location":"configuration/authentication/cookie/#next-steps","text":"We will now configure the main FastAPI Users object that will expose the routers .","title":"Next steps"},{"location":"configuration/authentication/jwt/","text":"JWT \u00b6 JSON Web Token (JWT) is an internet standard for creating access tokens based on JSON. Configuration \u00b6 from fastapi_users.authentication import JWTAuthentication SECRET = \"SECRET\" auth_backends = [] jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) auth_backends . append ( jwt_authentication ) As you can see, instantiation is quite simple. You just have to define a constant SECRET which is used to encode the token and the lifetime of token (in seconds). Tip You can also optionally define the name . It's useful in the case you wish to have several backends of the same class. Each backend should have a unique name. Defaults to jwt . jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , name = \"my-jwt\" , ) Login \u00b6 This method will return a JWT token upon successful login: 200 OK { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"token_type\" : \"bearer\" } Check documentation about login route . Logout \u00b6 This backend does not provide a logout method (a JWT is valid until it expires). Authentication \u00b6 This method expects that you provide a Bearer authentication with a valid JWT. curl http://localhost:9000/protected-route -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI' Tip: Refresh \u00b6 The default implementation does not provide a mechanism to refresh the JWT. However, you can implement it quite easily like this: from fastapi import Depends , Response @router . post ( \"/auth/jwt/refresh\" ) async def refresh_jwt ( response : Response , user = Depends ( fastapi_users . get_current_active_user )): return await jwt_authentication . get_login_response ( user , response ) Next steps \u00b6 We will now configure the main FastAPI Users object that will expose the routers .","title":"JWT"},{"location":"configuration/authentication/jwt/#jwt","text":"JSON Web Token (JWT) is an internet standard for creating access tokens based on JSON.","title":"JWT"},{"location":"configuration/authentication/jwt/#configuration","text":"from fastapi_users.authentication import JWTAuthentication SECRET = \"SECRET\" auth_backends = [] jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) auth_backends . append ( jwt_authentication ) As you can see, instantiation is quite simple. You just have to define a constant SECRET which is used to encode the token and the lifetime of token (in seconds). Tip You can also optionally define the name . It's useful in the case you wish to have several backends of the same class. Each backend should have a unique name. Defaults to jwt . jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , name = \"my-jwt\" , )","title":"Configuration"},{"location":"configuration/authentication/jwt/#login","text":"This method will return a JWT token 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/jwt/#logout","text":"This backend does not provide a logout method (a JWT is valid until it expires).","title":"Logout"},{"location":"configuration/authentication/jwt/#authentication","text":"This method expects that you provide a Bearer authentication with a valid JWT. curl http://localhost:9000/protected-route -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI'","title":"Authentication"},{"location":"configuration/authentication/jwt/#tip-refresh","text":"The default implementation does not provide a mechanism to refresh the JWT. However, you can implement it quite easily like this: from fastapi import Depends , Response @router . post ( \"/auth/jwt/refresh\" ) async def refresh_jwt ( response : Response , user = Depends ( fastapi_users . get_current_active_user )): return await jwt_authentication . get_login_response ( user , response )","title":"Tip: Refresh"},{"location":"configuration/authentication/jwt/#next-steps","text":"We will now configure the main FastAPI Users object that will expose the routers .","title":"Next steps"},{"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 import FastAPI from fastapi_users import models from fastapi_users.db import MongoDBUserDatabase class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] app = FastAPI () user_db = 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. Create it like this. import motor.motor_asyncio from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import MongoDBUserDatabase class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] app = FastAPI () user_db = 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 . Next steps \u00b6 We will now configure an authentication method .","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 import FastAPI from fastapi_users import models from fastapi_users.db import MongoDBUserDatabase class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] app = FastAPI () user_db = 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. Create it like this. import motor.motor_asyncio from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import MongoDBUserDatabase class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] app = FastAPI () user_db = 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/mongodb/#next-steps","text":"We will now configure an authentication method .","title":"Next steps"},{"location":"configuration/databases/sqlalchemy/","text":"SQLAlchemy \u00b6 FastAPI Users provides the necessary tools to work with SQL databases thanks to SQLAlchemy Core and encode/databases package for full async support. Installation \u00b6 Install the database driver that corresponds to your DBMS: pip install databases [ postgresql ] pip install databases [ mysql ] pip install databases [ sqlite ] For the sake of this tutorial from now on, we'll use a simple SQLite databse. Setup User table \u00b6 Let's create a metadata object and declare our User table. import databases import sqlalchemy from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite:///./test.db\" database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) app = FastAPI () @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () 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! Create the tables \u00b6 We'll now create an SQLAlchemy engine and ask it to create all the defined tables. import databases import sqlalchemy from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite:///./test.db\" database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) app = FastAPI () @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See Alembic . Create the database adapter \u00b6 The database adapter of FastAPI Users makes the link between your database configuration and the users logic. Create it like this. import databases import sqlalchemy from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite:///./test.db\" database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) app = FastAPI () @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () Notice that we pass it three things: A reference to your UserDB model . The users variable, which is the actual SQLAlchemy table behind the table class. A database instance, which allows us to do asynchronous request to the database. Next steps \u00b6 We will now configure an authentication method . What about SQLAlchemy ORM? \u00b6 The primary objective was to use pure async approach as much as possible. However, we understand that ORM is convenient and useful for many developers. If this feature becomes very demanded, we will add a database adapter for SQLAlchemy ORM.","title":"SQLAlchemy"},{"location":"configuration/databases/sqlalchemy/#sqlalchemy","text":"FastAPI Users provides the necessary tools to work with SQL databases thanks to SQLAlchemy Core and encode/databases package for full async support.","title":"SQLAlchemy"},{"location":"configuration/databases/sqlalchemy/#installation","text":"Install the database driver that corresponds to your DBMS: pip install databases [ postgresql ] pip install databases [ mysql ] pip install databases [ sqlite ] For the sake of this tutorial from now on, we'll use a simple SQLite databse.","title":"Installation"},{"location":"configuration/databases/sqlalchemy/#setup-user-table","text":"Let's create a metadata object and declare our User table. import databases import sqlalchemy from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite:///./test.db\" database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) app = FastAPI () @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () 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/#create-the-tables","text":"We'll now create an SQLAlchemy engine and ask it to create all the defined tables. import databases import sqlalchemy from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite:///./test.db\" database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) app = FastAPI () @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See Alembic .","title":"Create the tables"},{"location":"configuration/databases/sqlalchemy/#create-the-database-adapter","text":"The database adapter of FastAPI Users makes the link between your database configuration and the users logic. Create it like this. import databases import sqlalchemy from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite:///./test.db\" database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) app = FastAPI () @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () Notice that we pass it three things: A reference to your UserDB model . The users variable, which is the actual SQLAlchemy table behind the table class. A database instance, which allows us to do asynchronous request to the database.","title":"Create the database adapter"},{"location":"configuration/databases/sqlalchemy/#next-steps","text":"We will now configure an authentication method .","title":"Next steps"},{"location":"configuration/databases/sqlalchemy/#what-about-sqlalchemy-orm","text":"The primary objective was to use pure async approach as much as possible. However, we understand that ORM is convenient and useful for many developers. If this feature becomes very demanded, we will add a database adapter for SQLAlchemy ORM.","title":"What about SQLAlchemy ORM?"},{"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 \u00b6 Let's declare our User ORM model. from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite://./test.db\" class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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. Create it like this. from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite://./test.db\" class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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 fastapi import FastAPI from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite://./test.db\" class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, 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 . Next steps \u00b6 We will now configure an authentication method .","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","text":"Let's declare our User ORM model. from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite://./test.db\" class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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/tortoise/#create-the-database-adapter","text":"The database adapter of FastAPI Users makes the link between your database configuration and the users logic. Create it like this. from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite://./test.db\" class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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 fastapi import FastAPI from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite://./test.db\" class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, 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/databases/tortoise/#next-steps","text":"We will now configure an authentication method .","title":"Next steps"},{"location":"configuration/routers/","text":"Routers \u00b6 We're almost there! The last step is to configure the FastAPIUsers object that will wire the database adapter, 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: db : Database adapter instance. 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 ( user_db , auth_backends , 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 database adapter, 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: db : Database adapter instance. 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 ( user_db , auth_backends , 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 (if applicable) 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 from fastapi_users.authentication import JWTAuthentication SECRET = \"SECRET\" jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 )) fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( jwt_authentication ), 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_validation parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_auth_router ( jwt_authentication , 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 (if applicable) 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 from fastapi_users.authentication import JWTAuthentication SECRET = \"SECRET\" jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 )) fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( jwt_authentication ), 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_validation parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_auth_router ( jwt_authentication , 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 from fastapi_users.authentication import JWTAuthentication SECRET = \"SECRET\" jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 )) fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) After register \u00b6 You can provide a custom function to be called after a successful registration. It is called with two argument : the user that has just registered, and the original Request object . Typically, you'll want to send a welcome e-mail or add it to your marketing analytics pipeline. You can define it as an async or standard method. Example: def on_after_register ( user : UserDB , request : Request ): print ( f \"User { user . id } has registered.\" ) app . include_router ( fastapi_users . get_register_router ( on_after_register ), 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 from fastapi_users.authentication import JWTAuthentication SECRET = \"SECRET\" jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 )) fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Setup"},{"location":"configuration/routers/register/#after-register","text":"You can provide a custom function to be called after a successful registration. It is called with two argument : the user that has just registered, and the original Request object . Typically, you'll want to send a welcome e-mail or add it to your marketing analytics pipeline. You can define it as an async or standard method. Example: def on_after_register ( user : UserDB , request : Request ): print ( f \"User { user . id } has registered.\" ) app . include_router ( fastapi_users . get_register_router ( on_after_register ), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"After register"},{"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 fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_reset_password_router ( \"SECRET\" ), prefix = \"/auth\" , tags = [ \"auth\" ], ) Parameters: reset_password_token_secret : Secret to encode reset password token. reset_password_token_lifetime_seconds : Lifetime of reset password token. Defaults to 3600 . after_forgot_password : Optional function called after a successful forgot password request. See below. After forgot password \u00b6 You can provide a custom function to be called after a successful forgot password request. It is called with three arguments : The user which has requested to reset their password. A ready-to-use JWT token that will be accepted by the reset password route. The original Request object . Typically, you'll want to send an e-mail with the link (and the token) that allows the user to reset their password. You can define it as an async or standard method. Example: def on_after_forgot_password ( user : UserDB , token : str , request : Request ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) app . include_router ( fastapi_users . get_reset_password_router ( \"SECRET\" , after_forgot_password = on_after_forgot_password ), 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 fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_reset_password_router ( \"SECRET\" ), prefix = \"/auth\" , tags = [ \"auth\" ], ) Parameters: reset_password_token_secret : Secret to encode reset password token. reset_password_token_lifetime_seconds : Lifetime of reset password token. Defaults to 3600 . after_forgot_password : Optional function called after a successful forgot password request. See below.","title":"Setup"},{"location":"configuration/routers/reset/#after-forgot-password","text":"You can provide a custom function to be called after a successful forgot password request. It is called with three arguments : The user which has requested to reset their password. A ready-to-use JWT token that will be accepted by the reset password route. The original Request object . Typically, you'll want to send an e-mail with the link (and the token) that allows the user to reset their password. You can define it as an async or standard method. Example: def on_after_forgot_password ( user : UserDB , token : str , request : Request ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) app . include_router ( fastapi_users . get_reset_password_router ( \"SECRET\" , after_forgot_password = on_after_forgot_password ), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"After forgot password"},{"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 fastapi_users = FastAPIUsers ( user_db , auth_backends , 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_validation parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_users_router ( requires_verification = True ), prefix = \"/users\" , tags = [ \"users\" ], ) After update \u00b6 You can provide a custom function to be called after a successful update user request. It is called with three arguments : The user which was updated. The dictionary containing the updated fields. The original Request object . It may be useful if you wish for example update your user in a data analytics or customer success platform. You can define it as an async or standard method. Example: def on_after_update ( user : UserDB , updated_user_data : Dict [ str , Any ], request : Request ): print ( f \"User { user . id } has been updated with the following data: { updated_user_data } \" ) app . include_router ( fastapi_users . get_users_router ( on_after_update ), 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 fastapi_users = FastAPIUsers ( user_db , auth_backends , 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_validation 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/users/#after-update","text":"You can provide a custom function to be called after a successful update user request. It is called with three arguments : The user which was updated. The dictionary containing the updated fields. The original Request object . It may be useful if you wish for example update your user in a data analytics or customer success platform. You can define it as an async or standard method. Example: def on_after_update ( user : UserDB , updated_user_data : Dict [ str , Any ], request : Request ): print ( f \"User { user . id } has been updated with the following data: { updated_user_data } \" ) app . include_router ( fastapi_users . get_users_router ( on_after_update ), prefix = \"/users\" , tags = [ \"users\" ], )","title":"After update"},{"location":"configuration/routers/verify/","text":"Verify router \u00b6 Warning This feature is not released yet. 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 fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_verify_router ( \"SECRET\" ), prefix = \"/auth\" , tags = [ \"auth\" ], ) Parameters: verification_token_secret : Secret to encode verify token. verification_token_lifetime_seconds : Lifetime of verify token. Defaults to 3600 . after_verification_request : Optional function called after a successful verify request. See below. after_verification : Optional function called after a successful verification. See below. After verification request \u00b6 You can provide a custom function to be called after a successful verification request. It is called with three arguments : The user for which the verification has been requested. A ready-to-use JWT token that will be accepted by the verify route. The original Request object . Typically, you'll want to send an e-mail with the link (and the token) that allows the user to verify their e-mail. You can define it as an async or standard method. Example: def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) app . include_router ( fastapi_users . get_verify_router ( \"SECRET\" , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) After verification \u00b6 You can provide a custom function to be called after a successful user verification. It is called with two arguments : The user that has been verified. The original Request object . This may be useful if you wish to send another e-mail or store this information in a data analytics or customer success platform. You can define it as an async or standard method. Example: def after_verification ( user : UserDB , request : Request ): print ( f \" { user . id } is now verified.\" ) app . include_router ( fastapi_users . get_verify_router ( \"SECRET\" , after_verification = after_verification ), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Verify router"},{"location":"configuration/routers/verify/#verify-router","text":"Warning This feature is not released yet. 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 fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_verify_router ( \"SECRET\" ), prefix = \"/auth\" , tags = [ \"auth\" ], ) Parameters: verification_token_secret : Secret to encode verify token. verification_token_lifetime_seconds : Lifetime of verify token. Defaults to 3600 . after_verification_request : Optional function called after a successful verify request. See below. after_verification : Optional function called after a successful verification. See below.","title":"Setup"},{"location":"configuration/routers/verify/#after-verification-request","text":"You can provide a custom function to be called after a successful verification request. It is called with three arguments : The user for which the verification has been requested. A ready-to-use JWT token that will be accepted by the verify route. The original Request object . Typically, you'll want to send an e-mail with the link (and the token) that allows the user to verify their e-mail. You can define it as an async or standard method. Example: def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) app . include_router ( fastapi_users . get_verify_router ( \"SECRET\" , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"After verification request"},{"location":"configuration/routers/verify/#after-verification","text":"You can provide a custom function to be called after a successful user verification. It is called with two arguments : The user that has been verified. The original Request object . This may be useful if you wish to send another e-mail or store this information in a data analytics or customer success platform. You can define it as an async or standard method. Example: def after_verification ( user : UserDB , request : Request ): print ( f \" { user . id } is now verified.\" ) app . include_router ( fastapi_users . get_verify_router ( \"SECRET\" , after_verification = after_verification ), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"After verification"},{"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":"usage/dependency-callables/","text":"Dependency callables \u00b6 FastAPI Users provides dependency callables to easily inject users 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 . get_current_user \u00b6 Get the current user ( active or not ). Will throw a 401 Unauthorized if missing or wrong credentials. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_user )): return f \"Hello, { user . email } \" get_current_active_user \u00b6 Get the current active user. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_active_user )): return f \"Hello, { user . email } \" get_current_verified_user \u00b6 Get the current active and verified user. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active and verified. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_verified_user )): return f \"Hello, { user . email } \" get_current_superuser \u00b6 Get the current superuser. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active. Will throw a 403 Forbidden if the user is not a superuser. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_superuser )): return f \"Hello, { user . email } \" get_current_verified_superuser \u00b6 Get the current verified superuser. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active and verified. Will throw a 403 Forbidden if the user is not a superuser. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_verified_superuser )): return f \"Hello, { user . email } \" get_optional_current_user \u00b6 Get the current user ( active or not ). Will return None if missing or wrong credentials. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : Optional [ User ] = Depends ( fastapi_users . get_optional_current_user )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\" get_optional_current_active_user \u00b6 Get the current active user. Will return None if missing or wrong credentials or if the user is not active. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_active_user )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\" get_optional_current_verified_user \u00b6 Get the current active and verified user. Will return None if missing or wrong credentials or if the user is not active and verified. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_verified_user )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\" get_optional_current_superuser \u00b6 Get the current superuser. Will return None if missing or wrong credentials or if the user is not active. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_superuser )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\" get_optional_current_verified_superuser \u00b6 Get the current active and verified superuser. Will return None if missing or wrong credentials or if the user is not active and verified. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_verified_superuser )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\" In 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 ( fastapi_users . get_current_superuser )]) def protected_route (): return \"Hello, some user.\" You can read more about this in FastAPI docs .","title":"Dependency callables"},{"location":"usage/dependency-callables/#dependency-callables","text":"FastAPI Users provides dependency callables to easily inject users 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":"Dependency callables"},{"location":"usage/dependency-callables/#get_current_user","text":"Get the current user ( active or not ). Will throw a 401 Unauthorized if missing or wrong credentials. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_user )): return f \"Hello, { user . email } \"","title":"get_current_user"},{"location":"usage/dependency-callables/#get_current_active_user","text":"Get the current active user. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_active_user )): return f \"Hello, { user . email } \"","title":"get_current_active_user"},{"location":"usage/dependency-callables/#get_current_verified_user","text":"Get the current active and verified user. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active and verified. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_verified_user )): return f \"Hello, { user . email } \"","title":"get_current_verified_user"},{"location":"usage/dependency-callables/#get_current_superuser","text":"Get the current superuser. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active. Will throw a 403 Forbidden if the user is not a superuser. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_superuser )): return f \"Hello, { user . email } \"","title":"get_current_superuser"},{"location":"usage/dependency-callables/#get_current_verified_superuser","text":"Get the current verified superuser. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active and verified. Will throw a 403 Forbidden if the user is not a superuser. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_verified_superuser )): return f \"Hello, { user . email } \"","title":"get_current_verified_superuser"},{"location":"usage/dependency-callables/#get_optional_current_user","text":"Get the current user ( active or not ). Will return None if missing or wrong credentials. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : Optional [ User ] = Depends ( fastapi_users . get_optional_current_user )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\"","title":"get_optional_current_user"},{"location":"usage/dependency-callables/#get_optional_current_active_user","text":"Get the current active user. Will return None if missing or wrong credentials or if the user is not active. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_active_user )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\"","title":"get_optional_current_active_user"},{"location":"usage/dependency-callables/#get_optional_current_verified_user","text":"Get the current active and verified user. Will return None if missing or wrong credentials or if the user is not active and verified. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_verified_user )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\"","title":"get_optional_current_verified_user"},{"location":"usage/dependency-callables/#get_optional_current_superuser","text":"Get the current superuser. Will return None if missing or wrong credentials or if the user is not active. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_superuser )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\"","title":"get_optional_current_superuser"},{"location":"usage/dependency-callables/#get_optional_current_verified_superuser","text":"Get the current active and verified superuser. Will return None if missing or wrong credentials or if the user is not active and verified. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_verified_superuser )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\"","title":"get_optional_current_verified_superuser"},{"location":"usage/dependency-callables/#in-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 ( fastapi_users . get_current_superuser )]) def protected_route (): return \"Hello, some user.\" You can read more about this in FastAPI docs .","title":"In 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 curl \\ -H \"Content-Type: application/json\" \\ -X POST \\ -d \"{\\\"email\\\": \\\"king.arthur@camelot.bt\\\",\\\"password\\\": \\\"guinevere\\\"}\" \\ http://localhost:8000/auth/register axios 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. JWT backend \u00b6 Request \u00b6 cURL curl \\ -H \"Content-Type: multipart/form-data\" \\ -X POST \\ -F \"username=king.arthur@camelot.bt\" \\ -F \"password=guinevere\" \\ http://localhost:8000/auth/jwt/login axios 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 backend \u00b6 Request \u00b6 cURL 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 axios 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 a 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 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 axios 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 curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X PATCH \\ -d \"{\\\"password\\\": \\\"lancelot\\\"}\" \\ http://localhost:8000/users/me axios 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 curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X GET \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios 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 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 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 curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X DELETE \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios 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. Note that it doesn't apply to every authentication backends . For JWT, it doesn't make sense to end the session, the token is valid until it expires. However, for Cookie backend, the server will clear the cookie. Request \u00b6 cURL curl \\ -H \"Content-Type: application/json\" \\ -H \"Cookie: fastapiusersauth= $TOKEN \" \\ -X POST \\ http://localhost:8000/auth/cookie/logout axios 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 curl \\ -H \"Content-Type: application/json\" \\ -X POST \\ -d \"{\\\"email\\\": \\\"king.arthur@camelot.bt\\\",\\\"password\\\": \\\"guinevere\\\"}\" \\ http://localhost:8000/auth/register axios 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/#jwt-backend","text":"","title":"JWT backend"},{"location":"usage/flow/#request_1","text":"cURL curl \\ -H \"Content-Type: multipart/form-data\" \\ -X POST \\ -F \"username=king.arthur@camelot.bt\" \\ -F \"password=guinevere\" \\ http://localhost:8000/auth/jwt/login axios 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-backend","text":"","title":"Cookie backend"},{"location":"usage/flow/#request_2","text":"cURL 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 axios 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 a 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 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 axios 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 curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X PATCH \\ -d \"{\\\"password\\\": \\\"lancelot\\\"}\" \\ http://localhost:8000/users/me axios 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 curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X GET \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios 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 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 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 curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X DELETE \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios 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. Note that it doesn't apply to every authentication backends . For JWT, it doesn't make sense to end the session, the token is valid until it expires. However, for Cookie backend, the server will clear the cookie.","title":"6. Logout"},{"location":"usage/flow/#request_8","text":"cURL curl \\ -H \"Content-Type: application/json\" \\ -H \"Cookie: fastapiusersauth= $TOKEN \" \\ -X POST \\ http://localhost:8000/auth/cookie/logout axios 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/helpers/","text":"Helpers \u00b6 FastAPI Users provides some helper functions to perform some actions programmatically. They are available from your FastAPIUsers instance. Create user \u00b6 Create a user. regular_user = await fastapi_users . create_user ( UserCreate ( email = \"king.arthur@camelot.bt\" , password = \"guinevere\" , ) ) superuser = await fastapi_users . create_user ( UserCreate ( email = \"king.arthur@camelot.bt\" , password = \"guinevere\" , is_superuser = True , ) ) Verify user \u00b6 Verify a user. verified_user = await fastapi_users . verify_user ( non_verified_user ) assert verified_user . is_verified is True Get user \u00b6 Retrieve a user by e-mail. user = await fastapi_users . get_user ( \"king.arthur@camelot.bt\" )","title":"Helpers"},{"location":"usage/helpers/#helpers","text":"FastAPI Users provides some helper functions to perform some actions programmatically. They are available from your FastAPIUsers instance.","title":"Helpers"},{"location":"usage/helpers/#create-user","text":"Create a user. regular_user = await fastapi_users . create_user ( UserCreate ( email = \"king.arthur@camelot.bt\" , password = \"guinevere\" , ) ) superuser = await fastapi_users . create_user ( UserCreate ( email = \"king.arthur@camelot.bt\" , password = \"guinevere\" , is_superuser = True , ) )","title":"Create user"},{"location":"usage/helpers/#verify-user","text":"Verify a user. verified_user = await fastapi_users . verify_user ( non_verified_user ) assert verified_user . is_verified is True","title":"Verify user"},{"location":"usage/helpers/#get-user","text":"Retrieve a user by e-mail. user = await fastapi_users . get_user ( \"king.arthur@camelot.bt\" )","title":"Get user"},{"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\" } 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. Tip Some backend (like JWT) won't produce this route. Register router \u00b6 POST /register \u00b6 Register a new user. Will call the 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\" } Reset password router \u00b6 POST /forgot-password \u00b6 Request a reset password procedure. Will generate a temporary token and call the 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\" } Verify router \u00b6 Warning This feature is not released yet. POST /request-verify-token \u00b6 Request a user to verify their e-mail. Will generate a temporary token and call the after_verification_request 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 /verify \u00b6 Verify a user. Requires the token generated by the /request-verify-token route. Will call the call the after_verification handler on success. Payload { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } 200 OK 422 Validation Error 400 Bad Request Expired token. { \"detail\" : \"VERIFY_USER_TOKEN_EXPIRED\" } 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 authentication_backend : name property of a defined authentication method to use to authenticate the user on successful callback. Usually jwt or cookie . 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 400 Bad Request 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 . 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. 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. 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\" }","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. Tip Some backend (like JWT) won't produce this route.","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 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\" }","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 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\" }","title":"POST /reset-password"},{"location":"usage/routes/#verify-router","text":"Warning This feature is not released yet.","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 after_verification_request 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 /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 after_verification handler on success. Payload { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } 200 OK 422 Validation Error 400 Bad Request Expired token. { \"detail\" : \"VERIFY_USER_TOKEN_EXPIRED\" } 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 authentication_backend : name property of a defined authentication method to use to authenticate the user on successful callback. Usually jwt or cookie . 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 400 Bad Request 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 .","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.","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.","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":{"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://frankie567.github.io/fastapi-users/ Source Code : https://github.com/frankie567/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 OAuth2 flow Dependency callables to inject current user in route Customizable database backend SQLAlchemy async backend included thanks to encode/databases MongoDB async backend included thanks to mongodb/motor Tortoise ORM backend included Multiple customizable authentication backends JWT authentication backend included Cookie authentication backend included Full OpenAPI schema support, even with several authentication backends Development \u00b6 Setup environement \u00b6 You should have Pipenv installed. Then, you can install the dependencies with: pipenv install --dev After that, activate the virtual environment: pipenv shell 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://frankie567.github.io/fastapi-users/ Source Code : https://github.com/frankie567/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 OAuth2 flow Dependency callables to inject current user in route Customizable database backend SQLAlchemy async backend included thanks to encode/databases MongoDB async backend included thanks to mongodb/motor Tortoise ORM backend included Multiple customizable authentication backends JWT authentication backend included Cookie authentication backend included Full OpenAPI schema support, even with several authentication backends","title":"Features"},{"location":"#development","text":"","title":"Development"},{"location":"#setup-environement","text":"You should have Pipenv installed. Then, you can install the dependencies with: pipenv install --dev After that, activate the virtual environment: pipenv shell","title":"Setup environement"},{"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 [ sqlalchemy ] With MongoDB support \u00b6 pip install fastapi-users [ mongodb ] With Tortoise ORM support \u00b6 pip install fastapi-users [ tortoise-orm ] 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 [ sqlalchemy ]","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 ] That's it! Now, let's have a look at our User model .","title":"With Tortoise ORM 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 import databases import sqlalchemy from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () MongoDB \u00b6 import motor.motor_asyncio from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) Tortoise ORM \u00b6 from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) What now? \u00b6 You're ready to go! Be sure to check the Usage section to understand how yo 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":"import databases import sqlalchemy from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect ()","title":"SQLAlchemy"},{"location":"configuration/full_example/#mongodb","text":"import motor.motor_asyncio from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ])","title":"MongoDB"},{"location":"configuration/full_example/#tortoise-orm","text":"from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ])","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 yo work with FastAPI Users .","title":"What now?"},{"location":"configuration/model/","text":"User model \u00b6 FastAPI Users defines a minimal User model for authentication purposes. It is structured like this: id ( UUID4 ) \u2013 Unique identifier of the user. Default 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. Default to True . is_verified ( bool ) \u2013 Whether or not the user is verified. Optional but helpful with the verify router logic. Default to False . is_superuser ( bool ) \u2013 Whether or not the user is a superuser. Useful to implement administration logic. Default 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 ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass You can of course add your own properties there to fit to your needs! Password validation \u00b6 FastAPI Users doesn't provide a default password validation, but you can implement it easily with a Pydantic validator on the UserCreate class. Here is a simple example to check if the password is at least six characters long: from fastapi_users import models from pydantic import validator class UserCreate ( models . BaseUserCreate ): @validator ( 'password' ) def valid_password ( cls , v : str ): if len ( v ) < 6 : raise ValueError ( 'Password should be at least 6 characters' ) return v Next steps \u00b6 Depending on your database backend, the database configuration will differ a bit. I'm using SQLAlchemy I'm using MongoDB I'm using Tortoise ORM","title":"User model"},{"location":"configuration/model/#user-model","text":"FastAPI Users defines a minimal User model for authentication purposes. It is structured like this: id ( UUID4 ) \u2013 Unique identifier of the user. Default 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. Default to True . is_verified ( bool ) \u2013 Whether or not the user is verified. Optional but helpful with the verify router logic. Default to False . is_superuser ( bool ) \u2013 Whether or not the user is a superuser. Useful to implement administration logic. Default to False .","title":"User model"},{"location":"configuration/model/#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 ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass You can of course add your own properties there to fit to your needs!","title":"Define your models"},{"location":"configuration/model/#password-validation","text":"FastAPI Users doesn't provide a default password validation, but you can implement it easily with a Pydantic validator on the UserCreate class. Here is a simple example to check if the password is at least six characters long: from fastapi_users import models from pydantic import validator class UserCreate ( models . BaseUserCreate ): @validator ( 'password' ) def valid_password ( cls , v : str ): if len ( v ) < 6 : raise ValueError ( 'Password should be at least 6 characters' ) return v","title":"Password validation"},{"location":"configuration/model/#next-steps","text":"Depending on your database backend, the database configuration will differ a bit. I'm using SQLAlchemy I'm using MongoDB I'm using Tortoise ORM","title":"Next steps"},{"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 [ sqlalchemy,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 ( User , 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. Default 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 table for storing the OAuth account model. We provide a base one for this: from fastapi_users.db.sqlalchemy import SQLAlchemyBaseOAuthAccountTable class OAuthAccount ( SQLAlchemyBaseOAuthAccountTable , Base ): pass Then, you should declare it on the database adapter: user_db = SQLAlchemyUserDatabase ( UserDB , database , User . __table__ , OAuthAccount . __table__ ) 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.db.tortoise import TortoiseBaseOAuthAccountModel class OAuthAccount ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.User\" , 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: user_db = TortoiseUserDatabase ( UserDB , User , OAuthAccount ) Generate a router \u00b6 Once you have a FastAPIUsers instance, you can make it generate a single OAuth router for the given client. from fastapi import FastAPI from fastapi_users import FastAPIUsers from httpx_oauth.clients.google import GoogleOAuth2 google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB ) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ]) After register \u00b6 You can provide a custom function to be called after a successful registration. It is called with two argument : the user that has just registered, and the original Request object . Typically, you'll want to send a welcome e-mail or add it to your marketing analytics pipeline. You can define it as an async or standard method. Example: from fastapi import FastAPI from fastapi_users import FastAPIUsers from httpx_oauth.clients.google import GoogleOAuth2 def on_after_register ( user : UserDB , request : Request ): print ( f \"User { user . id } has registered.\" ) google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB ) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , 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 import databases import sqlalchemy from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from httpx_oauth.clients.google import GoogleOAuth2 from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass class OAuthAccount ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ oauth_accounts = OAuthAccount . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users , oauth_accounts ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ]) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () MongoDB \u00b6 import motor.motor_asyncio from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ]) Tortoise ORM \u00b6 from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import ( TortoiseBaseOAuthAccountModel , TortoiseBaseUserModel , TortoiseUserDatabase , ) from httpx_oauth.clients.google import GoogleOAuth2 from tortoise import fields from tortoise.contrib.fastapi import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass class UserModel ( TortoiseBaseUserModel ): pass class OAuthAccountModel ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"oauth_accounts\" ) user_db = TortoiseUserDatabase ( UserDB , UserModel , OAuthAccountModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ])","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 [ sqlalchemy,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 ( User , 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. Default 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 table for storing the OAuth account model. We provide a base one for this: from fastapi_users.db.sqlalchemy import SQLAlchemyBaseOAuthAccountTable class OAuthAccount ( SQLAlchemyBaseOAuthAccountTable , Base ): pass Then, you should declare it on the database adapter: user_db = SQLAlchemyUserDatabase ( UserDB , database , User . __table__ , OAuthAccount . __table__ )","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.db.tortoise import TortoiseBaseOAuthAccountModel class OAuthAccount ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.User\" , 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: user_db = TortoiseUserDatabase ( UserDB , User , 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 the given client. from fastapi import FastAPI from fastapi_users import FastAPIUsers from httpx_oauth.clients.google import GoogleOAuth2 google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB ) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ])","title":"Generate a router"},{"location":"configuration/oauth/#after-register","text":"You can provide a custom function to be called after a successful registration. It is called with two argument : the user that has just registered, and the original Request object . Typically, you'll want to send a welcome e-mail or add it to your marketing analytics pipeline. You can define it as an async or standard method. Example: from fastapi import FastAPI from fastapi_users import FastAPIUsers from httpx_oauth.clients.google import GoogleOAuth2 def on_after_register ( user : UserDB , request : Request ): print ( f \"User { user . id } has registered.\" ) google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB ) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ])","title":"After register"},{"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":"import databases import sqlalchemy from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import ( SQLAlchemyBaseOAuthAccountTable , SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase , ) from httpx_oauth.clients.google import GoogleOAuth2 from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass class OAuthAccount ( SQLAlchemyBaseOAuthAccountTable , Base ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ oauth_accounts = OAuthAccount . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users , oauth_accounts ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ]) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect ()","title":"SQLAlchemy"},{"location":"configuration/oauth/#mongodb_1","text":"import motor.motor_asyncio from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase from httpx_oauth.clients.google import GoogleOAuth2 DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ])","title":"MongoDB"},{"location":"configuration/oauth/#tortoise-orm_1","text":"from fastapi import FastAPI , Request from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import ( TortoiseBaseOAuthAccountModel , TortoiseBaseUserModel , TortoiseUserDatabase , ) from httpx_oauth.clients.google import GoogleOAuth2 from tortoise import fields from tortoise.contrib.fastapi import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass class UserModel ( TortoiseBaseUserModel ): pass class OAuthAccountModel ( TortoiseBaseOAuthAccountModel ): user = fields . ForeignKeyField ( \"models.UserModel\" , related_name = \"oauth_accounts\" ) user_db = TortoiseUserDatabase ( UserDB , UserModel , OAuthAccountModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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 } \" ) def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , tokenUrl = \"/auth/jwt/login\" ) 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_verify_router ( SECRET , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) app . include_router ( fastapi_users . get_users_router (), prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET , after_register = on_after_register ) app . include_router ( google_oauth_router , prefix = \"/auth/google\" , tags = [ \"auth\" ])","title":"Tortoise ORM"},{"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 (if applicable routes). More on this in the routers documentation . Provided methods \u00b6 JWT authentication Cookie authentication","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 (if applicable routes). More on this in the routers documentation .","title":"How it works?"},{"location":"configuration/authentication/#provided-methods","text":"JWT authentication Cookie authentication","title":"Provided methods"},{"location":"configuration/authentication/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 CookieAuthentication SECRET = \"SECRET\" auth_backends = [] cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) auth_backends . append ( cookie_authentication ) As you can see, instantiation is quite simple. You just have to define a constant SECRET which is used to encode the token and the lifetime of the cookie (in seconds). You can also define the parameters for the generated cookie: cookie_name ( fastapiusersauth ): Name of the 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'. Tip You can also optionally define the name . It's useful in the case you wish to have several backends of the same class. Each backend should have a unique name. Defaults to cookie . cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 , name = \"my-cookie\" , ) Tip The value of the cookie is actually a JWT. This authentication backend shares most of its logic with the JWT one. 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. Next steps \u00b6 We will now configure the main FastAPI Users object that will expose the routers .","title":"Cookie"},{"location":"configuration/authentication/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/cookie/#configuration","text":"from fastapi_users.authentication import CookieAuthentication SECRET = \"SECRET\" auth_backends = [] cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) auth_backends . append ( cookie_authentication ) As you can see, instantiation is quite simple. You just have to define a constant SECRET which is used to encode the token and the lifetime of the cookie (in seconds). You can also define the parameters for the generated cookie: cookie_name ( fastapiusersauth ): Name of the 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'. Tip You can also optionally define the name . It's useful in the case you wish to have several backends of the same class. Each backend should have a unique name. Defaults to cookie . cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 , name = \"my-cookie\" , ) Tip The value of the cookie is actually a JWT. This authentication backend shares most of its logic with the JWT one.","title":"Configuration"},{"location":"configuration/authentication/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/cookie/#logout","text":"This method will remove the authentication cookie: 200 OK Check documentation about logout route .","title":"Logout"},{"location":"configuration/authentication/cookie/#authentication","text":"This method expects that you provide a valid cookie in the headers.","title":"Authentication"},{"location":"configuration/authentication/cookie/#next-steps","text":"We will now configure the main FastAPI Users object that will expose the routers .","title":"Next steps"},{"location":"configuration/authentication/jwt/","text":"JWT \u00b6 JSON Web Token (JWT) is an internet standard for creating access tokens based on JSON. Configuration \u00b6 from fastapi_users.authentication import JWTAuthentication SECRET = \"SECRET\" auth_backends = [] jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) auth_backends . append ( jwt_authentication ) As you can see, instantiation is quite simple. You just have to define a constant SECRET which is used to encode the token and the lifetime of token (in seconds). Tip You can also optionally define the name . It's useful in the case you wish to have several backends of the same class. Each backend should have a unique name. Defaults to jwt . jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , name = \"my-jwt\" , ) Login \u00b6 This method will return a JWT token upon successful login: 200 OK { \"access_token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" , \"token_type\" : \"bearer\" } Check documentation about login route . Logout \u00b6 This backend does not provide a logout method (a JWT is valid until it expires). Authentication \u00b6 This method expects that you provide a Bearer authentication with a valid JWT. curl http://localhost:9000/protected-route -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI' Tip: Refresh \u00b6 The default implementation does not provide a mechanism to refresh the JWT. However, you can implement it quite easily like this: from fastapi import Depends , Response @router . post ( \"/auth/jwt/refresh\" ) async def refresh_jwt ( response : Response , user = Depends ( fastapi_users . get_current_active_user )): return await jwt_authentication . get_login_response ( user , response ) Next steps \u00b6 We will now configure the main FastAPI Users object that will expose the routers .","title":"JWT"},{"location":"configuration/authentication/jwt/#jwt","text":"JSON Web Token (JWT) is an internet standard for creating access tokens based on JSON.","title":"JWT"},{"location":"configuration/authentication/jwt/#configuration","text":"from fastapi_users.authentication import JWTAuthentication SECRET = \"SECRET\" auth_backends = [] jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) auth_backends . append ( jwt_authentication ) As you can see, instantiation is quite simple. You just have to define a constant SECRET which is used to encode the token and the lifetime of token (in seconds). Tip You can also optionally define the name . It's useful in the case you wish to have several backends of the same class. Each backend should have a unique name. Defaults to jwt . jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 , name = \"my-jwt\" , )","title":"Configuration"},{"location":"configuration/authentication/jwt/#login","text":"This method will return a JWT token 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/jwt/#logout","text":"This backend does not provide a logout method (a JWT is valid until it expires).","title":"Logout"},{"location":"configuration/authentication/jwt/#authentication","text":"This method expects that you provide a Bearer authentication with a valid JWT. curl http://localhost:9000/protected-route -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI'","title":"Authentication"},{"location":"configuration/authentication/jwt/#tip-refresh","text":"The default implementation does not provide a mechanism to refresh the JWT. However, you can implement it quite easily like this: from fastapi import Depends , Response @router . post ( \"/auth/jwt/refresh\" ) async def refresh_jwt ( response : Response , user = Depends ( fastapi_users . get_current_active_user )): return await jwt_authentication . get_login_response ( user , response )","title":"Tip: Refresh"},{"location":"configuration/authentication/jwt/#next-steps","text":"We will now configure the main FastAPI Users object that will expose the routers .","title":"Next steps"},{"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 import FastAPI from fastapi_users import models from fastapi_users.db import MongoDBUserDatabase class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] app = FastAPI () user_db = 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. Create it like this. import motor.motor_asyncio from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import MongoDBUserDatabase class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] app = FastAPI () user_db = 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 . Next steps \u00b6 We will now configure an authentication method .","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 import FastAPI from fastapi_users import models from fastapi_users.db import MongoDBUserDatabase class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] app = FastAPI () user_db = 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. Create it like this. import motor.motor_asyncio from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import MongoDBUserDatabase class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL , uuidRepresentation = \"standard\" ) db = client [ \"database_name\" ] collection = db [ \"users\" ] app = FastAPI () user_db = 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/mongodb/#next-steps","text":"We will now configure an authentication method .","title":"Next steps"},{"location":"configuration/databases/sqlalchemy/","text":"SQLAlchemy \u00b6 FastAPI Users provides the necessary tools to work with SQL databases thanks to SQLAlchemy Core and encode/databases package for full async support. Installation \u00b6 Install the database driver that corresponds to your DBMS: pip install databases [ postgresql ] pip install databases [ mysql ] pip install databases [ sqlite ] For the sake of this tutorial from now on, we'll use a simple SQLite databse. Setup User table \u00b6 Let's create a metadata object and declare our User table. import databases import sqlalchemy from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite:///./test.db\" database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) app = FastAPI () @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () 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! Create the tables \u00b6 We'll now create an SQLAlchemy engine and ask it to create all the defined tables. import databases import sqlalchemy from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite:///./test.db\" database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) app = FastAPI () @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See Alembic . Create the database adapter \u00b6 The database adapter of FastAPI Users makes the link between your database configuration and the users logic. Create it like this. import databases import sqlalchemy from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite:///./test.db\" database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) app = FastAPI () @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () Notice that we pass it three things: A reference to your UserDB model . The users variable, which is the actual SQLAlchemy table behind the table class. A database instance, which allows us to do asynchronous request to the database. Next steps \u00b6 We will now configure an authentication method . What about SQLAlchemy ORM? \u00b6 The primary objective was to use pure async approach as much as possible. However, we understand that ORM is convenient and useful for many developers. If this feature becomes very demanded, we will add a database adapter for SQLAlchemy ORM.","title":"SQLAlchemy"},{"location":"configuration/databases/sqlalchemy/#sqlalchemy","text":"FastAPI Users provides the necessary tools to work with SQL databases thanks to SQLAlchemy Core and encode/databases package for full async support.","title":"SQLAlchemy"},{"location":"configuration/databases/sqlalchemy/#installation","text":"Install the database driver that corresponds to your DBMS: pip install databases [ postgresql ] pip install databases [ mysql ] pip install databases [ sqlite ] For the sake of this tutorial from now on, we'll use a simple SQLite databse.","title":"Installation"},{"location":"configuration/databases/sqlalchemy/#setup-user-table","text":"Let's create a metadata object and declare our User table. import databases import sqlalchemy from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite:///./test.db\" database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) app = FastAPI () @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () 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/#create-the-tables","text":"We'll now create an SQLAlchemy engine and ask it to create all the defined tables. import databases import sqlalchemy from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite:///./test.db\" database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) app = FastAPI () @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () Warning In production, it's strongly recommended to setup a migration system to update your SQL schemas. See Alembic .","title":"Create the tables"},{"location":"configuration/databases/sqlalchemy/#create-the-database-adapter","text":"The database adapter of FastAPI Users makes the link between your database configuration and the users logic. Create it like this. import databases import sqlalchemy from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite:///./test.db\" database = databases . Database ( DATABASE_URL ) Base : DeclarativeMeta = declarative_base () class UserTable ( Base , SQLAlchemyBaseUserTable ): pass engine = sqlalchemy . create_engine ( DATABASE_URL , connect_args = { \"check_same_thread\" : False } ) Base . metadata . create_all ( engine ) users = UserTable . __table__ user_db = SQLAlchemyUserDatabase ( UserDB , database , users ) app = FastAPI () @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () Notice that we pass it three things: A reference to your UserDB model . The users variable, which is the actual SQLAlchemy table behind the table class. A database instance, which allows us to do asynchronous request to the database.","title":"Create the database adapter"},{"location":"configuration/databases/sqlalchemy/#next-steps","text":"We will now configure an authentication method .","title":"Next steps"},{"location":"configuration/databases/sqlalchemy/#what-about-sqlalchemy-orm","text":"The primary objective was to use pure async approach as much as possible. However, we understand that ORM is convenient and useful for many developers. If this feature becomes very demanded, we will add a database adapter for SQLAlchemy ORM.","title":"What about SQLAlchemy ORM?"},{"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 \u00b6 Let's declare our User ORM model. from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite://./test.db\" class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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. Create it like this. from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite://./test.db\" class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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 fastapi import FastAPI from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite://./test.db\" class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, 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 . Next steps \u00b6 We will now configure an authentication method .","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","text":"Let's declare our User ORM model. from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite://./test.db\" class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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/tortoise/#create-the-database-adapter","text":"The database adapter of FastAPI Users makes the link between your database configuration and the users logic. Create it like this. from fastapi import FastAPI from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite://./test.db\" class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, generate_schemas = True , ) 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 fastapi import FastAPI from fastapi_users import models from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from tortoise.contrib.fastapi import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass DATABASE_URL = \"sqlite://./test.db\" class UserModel ( TortoiseBaseUserModel ): pass user_db = TortoiseUserDatabase ( UserDB , UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"path_to_your_package\" ]}, 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/databases/tortoise/#next-steps","text":"We will now configure an authentication method .","title":"Next steps"},{"location":"configuration/routers/","text":"Routers \u00b6 We're almost there! The last step is to configure the FastAPIUsers object that will wire the database adapter, 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: db : Database adapter instance. 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 ( user_db , auth_backends , 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 database adapter, 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: db : Database adapter instance. 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 ( user_db , auth_backends , 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 (if applicable) 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 from fastapi_users.authentication import JWTAuthentication SECRET = \"SECRET\" jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 )) fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( jwt_authentication ), 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_validation parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_auth_router ( jwt_authentication , 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 (if applicable) 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 from fastapi_users.authentication import JWTAuthentication SECRET = \"SECRET\" jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 )) fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_auth_router ( jwt_authentication ), 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_validation parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_auth_router ( jwt_authentication , 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 from fastapi_users.authentication import JWTAuthentication SECRET = \"SECRET\" jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 )) fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ], ) After register \u00b6 You can provide a custom function to be called after a successful registration. It is called with two argument : the user that has just registered, and the original Request object . Typically, you'll want to send a welcome e-mail or add it to your marketing analytics pipeline. You can define it as an async or standard method. Example: def on_after_register ( user : UserDB , request : Request ): print ( f \"User { user . id } has registered.\" ) app . include_router ( fastapi_users . get_register_router ( on_after_register ), 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 from fastapi_users.authentication import JWTAuthentication SECRET = \"SECRET\" jwt_authentication = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 )) fastapi_users = FastAPIUsers ( user_db , [ jwt_authentication ], User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_register_router (), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Setup"},{"location":"configuration/routers/register/#after-register","text":"You can provide a custom function to be called after a successful registration. It is called with two argument : the user that has just registered, and the original Request object . Typically, you'll want to send a welcome e-mail or add it to your marketing analytics pipeline. You can define it as an async or standard method. Example: def on_after_register ( user : UserDB , request : Request ): print ( f \"User { user . id } has registered.\" ) app . include_router ( fastapi_users . get_register_router ( on_after_register ), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"After register"},{"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 fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_reset_password_router ( \"SECRET\" ), prefix = \"/auth\" , tags = [ \"auth\" ], ) Parameters: reset_password_token_secret : Secret to encode reset password token. reset_password_token_lifetime_seconds : Lifetime of reset password token. Defaults to 3600 . after_forgot_password : Optional function called after a successful forgot password request. See below. After forgot password \u00b6 You can provide a custom function to be called after a successful forgot password request. It is called with three arguments : The user which has requested to reset their password. A ready-to-use JWT token that will be accepted by the reset password route. The original Request object . Typically, you'll want to send an e-mail with the link (and the token) that allows the user to reset their password. You can define it as an async or standard method. Example: def on_after_forgot_password ( user : UserDB , token : str , request : Request ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) app . include_router ( fastapi_users . get_reset_password_router ( \"SECRET\" , after_forgot_password = on_after_forgot_password ), prefix = \"/auth\" , tags = [ \"auth\" ], ) After reset password \u00b6 You can provide a custom function to be called after a successful password reset. It is called with two arguments : The user which has reset their password. The original Request object . 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. You can define it as an async or standard method. Example: def on_after_reset_password ( user : UserDB , request : Request ): print ( f \"User { user . id } has reset their password.\" ) app . include_router ( fastapi_users . get_reset_password_router ( \"SECRET\" , after_reset_password = on_after_reset_password ), 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 fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_reset_password_router ( \"SECRET\" ), prefix = \"/auth\" , tags = [ \"auth\" ], ) Parameters: reset_password_token_secret : Secret to encode reset password token. reset_password_token_lifetime_seconds : Lifetime of reset password token. Defaults to 3600 . after_forgot_password : Optional function called after a successful forgot password request. See below.","title":"Setup"},{"location":"configuration/routers/reset/#after-forgot-password","text":"You can provide a custom function to be called after a successful forgot password request. It is called with three arguments : The user which has requested to reset their password. A ready-to-use JWT token that will be accepted by the reset password route. The original Request object . Typically, you'll want to send an e-mail with the link (and the token) that allows the user to reset their password. You can define it as an async or standard method. Example: def on_after_forgot_password ( user : UserDB , token : str , request : Request ): print ( f \"User { user . id } has forgot their password. Reset token: { token } \" ) app . include_router ( fastapi_users . get_reset_password_router ( \"SECRET\" , after_forgot_password = on_after_forgot_password ), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"After forgot password"},{"location":"configuration/routers/reset/#after-reset-password","text":"You can provide a custom function to be called after a successful password reset. It is called with two arguments : The user which has reset their password. The original Request object . 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. You can define it as an async or standard method. Example: def on_after_reset_password ( user : UserDB , request : Request ): print ( f \"User { user . id } has reset their password.\" ) app . include_router ( fastapi_users . get_reset_password_router ( \"SECRET\" , after_reset_password = on_after_reset_password ), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"After reset password"},{"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 fastapi_users = FastAPIUsers ( user_db , auth_backends , 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_validation parameter to True on the router instantiation method: app . include_router ( fastapi_users . get_users_router ( requires_verification = True ), prefix = \"/users\" , tags = [ \"users\" ], ) After update \u00b6 You can provide a custom function to be called after a successful update user request. It is called with three arguments : The user which was updated. The dictionary containing the updated fields. The original Request object . It may be useful if you wish for example update your user in a data analytics or customer success platform. You can define it as an async or standard method. Example: def on_after_update ( user : UserDB , updated_user_data : Dict [ str , Any ], request : Request ): print ( f \"User { user . id } has been updated with the following data: { updated_user_data } \" ) app . include_router ( fastapi_users . get_users_router ( on_after_update ), 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 fastapi_users = FastAPIUsers ( user_db , auth_backends , 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_validation 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/users/#after-update","text":"You can provide a custom function to be called after a successful update user request. It is called with three arguments : The user which was updated. The dictionary containing the updated fields. The original Request object . It may be useful if you wish for example update your user in a data analytics or customer success platform. You can define it as an async or standard method. Example: def on_after_update ( user : UserDB , updated_user_data : Dict [ str , Any ], request : Request ): print ( f \"User { user . id } has been updated with the following data: { updated_user_data } \" ) app . include_router ( fastapi_users . get_users_router ( on_after_update ), prefix = \"/users\" , tags = [ \"users\" ], )","title":"After update"},{"location":"configuration/routers/verify/","text":"Verify router \u00b6 Warning This feature is not released yet. 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 fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_verify_router ( \"SECRET\" ), prefix = \"/auth\" , tags = [ \"auth\" ], ) Parameters: verification_token_secret : Secret to encode verify token. verification_token_lifetime_seconds : Lifetime of verify token. Defaults to 3600 . after_verification_request : Optional function called after a successful verify request. See below. after_verification : Optional function called after a successful verification. See below. After verification request \u00b6 You can provide a custom function to be called after a successful verification request. It is called with three arguments : The user for which the verification has been requested. A ready-to-use JWT token that will be accepted by the verify route. The original Request object . Typically, you'll want to send an e-mail with the link (and the token) that allows the user to verify their e-mail. You can define it as an async or standard method. Example: def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) app . include_router ( fastapi_users . get_verify_router ( \"SECRET\" , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], ) After verification \u00b6 You can provide a custom function to be called after a successful user verification. It is called with two arguments : The user that has been verified. The original Request object . This may be useful if you wish to send another e-mail or store this information in a data analytics or customer success platform. You can define it as an async or standard method. Example: def after_verification ( user : UserDB , request : Request ): print ( f \" { user . id } is now verified.\" ) app . include_router ( fastapi_users . get_verify_router ( \"SECRET\" , after_verification = after_verification ), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"Verify router"},{"location":"configuration/routers/verify/#verify-router","text":"Warning This feature is not released yet. 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 fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , ) app = FastAPI () app . include_router ( fastapi_users . get_verify_router ( \"SECRET\" ), prefix = \"/auth\" , tags = [ \"auth\" ], ) Parameters: verification_token_secret : Secret to encode verify token. verification_token_lifetime_seconds : Lifetime of verify token. Defaults to 3600 . after_verification_request : Optional function called after a successful verify request. See below. after_verification : Optional function called after a successful verification. See below.","title":"Setup"},{"location":"configuration/routers/verify/#after-verification-request","text":"You can provide a custom function to be called after a successful verification request. It is called with three arguments : The user for which the verification has been requested. A ready-to-use JWT token that will be accepted by the verify route. The original Request object . Typically, you'll want to send an e-mail with the link (and the token) that allows the user to verify their e-mail. You can define it as an async or standard method. Example: def after_verification_request ( user : UserDB , token : str , request : Request ): print ( f \"Verification requested for user { user . id } . Verification token: { token } \" ) app . include_router ( fastapi_users . get_verify_router ( \"SECRET\" , after_verification_request = after_verification_request ), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"After verification request"},{"location":"configuration/routers/verify/#after-verification","text":"You can provide a custom function to be called after a successful user verification. It is called with two arguments : The user that has been verified. The original Request object . This may be useful if you wish to send another e-mail or store this information in a data analytics or customer success platform. You can define it as an async or standard method. Example: def after_verification ( user : UserDB , request : Request ): print ( f \" { user . id } is now verified.\" ) app . include_router ( fastapi_users . get_verify_router ( \"SECRET\" , after_verification = after_verification ), prefix = \"/auth\" , tags = [ \"auth\" ], )","title":"After verification"},{"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":"usage/dependency-callables/","text":"Dependency callables \u00b6 FastAPI Users provides dependency callables to easily inject users 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 . get_current_user \u00b6 Get the current user ( active or not ). Will throw a 401 Unauthorized if missing or wrong credentials. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_user )): return f \"Hello, { user . email } \" get_current_active_user \u00b6 Get the current active user. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_active_user )): return f \"Hello, { user . email } \" get_current_verified_user \u00b6 Get the current active and verified user. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active and verified. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_verified_user )): return f \"Hello, { user . email } \" get_current_superuser \u00b6 Get the current superuser. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active. Will throw a 403 Forbidden if the user is not a superuser. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_superuser )): return f \"Hello, { user . email } \" get_current_verified_superuser \u00b6 Get the current verified superuser. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active and verified. Will throw a 403 Forbidden if the user is not a superuser. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_verified_superuser )): return f \"Hello, { user . email } \" get_optional_current_user \u00b6 Get the current user ( active or not ). Will return None if missing or wrong credentials. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : Optional [ User ] = Depends ( fastapi_users . get_optional_current_user )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\" get_optional_current_active_user \u00b6 Get the current active user. Will return None if missing or wrong credentials or if the user is not active. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_active_user )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\" get_optional_current_verified_user \u00b6 Get the current active and verified user. Will return None if missing or wrong credentials or if the user is not active and verified. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_verified_user )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\" get_optional_current_superuser \u00b6 Get the current superuser. Will return None if missing or wrong credentials or if the user is not active. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_superuser )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\" get_optional_current_verified_superuser \u00b6 Get the current active and verified superuser. Will return None if missing or wrong credentials or if the user is not active and verified. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_verified_superuser )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\" In 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 ( fastapi_users . get_current_superuser )]) def protected_route (): return \"Hello, some user.\" You can read more about this in FastAPI docs .","title":"Dependency callables"},{"location":"usage/dependency-callables/#dependency-callables","text":"FastAPI Users provides dependency callables to easily inject users 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":"Dependency callables"},{"location":"usage/dependency-callables/#get_current_user","text":"Get the current user ( active or not ). Will throw a 401 Unauthorized if missing or wrong credentials. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_user )): return f \"Hello, { user . email } \"","title":"get_current_user"},{"location":"usage/dependency-callables/#get_current_active_user","text":"Get the current active user. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_active_user )): return f \"Hello, { user . email } \"","title":"get_current_active_user"},{"location":"usage/dependency-callables/#get_current_verified_user","text":"Get the current active and verified user. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active and verified. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_verified_user )): return f \"Hello, { user . email } \"","title":"get_current_verified_user"},{"location":"usage/dependency-callables/#get_current_superuser","text":"Get the current superuser. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active. Will throw a 403 Forbidden if the user is not a superuser. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_superuser )): return f \"Hello, { user . email } \"","title":"get_current_superuser"},{"location":"usage/dependency-callables/#get_current_verified_superuser","text":"Get the current verified superuser. Will throw a 401 Unauthorized if missing or wrong credentials or if the user is not active and verified. Will throw a 403 Forbidden if the user is not a superuser. @app . get ( \"/protected-route\" ) def protected_route ( user : User = Depends ( fastapi_users . get_current_verified_superuser )): return f \"Hello, { user . email } \"","title":"get_current_verified_superuser"},{"location":"usage/dependency-callables/#get_optional_current_user","text":"Get the current user ( active or not ). Will return None if missing or wrong credentials. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : Optional [ User ] = Depends ( fastapi_users . get_optional_current_user )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\"","title":"get_optional_current_user"},{"location":"usage/dependency-callables/#get_optional_current_active_user","text":"Get the current active user. Will return None if missing or wrong credentials or if the user is not active. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_active_user )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\"","title":"get_optional_current_active_user"},{"location":"usage/dependency-callables/#get_optional_current_verified_user","text":"Get the current active and verified user. Will return None if missing or wrong credentials or if the user is not active and verified. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_verified_user )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\"","title":"get_optional_current_verified_user"},{"location":"usage/dependency-callables/#get_optional_current_superuser","text":"Get the current superuser. Will return None if missing or wrong credentials or if the user is not active. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_superuser )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\"","title":"get_optional_current_superuser"},{"location":"usage/dependency-callables/#get_optional_current_verified_superuser","text":"Get the current active and verified superuser. Will return None if missing or wrong credentials or if the user is not active and verified. It can be useful if you wish to change the behaviour of your endpoint if a user is logged in or not. @app . get ( \"/optional-user-route\" ) def optional_user_route ( user : User = Depends ( fastapi_users . get_optional_current_verified_superuser )): if user : return f \"Hello, { user . email } \" else : return \"Hello, anonymous\"","title":"get_optional_current_verified_superuser"},{"location":"usage/dependency-callables/#in-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 ( fastapi_users . get_current_superuser )]) def protected_route (): return \"Hello, some user.\" You can read more about this in FastAPI docs .","title":"In 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 curl \\ -H \"Content-Type: application/json\" \\ -X POST \\ -d \"{\\\"email\\\": \\\"king.arthur@camelot.bt\\\",\\\"password\\\": \\\"guinevere\\\"}\" \\ http://localhost:8000/auth/register axios 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. JWT backend \u00b6 Request \u00b6 cURL curl \\ -H \"Content-Type: multipart/form-data\" \\ -X POST \\ -F \"username=king.arthur@camelot.bt\" \\ -F \"password=guinevere\" \\ http://localhost:8000/auth/jwt/login axios 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 backend \u00b6 Request \u00b6 cURL 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 axios 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 a 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 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 axios 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 curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X PATCH \\ -d \"{\\\"password\\\": \\\"lancelot\\\"}\" \\ http://localhost:8000/users/me axios 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 curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X GET \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios 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 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 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 curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X DELETE \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios 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. Note that it doesn't apply to every authentication backends . For JWT, it doesn't make sense to end the session, the token is valid until it expires. However, for Cookie backend, the server will clear the cookie. Request \u00b6 cURL curl \\ -H \"Content-Type: application/json\" \\ -H \"Cookie: fastapiusersauth= $TOKEN \" \\ -X POST \\ http://localhost:8000/auth/cookie/logout axios 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 curl \\ -H \"Content-Type: application/json\" \\ -X POST \\ -d \"{\\\"email\\\": \\\"king.arthur@camelot.bt\\\",\\\"password\\\": \\\"guinevere\\\"}\" \\ http://localhost:8000/auth/register axios 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/#jwt-backend","text":"","title":"JWT backend"},{"location":"usage/flow/#request_1","text":"cURL curl \\ -H \"Content-Type: multipart/form-data\" \\ -X POST \\ -F \"username=king.arthur@camelot.bt\" \\ -F \"password=guinevere\" \\ http://localhost:8000/auth/jwt/login axios 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-backend","text":"","title":"Cookie backend"},{"location":"usage/flow/#request_2","text":"cURL 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 axios 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 a 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 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 axios 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 curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X PATCH \\ -d \"{\\\"password\\\": \\\"lancelot\\\"}\" \\ http://localhost:8000/users/me axios 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 curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X GET \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios 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 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 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 curl \\ -H \"Content-Type: application/json\" \\ -H \"Authorization: Bearer $TOKEN \" \\ -X DELETE \\ http://localhost:8000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios 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. Note that it doesn't apply to every authentication backends . For JWT, it doesn't make sense to end the session, the token is valid until it expires. However, for Cookie backend, the server will clear the cookie.","title":"6. Logout"},{"location":"usage/flow/#request_8","text":"cURL curl \\ -H \"Content-Type: application/json\" \\ -H \"Cookie: fastapiusersauth= $TOKEN \" \\ -X POST \\ http://localhost:8000/auth/cookie/logout axios 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/helpers/","text":"Helpers \u00b6 FastAPI Users provides some helper functions to perform some actions programmatically. They are available from your FastAPIUsers instance. Create user \u00b6 Create a user. regular_user = await fastapi_users . create_user ( UserCreate ( email = \"king.arthur@camelot.bt\" , password = \"guinevere\" , ) ) superuser = await fastapi_users . create_user ( UserCreate ( email = \"king.arthur@camelot.bt\" , password = \"guinevere\" , is_superuser = True , ) ) Verify user \u00b6 Verify a user. verified_user = await fastapi_users . verify_user ( non_verified_user ) assert verified_user . is_verified is True Get user \u00b6 Retrieve a user by e-mail. user = await fastapi_users . get_user ( \"king.arthur@camelot.bt\" )","title":"Helpers"},{"location":"usage/helpers/#helpers","text":"FastAPI Users provides some helper functions to perform some actions programmatically. They are available from your FastAPIUsers instance.","title":"Helpers"},{"location":"usage/helpers/#create-user","text":"Create a user. regular_user = await fastapi_users . create_user ( UserCreate ( email = \"king.arthur@camelot.bt\" , password = \"guinevere\" , ) ) superuser = await fastapi_users . create_user ( UserCreate ( email = \"king.arthur@camelot.bt\" , password = \"guinevere\" , is_superuser = True , ) )","title":"Create user"},{"location":"usage/helpers/#verify-user","text":"Verify a user. verified_user = await fastapi_users . verify_user ( non_verified_user ) assert verified_user . is_verified is True","title":"Verify user"},{"location":"usage/helpers/#get-user","text":"Retrieve a user by e-mail. user = await fastapi_users . get_user ( \"king.arthur@camelot.bt\" )","title":"Get user"},{"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\" } 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. Tip Some backend (like JWT) won't produce this route. Register router \u00b6 POST /register \u00b6 Register a new user. Will call the 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\" } Reset password router \u00b6 POST /forgot-password \u00b6 Request a reset password procedure. Will generate a temporary token and call the 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\" } Verify router \u00b6 Warning This feature is not released yet. POST /request-verify-token \u00b6 Request a user to verify their e-mail. Will generate a temporary token and call the after_verification_request 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 /verify \u00b6 Verify a user. Requires the token generated by the /request-verify-token route. Will call the call the after_verification handler on success. Payload { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } 200 OK 422 Validation Error 400 Bad Request Expired token. { \"detail\" : \"VERIFY_USER_TOKEN_EXPIRED\" } 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 authentication_backend : name property of a defined authentication method to use to authenticate the user on successful callback. Usually jwt or cookie . 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 400 Bad Request 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 . 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. 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. 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\" }","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. Tip Some backend (like JWT) won't produce this route.","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 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\" }","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 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\" }","title":"POST /reset-password"},{"location":"usage/routes/#verify-router","text":"Warning This feature is not released yet.","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 after_verification_request 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 /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 after_verification handler on success. Payload { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } 200 OK 422 Validation Error 400 Bad Request Expired token. { \"detail\" : \"VERIFY_USER_TOKEN_EXPIRED\" } 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 authentication_backend : name property of a defined authentication method to use to authenticate the user on successful callback. Usually jwt or cookie . 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 400 Bad Request 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 .","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.","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.","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.gz b/sitemap.xml.gz
index d60da30b..fc0e5575 100644
Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ