From f79ca93d75aaf94e6bb6bf14ed9e9c7d0da4919b Mon Sep 17 00:00:00 2001 From: frankie567 Date: Sat, 25 Apr 2020 12:34:09 +0000 Subject: [PATCH] Automated deployment: Sat Apr 25 12:34:09 UTC 2020 bf0c92450199c9eab3c7f38667a03293ce73e125 --- 404.html | 12 + .../authentication/cookie/index.html | 12 + configuration/authentication/index.html | 12 + configuration/authentication/jwt/index.html | 12 + configuration/databases/mongodb/index.html | 12 + configuration/databases/sqlalchemy/index.html | 12 + configuration/databases/tortoise/index.html | 12 + configuration/full_example/index.html | 12 + configuration/model/index.html | 12 + configuration/oauth/index.html | 16 +- configuration/router/index.html | 12 + index.html | 12 + installation/index.html | 12 + search/search_index.json | 2 +- sitemap.xml | 4 + sitemap.xml.gz | Bin 203 -> 203 bytes usage/dependency-callables/index.html | 12 + usage/flow/index.html | 1555 +++++++++++++++++ usage/routes/index.html | 51 +- 19 files changed, 1744 insertions(+), 40 deletions(-) create mode 100644 usage/flow/index.html diff --git a/404.html b/404.html index ac8cf7dc..699ccb1e 100644 --- a/404.html +++ b/404.html @@ -439,6 +439,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes diff --git a/configuration/authentication/cookie/index.html b/configuration/authentication/cookie/index.html index ada84153..ec3b3de6 100644 --- a/configuration/authentication/cookie/index.html +++ b/configuration/authentication/cookie/index.html @@ -518,6 +518,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes diff --git a/configuration/authentication/index.html b/configuration/authentication/index.html index 80ad8919..b82e4c17 100644 --- a/configuration/authentication/index.html +++ b/configuration/authentication/index.html @@ -497,6 +497,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes diff --git a/configuration/authentication/jwt/index.html b/configuration/authentication/jwt/index.html index cbf273b1..babf42ee 100644 --- a/configuration/authentication/jwt/index.html +++ b/configuration/authentication/jwt/index.html @@ -518,6 +518,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes diff --git a/configuration/databases/mongodb/index.html b/configuration/databases/mongodb/index.html index e344e64f..d96eaf6f 100644 --- a/configuration/databases/mongodb/index.html +++ b/configuration/databases/mongodb/index.html @@ -504,6 +504,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes diff --git a/configuration/databases/sqlalchemy/index.html b/configuration/databases/sqlalchemy/index.html index 9016fb2a..9d157a17 100644 --- a/configuration/databases/sqlalchemy/index.html +++ b/configuration/databases/sqlalchemy/index.html @@ -525,6 +525,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes diff --git a/configuration/databases/tortoise/index.html b/configuration/databases/tortoise/index.html index d8be5c38..e3163abd 100644 --- a/configuration/databases/tortoise/index.html +++ b/configuration/databases/tortoise/index.html @@ -518,6 +518,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes diff --git a/configuration/full_example/index.html b/configuration/full_example/index.html index efbf396c..155a66dd 100644 --- a/configuration/full_example/index.html +++ b/configuration/full_example/index.html @@ -488,6 +488,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes diff --git a/configuration/model/index.html b/configuration/model/index.html index 8c106c3e..fc7f35de 100644 --- a/configuration/model/index.html +++ b/configuration/model/index.html @@ -495,6 +495,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes diff --git a/configuration/oauth/index.html b/configuration/oauth/index.html index 76c4c6f6..9c632f97 100644 --- a/configuration/oauth/index.html +++ b/configuration/oauth/index.html @@ -563,6 +563,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes @@ -1069,13 +1081,13 @@ -
  • + Flow + +
  • + + + + + + +
  • Routes diff --git a/index.html b/index.html index 588ba732..03aae170 100644 --- a/index.html +++ b/index.html @@ -527,6 +527,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes diff --git a/installation/index.html b/installation/index.html index fe2ba49f..ddabc55f 100644 --- a/installation/index.html +++ b/installation/index.html @@ -500,6 +500,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes diff --git a/search/search_index.json b/search/search_index.json index 53944bb4..7fa43ea1 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"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, forgot and reset password 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 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 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, forgot and reset password 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","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","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. SQLAlchemy import databases import sqlalchemy from fastapi import FastAPI 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 from starlette.requests import Request DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( User , 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 ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) 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 } \" ) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () MongoDB import motor.motor_asyncio from fastapi import FastAPI from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase from starlette.requests import Request DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( User , models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) 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 } \" ) Tortoise ORM from fastapi import FastAPI from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from starlette.requests import Request from tortoise.contrib.starlette import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( User , 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\" : [ \"test\" ]}) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) 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 } \" ) 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. SQLAlchemy import databases import sqlalchemy from fastapi import FastAPI 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 from starlette.requests import Request DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( User , 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 ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) 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 } \" ) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () MongoDB import motor.motor_asyncio from fastapi import FastAPI from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase from starlette.requests import Request DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( User , models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) 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 } \" ) Tortoise ORM from fastapi import FastAPI from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from starlette.requests import Request from tortoise.contrib.starlette import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( User , 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\" : [ \"test\" ]}) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) 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":"Full example"},{"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 ( str ) \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_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 makes the email compulsory and adds a compulsory password field ; 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 ( User , models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass You can of course add you own properties there to fit to your needs! Next steps \u00b6 Depending on your database backend, 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 ( str ) \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_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 makes the email compulsory and adds a compulsory password field ; 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 ( User , models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass You can of course add you own properties there to fit to your needs!","title":"Define your models"},{"location":"configuration/model/#next-steps","text":"Depending on your database backend, 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 ( User , 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 ( str ) \u2013 Unique identifier of the user. 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 ( 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 shouls 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 , SECRET , ) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , tags = [ \"users\" ]) Full example \u00b6 SQLAlchemy import databases import sqlalchemy from fastapi import FastAPI 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 from starlette.requests import Request DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( User , 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 ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , 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 } \" ) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () MongoDB import motor.motor_asyncio from fastapi import FastAPI 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 from starlette.requests import Request DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( User , models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , 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 } \" ) Tortoise ORM from fastapi import FastAPI 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 starlette.requests import Request from tortoise import fields from tortoise.contrib.starlette 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 ( User , 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\" : [ \"test\" ]}) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , 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":"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 ( User , 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 ( str ) \u2013 Unique identifier of the user. 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 ( 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 shouls 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 , SECRET , ) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , tags = [ \"users\" ])","title":"Generate a router"},{"location":"configuration/oauth/#full-example","text":"SQLAlchemy import databases import sqlalchemy from fastapi import FastAPI 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 from starlette.requests import Request DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( User , 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 ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , 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 } \" ) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () MongoDB import motor.motor_asyncio from fastapi import FastAPI 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 from starlette.requests import Request DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( User , models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , 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 } \" ) Tortoise ORM from fastapi import FastAPI 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 starlette.requests import Request from tortoise import fields from tortoise.contrib.starlette 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 ( User , 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\" : [ \"test\" ]}) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , 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":"Full example"},{"location":"configuration/router/","text":"Router \u00b6 We're almost there! The last step is to configure the FastAPIUsers object that will wire the database adapter, the authentication class and the user models to expose the FastAPI router. 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. reset_password_token_secret : Secret to encode reset password token. reset_password_token_lifetime_seconds : Lifetime of reset password token in seconds. Default to one hour. from fastapi_users import FastAPIUsers fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) And then, include the router in the FastAPI app: app = FastAPI () app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) Event handlers \u00b6 In order to be as unopinionated as possible, we expose decorators that allow you to plug your own logic after some actions. You can have several handlers per event. After register \u00b6 This event handler is 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: @fastapi_users . on_after_register () def on_after_register ( user : User , request : Request ): print ( f \"User { user . id } has registered.\" ) After forgot password \u00b6 This event handler is 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: @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 update \u00b6 This event handler is 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: @fastapi_users . on_after_update () def on_after_update ( user : User , updated_user_data : Dict [ str , Any ], request : Request ): print ( f \"User { user . id } has been updated with the following data: { updated_user_data } \" ) Next steps \u00b6 Check out a full example that will show you the big picture.","title":"Router"},{"location":"configuration/router/#router","text":"We're almost there! The last step is to configure the FastAPIUsers object that will wire the database adapter, the authentication class and the user models to expose the FastAPI router.","title":"Router"},{"location":"configuration/router/#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. reset_password_token_secret : Secret to encode reset password token. reset_password_token_lifetime_seconds : Lifetime of reset password token in seconds. Default to one hour. from fastapi_users import FastAPIUsers fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) And then, include the router in the FastAPI app: app = FastAPI () app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ])","title":"Configure FastAPIUsers"},{"location":"configuration/router/#event-handlers","text":"In order to be as unopinionated as possible, we expose decorators that allow you to plug your own logic after some actions. You can have several handlers per event.","title":"Event handlers"},{"location":"configuration/router/#after-register","text":"This event handler is 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: @fastapi_users . on_after_register () def on_after_register ( user : User , request : Request ): print ( f \"User { user . id } has registered.\" )","title":"After register"},{"location":"configuration/router/#after-forgot-password","text":"This event handler is 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: @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":"After forgot password"},{"location":"configuration/router/#after-update","text":"This event handler is 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: @fastapi_users . on_after_update () def on_after_update ( user : User , updated_user_data : Dict [ str , Any ], request : Request ): print ( f \"User { user . id } has been updated with the following data: { updated_user_data } \" )","title":"After update"},{"location":"configuration/router/#next-steps","text":"Check out a full example that will show you the big picture.","title":"Next steps"},{"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. Each defined method will generate a /login/{name} route where name is defined on the authentication method object. Each defined method will generate a /logout/{name} route where name is defined on the authentication method object. 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. Each defined method will generate a /login/{name} route where name is defined on the authentication method object. Each defined method will generate a /logout/{name} route where name is defined on the authentication method object.","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 optionally define the name which will be used to generate its /login route . Defaults to cookie . cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 , name = \"my-cookie\" , ) 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. 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 API router .","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 optionally define the name which will be used to generate its /login route . Defaults to cookie . cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 , name = \"my-cookie\" , ) 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. 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 API router .","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). You can also optionally define the name which will be used to generate its /login route . 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 { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } Check documentation about login route . Logout \u00b6 This method is not applicable to this backend and won't do anything. 202 Accepted Check documentation about logout route . 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' Next steps \u00b6 We will now configure the main FastAPI Users object that will expose the API router .","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). You can also optionally define the name which will be used to generate its /login route . 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 { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } Check documentation about login route .","title":"Login"},{"location":"configuration/authentication/jwt/#logout","text":"This method is not applicable to this backend and won't do anything. 202 Accepted Check documentation about logout route .","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/#next-steps","text":"We will now configure the main FastAPI Users object that will expose the API router .","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 ( User , 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 ) 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. 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 ( User , 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 ) 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-string 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 ( User , 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 ) 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.","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 ( User , 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 ) 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-string 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 ( User , 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 enigne 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 ( User , 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 () Tip In production, you would probably want to create the tables with Alembic, integrated with migrations, etc. 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 ( User , 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 ( User , 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 enigne 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 ( User , 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 () Tip In production, you would probably want to create the tables with Alembic, integrated with migrations, etc.","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 ( User , 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.starlette import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( User , 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 , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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.starlette import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( User , 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 , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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 Starlette/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.starlette import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( User , 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 , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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.starlette import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( User , 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 , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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.starlette import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( User , 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 , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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 Starlette/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.starlette import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( User , 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 , modules = { \"models\" : [ \"path_to_your_package\" ]})","title":"Register Tortoise"},{"location":"configuration/databases/tortoise/#next-steps","text":"We will now configure an authentication method .","title":"Next steps"},{"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_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 } ' In path operation \u00b6 If you don't need a user, you can use more clear way: @app . get ( '/protected-route' , dependencies = [ Depends ( fastapi_users . get_current_superuser )]) def protected_route (): return 'Hello, some user.' You can see more about it 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_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/#in-path-operation","text":"If you don't need a user, you can use more clear way: @app . get ( '/protected-route' , dependencies = [ Depends ( fastapi_users . get_current_superuser )]) def protected_route (): return 'Hello, some user.' You can see more about it in FastAPI docs .","title":"In path operation"},{"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 . Unauthenticated \u00b6 POST /register \u00b6 Register a new user. Will call the on_after_register event handlers 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\" } POST /login/{name} \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/{name} \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. 202 Accepted The logout process is not applicable for this authentication backend (e.g. JWT). POST /forgot-password \u00b6 Request a reset password procedure. Will generate a temporary token and call the on_after_forgot_password event handlers if the user exists. To prevent malicious users from guessing existing users in your databse, 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\" } OAuth routes \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 of a defined authentication method to use to authenticate the user on successful callback. 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 . Authenticated \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. Superuser \u00b6 GET / \u00b6 Return the list of registered users. 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. 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/#unauthenticated","text":"","title":"Unauthenticated"},{"location":"usage/routes/#post-register","text":"Register a new user. Will call the on_after_register event handlers 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/#post-loginname","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/{name}"},{"location":"usage/routes/#post-logoutname","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. 202 Accepted The logout process is not applicable for this authentication backend (e.g. JWT).","title":"POST /logout/{name}"},{"location":"usage/routes/#post-forgot-password","text":"Request a reset password procedure. Will generate a temporary token and call the on_after_forgot_password event handlers if the user exists. To prevent malicious users from guessing existing users in your databse, 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/#oauth-routes","text":"Each OAuth router you define will expose the two following routes.","title":"OAuth routes"},{"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 of a defined authentication method to use to authenticate the user on successful callback. 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/#authenticated","text":"","title":"Authenticated"},{"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/#superuser","text":"","title":"Superuser"},{"location":"usage/routes/#get","text":"Return the list of registered users. 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.","title":"GET /"},{"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"],"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, forgot and reset password 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 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 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, forgot and reset password 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","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","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. SQLAlchemy import databases import sqlalchemy from fastapi import FastAPI 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 from starlette.requests import Request DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( User , 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 ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) 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 } \" ) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () MongoDB import motor.motor_asyncio from fastapi import FastAPI from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase from starlette.requests import Request DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( User , models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) 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 } \" ) Tortoise ORM from fastapi import FastAPI from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from starlette.requests import Request from tortoise.contrib.starlette import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( User , 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\" : [ \"test\" ]}) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) 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 } \" ) 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. SQLAlchemy import databases import sqlalchemy from fastapi import FastAPI 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 from starlette.requests import Request DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( User , 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 ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) 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 } \" ) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () MongoDB import motor.motor_asyncio from fastapi import FastAPI from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase from starlette.requests import Request DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( User , models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) 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 } \" ) Tortoise ORM from fastapi import FastAPI from fastapi_users import FastAPIUsers , models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import TortoiseBaseUserModel , TortoiseUserDatabase from starlette.requests import Request from tortoise.contrib.starlette import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" class User ( models . BaseUser ): pass class UserCreate ( User , 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\" : [ \"test\" ]}) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) 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":"Full example"},{"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 ( str ) \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_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 makes the email compulsory and adds a compulsory password field ; 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 ( User , models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass You can of course add you own properties there to fit to your needs! Next steps \u00b6 Depending on your database backend, 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 ( str ) \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_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 makes the email compulsory and adds a compulsory password field ; 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 ( User , models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass You can of course add you own properties there to fit to your needs!","title":"Define your models"},{"location":"configuration/model/#next-steps","text":"Depending on your database backend, 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 ( User , 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 ( str ) \u2013 Unique identifier of the user. 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 ( 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 shouls 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 , SECRET , ) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , tags = [ \"users\" ]) Full example \u00b6 SQLAlchemy import databases import sqlalchemy from fastapi import FastAPI 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 from starlette.requests import Request DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( User , 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 ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , 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 } \" ) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () MongoDB import motor.motor_asyncio from fastapi import FastAPI 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 from starlette.requests import Request DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( User , models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , 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 } \" ) Tortoise ORM from fastapi import FastAPI 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 starlette.requests import Request from tortoise import fields from tortoise.contrib.starlette 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 ( User , 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\" : [ \"test\" ]}) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , 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":"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 ( User , 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 ( str ) \u2013 Unique identifier of the user. 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 ( 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 shouls 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 , SECRET , ) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , tags = [ \"users\" ])","title":"Generate a router"},{"location":"configuration/oauth/#full-example","text":"SQLAlchemy import databases import sqlalchemy from fastapi import FastAPI 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 from starlette.requests import Request DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( User , 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 ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , 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 } \" ) @app . on_event ( \"startup\" ) async def startup (): await database . connect () @app . on_event ( \"shutdown\" ) async def shutdown (): await database . disconnect () MongoDB import motor.motor_asyncio from fastapi import FastAPI 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 from starlette.requests import Request DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" google_oauth_client = GoogleOAuth2 ( \"CLIENT_ID\" , \"CLIENT_SECRET\" ) class User ( models . BaseUser , models . BaseOAuthAccountMixin ): pass class UserCreate ( User , models . BaseUserCreate ): pass class UserUpdate ( User , models . BaseUserUpdate ): pass class UserDB ( User , models . BaseUserDB ): pass client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( UserDB , collection ) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , 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 } \" ) Tortoise ORM from fastapi import FastAPI 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 starlette.requests import Request from tortoise import fields from tortoise.contrib.starlette 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 ( User , 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\" : [ \"test\" ]}) auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) google_oauth_router = fastapi_users . get_oauth_router ( google_oauth_client , SECRET ) app . include_router ( google_oauth_router , prefix = \"/google-oauth\" , 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":"Full example"},{"location":"configuration/router/","text":"Router \u00b6 We're almost there! The last step is to configure the FastAPIUsers object that will wire the database adapter, the authentication class and the user models to expose the FastAPI router. 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. reset_password_token_secret : Secret to encode reset password token. reset_password_token_lifetime_seconds : Lifetime of reset password token in seconds. Default to one hour. from fastapi_users import FastAPIUsers fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) And then, include the router in the FastAPI app: app = FastAPI () app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) Event handlers \u00b6 In order to be as unopinionated as possible, we expose decorators that allow you to plug your own logic after some actions. You can have several handlers per event. After register \u00b6 This event handler is 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: @fastapi_users . on_after_register () def on_after_register ( user : User , request : Request ): print ( f \"User { user . id } has registered.\" ) After forgot password \u00b6 This event handler is 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: @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 update \u00b6 This event handler is 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: @fastapi_users . on_after_update () def on_after_update ( user : User , updated_user_data : Dict [ str , Any ], request : Request ): print ( f \"User { user . id } has been updated with the following data: { updated_user_data } \" ) Next steps \u00b6 Check out a full example that will show you the big picture.","title":"Router"},{"location":"configuration/router/#router","text":"We're almost there! The last step is to configure the FastAPIUsers object that will wire the database adapter, the authentication class and the user models to expose the FastAPI router.","title":"Router"},{"location":"configuration/router/#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. reset_password_token_secret : Secret to encode reset password token. reset_password_token_lifetime_seconds : Lifetime of reset password token in seconds. Default to one hour. from fastapi_users import FastAPIUsers fastapi_users = FastAPIUsers ( user_db , auth_backends , User , UserCreate , UserUpdate , UserDB , SECRET , ) And then, include the router in the FastAPI app: app = FastAPI () app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ])","title":"Configure FastAPIUsers"},{"location":"configuration/router/#event-handlers","text":"In order to be as unopinionated as possible, we expose decorators that allow you to plug your own logic after some actions. You can have several handlers per event.","title":"Event handlers"},{"location":"configuration/router/#after-register","text":"This event handler is 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: @fastapi_users . on_after_register () def on_after_register ( user : User , request : Request ): print ( f \"User { user . id } has registered.\" )","title":"After register"},{"location":"configuration/router/#after-forgot-password","text":"This event handler is 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: @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":"After forgot password"},{"location":"configuration/router/#after-update","text":"This event handler is 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: @fastapi_users . on_after_update () def on_after_update ( user : User , updated_user_data : Dict [ str , Any ], request : Request ): print ( f \"User { user . id } has been updated with the following data: { updated_user_data } \" )","title":"After update"},{"location":"configuration/router/#next-steps","text":"Check out a full example that will show you the big picture.","title":"Next steps"},{"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. Each defined method will generate a /login/{name} route where name is defined on the authentication method object. Each defined method will generate a /logout/{name} route where name is defined on the authentication method object. 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. Each defined method will generate a /login/{name} route where name is defined on the authentication method object. Each defined method will generate a /logout/{name} route where name is defined on the authentication method object.","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 optionally define the name which will be used to generate its /login route . Defaults to cookie . cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 , name = \"my-cookie\" , ) 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. 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 API router .","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 optionally define the name which will be used to generate its /login route . Defaults to cookie . cookie_authentication = CookieAuthentication ( secret = SECRET , lifetime_seconds = 3600 , name = \"my-cookie\" , ) 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. 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 API router .","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). You can also optionally define the name which will be used to generate its /login route . 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 { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } Check documentation about login route . Logout \u00b6 This method is not applicable to this backend and won't do anything. 202 Accepted Check documentation about logout route . 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' Next steps \u00b6 We will now configure the main FastAPI Users object that will expose the API router .","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). You can also optionally define the name which will be used to generate its /login route . 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 { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI\" } Check documentation about login route .","title":"Login"},{"location":"configuration/authentication/jwt/#logout","text":"This method is not applicable to this backend and won't do anything. 202 Accepted Check documentation about logout route .","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/#next-steps","text":"We will now configure the main FastAPI Users object that will expose the API router .","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 ( User , 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 ) 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. 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 ( User , 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 ) 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-string 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 ( User , 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 ) 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.","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 ( User , 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 ) 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-string 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 ( User , 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 enigne 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 ( User , 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 () Tip In production, you would probably want to create the tables with Alembic, integrated with migrations, etc. 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 ( User , 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 ( User , 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 enigne 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 ( User , 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 () Tip In production, you would probably want to create the tables with Alembic, integrated with migrations, etc.","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 ( User , 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.starlette import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( User , 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 , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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.starlette import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( User , 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 , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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 Starlette/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.starlette import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( User , 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 , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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.starlette import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( User , 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 , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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.starlette import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( User , 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 , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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 Starlette/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.starlette import register_tortoise class User ( models . BaseUser ): pass class UserCreate ( User , 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 , modules = { \"models\" : [ \"path_to_your_package\" ]})","title":"Register Tortoise"},{"location":"configuration/databases/tortoise/#next-steps","text":"We will now configure an authentication method .","title":"Next steps"},{"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_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 } ' In path operation \u00b6 If you don't need a user, you can use more clear way: @app . get ( '/protected-route' , dependencies = [ Depends ( fastapi_users . get_current_superuser )]) def protected_route (): return 'Hello, some user.' You can see more about it 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_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/#in-path-operation","text":"If you don't need a user, you can use more clear way: @app . get ( '/protected-route' , dependencies = [ Depends ( fastapi_users . get_current_superuser )]) def protected_route (): return 'Hello, some user.' You can see more about it 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:9000/users/register axios axios . post ( 'http://localhost:9000/users/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. Each authentication backend will produce a single route. For example, the JWT backend will produce the /users/login/jwt route. 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:9000/users/login/jwt axios const formData = new FormData (); formData . set ( 'username' , 'king.arthur@camelot.bt' ); formData . set ( 'password' , 'guinevere' ); axios . post ( 'http://localhost:9000/users/login/jwt' , 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: { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM\" } 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:9000/users/login/cookie axios const formData = new FormData (); formData . set ( 'username' , 'king.arthur@camelot.bt' ); formData . set ( 'password' , 'guinevere' ); axios . post ( 'http://localhost:9000/users/login/cookie' , 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:9000/users/me axios const TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM' ; axios . get ( 'http://localhost:9000/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:9000/users/me axios axios . patch ( 'http://localhost:9000/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:9000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios axios . get ( 'http://localhost:9000/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:9000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios axios . patch ( 'http://localhost:9000/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:9000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios axios . delete ( 'http://localhost:9000/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 \"Authorization: Bearer $TOKEN \" \\ -X POST \\ http://localhost:9000/users/logout/cookie axios axios . post ( 'http://localhost:9000/users/logout/cookie' , null , { headers : { 'Authorization' : `Bearer ${ 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:9000/users/register axios axios . post ( 'http://localhost:9000/users/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. Each authentication backend will produce a single route. For example, the JWT backend will produce the /users/login/jwt route. 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:9000/users/login/jwt axios const formData = new FormData (); formData . set ( 'username' , 'king.arthur@camelot.bt' ); formData . set ( 'password' , 'guinevere' ); axios . post ( 'http://localhost:9000/users/login/jwt' , 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: { \"token\" : \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM\" } 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:9000/users/login/cookie axios const formData = new FormData (); formData . set ( 'username' , 'king.arthur@camelot.bt' ); formData . set ( 'password' , 'guinevere' ); axios . post ( 'http://localhost:9000/users/login/cookie' , 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:9000/users/me axios const TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM' ; axios . get ( 'http://localhost:9000/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:9000/users/me axios axios . patch ( 'http://localhost:9000/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:9000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios axios . get ( 'http://localhost:9000/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:9000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios axios . patch ( 'http://localhost:9000/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:9000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476 axios axios . delete ( 'http://localhost:9000/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 \"Authorization: Bearer $TOKEN \" \\ -X POST \\ http://localhost:9000/users/logout/cookie axios axios . post ( 'http://localhost:9000/users/logout/cookie' , null , { headers : { 'Authorization' : `Bearer ${ TOKEN } ` , }, } ) . then (( response ) => console . log ( response )) . catch (( error ) => console . log ( error ));","title":"Request"},{"location":"usage/flow/#response_8","text":"You'll get an empty response.","title":"Response"},{"location":"usage/flow/#conclusion","text":"That's it! You now have a good overview of how you can manage the users through the API. Be sure to check the Routes page to have all the details about each endpoints.","title":"Conclusion"},{"location":"usage/routes/","text":"Routes \u00b6 You'll find here the routes exposed by FastAPI Users . Note that you can also review them through the interactive API docs . Unauthenticated \u00b6 POST /register \u00b6 Register a new user. Will call the on_after_register event handlers 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\" } POST /login/{name} \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/{name} \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. 202 Accepted The logout process is not applicable for this authentication backend (e.g. JWT). POST /forgot-password \u00b6 Request a reset password procedure. Will generate a temporary token and call the on_after_forgot_password event handlers if the user exists. To prevent malicious users from guessing existing users in your databse, 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\" } OAuth routes \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 of a defined authentication method to use to authenticate the user on successful callback. 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 . Authenticated \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. Superuser \u00b6 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/#unauthenticated","text":"","title":"Unauthenticated"},{"location":"usage/routes/#post-register","text":"Register a new user. Will call the on_after_register event handlers 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/#post-loginname","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/{name}"},{"location":"usage/routes/#post-logoutname","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. 202 Accepted The logout process is not applicable for this authentication backend (e.g. JWT).","title":"POST /logout/{name}"},{"location":"usage/routes/#post-forgot-password","text":"Request a reset password procedure. Will generate a temporary token and call the on_after_forgot_password event handlers if the user exists. To prevent malicious users from guessing existing users in your databse, 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/#oauth-routes","text":"Each OAuth router you define will expose the two following routes.","title":"OAuth routes"},{"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 of a defined authentication method to use to authenticate the user on successful callback. 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/#authenticated","text":"","title":"Authenticated"},{"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/#superuser","text":"","title":"Superuser"},{"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 b/sitemap.xml index b107479f..25089fdd 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -55,5 +55,9 @@ None 2020-04-25 daily + + None + 2020-04-25 + daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 775f5eb872d5aa143c739b584e818cf88307f125..1698dd6c181afcaf23831c4d832390d909b6a03d 100644 GIT binary patch literal 203 zcmV;+05ty}iwFolE~H)p|8r?{Wo=<_E_iKh0PU4Q4#FT1MfW`gVPC*T6E&3XT)NT& z5Q;4ch1x-@w-=h4cm@NTVcz`7TMlntgGEn0f$^@!8^SQsPWjfjuEy8Psodj66#Ow+ z&;iA;gBtfCj7Li6c_v_j9^?qbPaOr-#|G#MDI*6g(yk~_dfa*?&faNG)9(u zVihadwybt>ys|Z-dg(fSoAh0@(%3hrKV->pnl#y!UD=gg+4bM9Vkz+=i4S!c5W2wz F002Q5UjqOD literal 203 zcmV;+05ty}iwFph1f*U9|8r?{Wo=<_E_iKh0PU5r4#FT1hW9=NVJ~2#i5f~bM<;y% zLa`;GPAq>71 z6{}duwq>=8g}%C7&rilxLWAwDnlZI4w3 F001V>UO)f< diff --git a/usage/dependency-callables/index.html b/usage/dependency-callables/index.html index 87d84aed..8197fcf7 100644 --- a/usage/dependency-callables/index.html +++ b/usage/dependency-callables/index.html @@ -446,6 +446,18 @@ +
  • + + Flow + +
  • + + + + + + +
  • Routes diff --git a/usage/flow/index.html b/usage/flow/index.html new file mode 100644 index 00000000..10c11ac7 --- /dev/null +++ b/usage/flow/index.html @@ -0,0 +1,1555 @@ + + + + + + + + + + + + + + + + + + + + Flow - FastAPI Users + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + Skip to content + + +
    +
    + +
    + +
    + +
    + +
    + + + + + + +
    +
    + + +
    +
    +
    + +
    +
    +
    + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + +

    Flow

    +

    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

    +

    First step, of course, is to register as a user.

    +

    Request

    +
    +
    curl \
    +-H "Content-Type: application/json" \
    +-X POST \
    +-d "{\"email\": \"king.arthur@camelot.bt\",\"password\": \"guinevere\"}" \
    +http://localhost:9000/users/register
    +
    + +
    +
    +
    axios.post('http://localhost:9000/users/register', {
    +    email: 'king.arthur@camelot.bt',
    +    password: 'guinevere',
    +})
    +.then((response) => console.log(response))
    +.catch((error) => console.log(error));
    +
    + +
    +
    +

    Response

    +

    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

    +

    Now, you can login as this new user.

    +

    Each authentication backend will produce a single route. For example, the JWT backend will produce the /users/login/jwt route. Each backend will have a different response.

    +

    JWT backend

    +

    Request

    +
    +
    curl \
    +-H "Content-Type: multipart/form-data" \
    +-X POST \
    +-F "username=king.arthur@camelot.bt" \
    +-F "password=guinevere" \
    +http://localhost:9000/users/login/jwt
    +
    + +
    +
    +
    const formData = new FormData();
    +formData.set('username', 'king.arthur@camelot.bt');
    +formData.set('password', 'guinevere');
    +axios.post(
    +    'http://localhost:9000/users/login/jwt',
    +    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

    +

    You'll get a JSON response looking like this:

    +
    {
    +    "token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM"
    +}
    +
    + +

    You can use this token to make authenticated requests as the user king.arthur@camelot.bt. We'll see how in the next section.

    + +

    Request

    +
    +
    curl \
    +-v \
    +-H "Content-Type: multipart/form-data" \
    +-X POST \
    +-F "username=king.arthur@camelot.bt" \
    +-F "password=guinevere" \
    +http://localhost:9000/users/login/cookie
    +
    + +
    +
    +
    const formData = new FormData();
    +formData.set('username', 'king.arthur@camelot.bt');
    +formData.set('password', 'guinevere');
    +axios.post(
    +    'http://localhost:9000/users/login/cookie',
    +    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

    +

    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

    +

    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

    +
    +
    export TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM";
    +curl \
    +-H "Content-Type: application/json" \
    +-H "Authorization: Bearer $TOKEN" \
    +-X GET \
    +http://localhost:9000/users/me
    +
    + +
    +
    +
    const TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiNGZkMzQ3N2ItZWNjZi00ZWUzLThmN2QtNjhhZDcyMjYxNDc2IiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTg3ODE4NDI5fQ.anO3JR8-WYCozZ4_2-PQ2Ov9O38RaLP2RAzQIiZhteM';
    +axios.get(
    +    'http://localhost:9000/users/me', {
    +    headers: {
    +        'Authorization': `Bearer ${TOKEN}`,
    +    },
    +})
    +.then((response) => console.log(response))
    +.catch((error) => console.log(error));
    +
    + +
    +
    +

    Response

    +

    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

    +

    We can also update our own profile. For example, we can change our password like this.

    +

    Request

    +
    +
    curl \
    +-H "Content-Type: application/json" \
    +-H "Authorization: Bearer $TOKEN" \
    +-X PATCH \
    +-d "{\"password\": \"lancelot\"}" \
    +http://localhost:9000/users/me
    +
    + +
    +
    +
    axios.patch(
    +    'http://localhost:9000/users/me',
    +    {
    +        password: 'lancelot',
    +    },
    +    {
    +        headers: {
    +            'Authorization': `Bearer ${TOKEN}`,
    +        },
    +    },
    +)
    +.then((response) => console.log(response))
    +.catch((error) => console.log(error));
    +
    + +
    +
    +

    Response

    +

    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 πŸ¦ΈπŸ»β€β™‚οΈ

    +

    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

    +

    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

    +
    +
    curl \
    +-H "Content-Type: application/json" \
    +-H "Authorization: Bearer $TOKEN" \
    +-X GET \
    +http://localhost:9000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476
    +
    + +
    +
    +
    axios.get(
    +    'http://localhost:9000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476', {
    +    headers: {
    +        'Authorization': `Bearer ${TOKEN}`,
    +    },
    +})
    +.then((response) => console.log(response))
    +.catch((error) => console.log(error));
    +
    + +
    +
    +

    Response

    +

    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

    +

    We can now update the profile of any user. For example, we can promote it as superuser.

    +

    Request

    +
    +
    curl \
    +-H "Content-Type: application/json" \
    +-H "Authorization: Bearer $TOKEN" \
    +-X PATCH \
    + -d "{\"is_superuser\": true}" \
    +http://localhost:9000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476
    +
    + +
    +
    +
    axios.patch(
    +    'http://localhost:9000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476',
    +    {
    +        is_superuser: true,
    +    },
    +    {
    +        headers: {
    +            'Authorization': `Bearer ${TOKEN}`,
    +        },
    +    },
    +)
    +.then((response) => console.log(response))
    +.catch((error) => console.log(error));
    +
    + +
    +
    +

    Response

    +

    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

    +

    Finally, we can delete a user.

    +

    Request

    +
    +
    curl \
    +-H "Content-Type: application/json" \
    +-H "Authorization: Bearer $TOKEN" \
    +-X DELETE \
    +http://localhost:9000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476
    +
    + +
    +
    +
    axios.delete(
    +    'http://localhost:9000/users/4fd3477b-eccf-4ee3-8f7d-68ad72261476',
    +    {
    +        headers: {
    +            'Authorization': `Bearer ${TOKEN}`,
    +        },
    +    },
    +)
    +.then((response) => console.log(response))
    +.catch((error) => console.log(error));
    +
    + +
    +
    +

    Response

    +

    You'll get an empty response.

    +

    6. Logout

    +

    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

    +
    +
    curl \
    +-H "Content-Type: application/json" \
    +-H "Authorization: Bearer $TOKEN" \
    +-X POST \
    +http://localhost:9000/users/logout/cookie
    +
    + +
    +
    +
    axios.post('http://localhost:9000/users/logout/cookie',
    +    null,
    +    {
    +        headers: {
    +            'Authorization': `Bearer ${TOKEN}`,
    +        },
    +    }
    +)
    +.then((response) => console.log(response))
    +.catch((error) => console.log(error));
    +
    + +
    +
    +

    Response

    +

    You'll get an empty response.

    +

    Conclusion

    +

    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.

    + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/usage/routes/index.html b/usage/routes/index.html index 6c5f176d..bb361497 100644 --- a/usage/routes/index.html +++ b/usage/routes/index.html @@ -445,6 +445,18 @@ + +
  • + + Flow + +
  • + + + + + + @@ -591,13 +603,6 @@