diff --git a/configuration/databases/mongodb/index.html b/configuration/databases/mongodb/index.html index 2d8fae8b..49354a8f 100644 --- a/configuration/databases/mongodb/index.html +++ b/configuration/databases/mongodb/index.html @@ -590,8 +590,26 @@

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"]
@@ -601,7 +619,7 @@
 app = FastAPI()
 
 
-user_db = MongoDBUserDatabase(collection)
+user_db = MongoDBUserDatabase(UserDB, collection)
 

You can choose any name for the database and the collection.

@@ -609,8 +627,26 @@

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"]
@@ -620,9 +656,10 @@
 app = FastAPI()
 
 
-user_db = MongoDBUserDatabase(collection)
+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.

diff --git a/configuration/databases/sqlalchemy/index.html b/configuration/databases/sqlalchemy/index.html index 70c40e55..e692fc6d 100644 --- a/configuration/databases/sqlalchemy/index.html +++ b/configuration/databases/sqlalchemy/index.html @@ -645,9 +645,27 @@
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)
@@ -666,7 +684,7 @@
 Base.metadata.create_all(engine)
 
 users = UserTable.__table__
-user_db = SQLAlchemyUserDatabase(database, users)
+user_db = SQLAlchemyUserDatabase(UserDB, database, users)
 
 app = FastAPI()
 
@@ -687,9 +705,27 @@
 
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)
@@ -708,7 +744,7 @@
 Base.metadata.create_all(engine)
 
 users = UserTable.__table__
-user_db = SQLAlchemyUserDatabase(database, users)
+user_db = SQLAlchemyUserDatabase(UserDB, database, users)
 
 app = FastAPI()
 
@@ -732,9 +768,27 @@
 
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)
@@ -753,7 +807,7 @@
 Base.metadata.create_all(engine)
 
 users = UserTable.__table__
-user_db = SQLAlchemyUserDatabase(database, users)
+user_db = SQLAlchemyUserDatabase(UserDB, database, users)
 
 app = FastAPI()
 
@@ -768,7 +822,12 @@
     await database.disconnect()
 
-

Notice that we declare the users variable, which is the actual SQLAlchemy table behind the table class. We also use our database instance, which allows us to do asynchronous request to the database.

+

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

We will now configure an authentication method.

What about SQLAlchemy ORM?

diff --git a/configuration/databases/tortoise/index.html b/configuration/databases/tortoise/index.html index 9080abde..3ecf49fe 100644 --- a/configuration/databases/tortoise/index.html +++ b/configuration/databases/tortoise/index.html @@ -627,62 +627,114 @@

For the sake of this tutorial from now on, we'll use a simple SQLite databse.

Setup User table

-

Let's declare our User model.

+

Let's declare our User ORM model.

from fastapi import FastAPI
-from fastapi_users.db.tortoise import BaseUserModel, TortoiseUserDatabase
-from tortoise import Model
+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(BaseUserModel, Model):
+class UserModel(TortoiseBaseUserModel):
     pass
 
 
-user_db = TortoiseUserDatabase(UserModel)
+user_db = TortoiseUserDatabase(UserDB, UserModel)
 app = FastAPI()
 
 register_tortoise(app, modules={"models": ["path_to_your_package"]})
 
-

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!

+

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

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.db.tortoise import BaseUserModel, TortoiseUserDatabase
-from tortoise import Model
+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(BaseUserModel, Model):
+class UserModel(TortoiseBaseUserModel):
     pass
 
 
-user_db = TortoiseUserDatabase(UserModel)
+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

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.db.tortoise import BaseUserModel, TortoiseUserDatabase
-from tortoise import Model
+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(BaseUserModel, Model):
+class UserModel(TortoiseBaseUserModel):
     pass
 
 
-user_db = TortoiseUserDatabase(UserModel)
+user_db = TortoiseUserDatabase(UserDB, UserModel)
 app = FastAPI()
 
 register_tortoise(app, modules={"models": ["path_to_your_package"]})
diff --git a/configuration/full_example/index.html b/configuration/full_example/index.html
index ab932954..32584d98 100644
--- a/configuration/full_example/index.html
+++ b/configuration/full_example/index.html
@@ -562,7 +562,7 @@
 
import databases
 import sqlalchemy
 from fastapi import FastAPI
-from fastapi_users import BaseUser, FastAPIUsers
+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
@@ -571,8 +571,23 @@
 SECRET = "SECRET"
 
 
-database = databases.Database(DATABASE_URL)
+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()
 
 
@@ -583,15 +598,10 @@
 engine = sqlalchemy.create_engine(
     DATABASE_URL, connect_args={"check_same_thread": False}
 )
-
 Base.metadata.create_all(engine)
 
 users = UserTable.__table__
-user_db = SQLAlchemyUserDatabase(database, users)
-
-
-class User(BaseUser):
-    pass
+user_db = SQLAlchemyUserDatabase(UserDB, database, users)
 
 
 auth_backends = [
@@ -599,7 +609,9 @@
 ]
 
 app = FastAPI()
-fastapi_users = FastAPIUsers(user_db, auth_backends, User, SECRET)
+fastapi_users = FastAPIUsers(
+    user_db, auth_backends, User, UserCreate, UserUpdate, UserDB, SECRET,
+)
 app.include_router(fastapi_users.router, prefix="/users", tags=["users"])
 
 
@@ -626,7 +638,7 @@
 
 
import motor.motor_asyncio
 from fastapi import FastAPI
-from fastapi_users import BaseUser, FastAPIUsers
+from fastapi_users import FastAPIUsers, models
 from fastapi_users.authentication import JWTAuthentication
 from fastapi_users.db import MongoDBUserDatabase
 
@@ -634,24 +646,35 @@
 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(collection)
-
-
-class User(BaseUser):
-    pass
-
+user_db = MongoDBUserDatabase(UserDB, collection)
 
 auth_backends = [
     JWTAuthentication(secret=SECRET, lifetime_seconds=3600),
 ]
 
 app = FastAPI()
-fastapi_users = FastAPIUsers(user_db, auth_backends, User, SECRET)
+fastapi_users = FastAPIUsers(
+    user_db, auth_backends, User, UserCreate, UserUpdate, UserDB, SECRET,
+)
 app.include_router(fastapi_users.router, prefix="/users", tags=["users"])
 
 
@@ -667,30 +690,46 @@
 
 
 
from fastapi import FastAPI
-from fastapi_users import BaseUser, FastAPIUsers
+from fastapi_users import FastAPIUsers, models
 from fastapi_users.authentication import JWTAuthentication
-from fastapi_users.db.tortoise import BaseUserModel, TortoiseUserDatabase
-from tortoise import Model
+from fastapi_users.db import TortoiseBaseUserModel, TortoiseUserDatabase
 from tortoise.contrib.starlette import register_tortoise
 
 DATABASE_URL = "sqlite://./test.db"
 SECRET = "SECRET"
 
 
-class UserModel(BaseUserModel, Model):
+class User(models.BaseUser):
     pass
 
 
-class User(BaseUser):
+class UserCreate(User, models.BaseUserCreate):
     pass
 
 
-auth = JWTAuthentication(secret=SECRET, lifetime_seconds=3600)
-user_db = TortoiseUserDatabase(UserModel)
+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"]})
-fastapi_users = FastAPIUsers(user_db, auth, User, SECRET)
+
+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"])
 
 
diff --git a/configuration/model/index.html b/configuration/model/index.html
index eb1b28de..50e092ee 100644
--- a/configuration/model/index.html
+++ b/configuration/model/index.html
@@ -296,8 +296,8 @@
     
  • - - Use the model + + Define your models
  • @@ -538,8 +538,8 @@
    • - - Use the model + + Define your models
    • @@ -576,12 +576,31 @@
    • is_active (bool) – Whether or not the user is active. If not, login and forgot password requests will be denied. Default to True.
    • is_active (bool) – Whether or not the user is a superuser. Useful to implement administration logic. Default to False.
    -

    Use the model

    -

    The model is exposed as a Pydantic model mixin.

    -
    from fastapi_users import BaseUser
    +

    Define your models

    +

    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(BaseUser):
    +class User(models.BaseUser):
    +    pass
    +
    +
    +class UserCreate(User, models.BaseUserCreate):
    +    pass
    +
    +
    +class UserUpdate(User, models.BaseUserUpdate):
    +    pass
    +
    +
    +class UserDB(User, models.BaseUserDB):
         pass
     
    diff --git a/configuration/router/index.html b/configuration/router/index.html index 73f82033..79d96b53 100644 --- a/configuration/router/index.html +++ b/configuration/router/index.html @@ -623,13 +623,16 @@

    Router

    -

    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 model to expose the FastAPI router.

    +

    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

    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.
    @@ -639,6 +642,9 @@ user_db, auth_backends, User, + UserCreate, + UserUpdate, + UserDB, SECRET, )
    diff --git a/index.html b/index.html index 1ba2f252..94528a57 100644 --- a/index.html +++ b/index.html @@ -660,6 +660,7 @@
  • Customizable database backend
  • Multiple customizable authentication backends
      diff --git a/search/search_index.json b/search/search_index.json index 12f819f8..a591c011 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. 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 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. 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 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 BaseUser , FastAPIUsers from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" 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 ( database , users ) class User ( BaseUser ): pass auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , SECRET ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) @fastapi_users . on_after_register () def on_after_register ( user : User ): print ( f \"User {user.id} has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str ): 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 BaseUser , FastAPIUsers from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( collection ) class User ( BaseUser ): pass auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , SECRET ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) @fastapi_users . on_after_register () def on_after_register ( user : User ): print ( f \"User {user.id} has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str ): print ( f \"User {user.id} has forgot their password. Reset token: {token} \" ) Tortoise ORM from fastapi import FastAPI from fastapi_users import BaseUser , FastAPIUsers from fastapi_users.authentication import JWTAuthentication from fastapi_users.db.tortoise import BaseUserModel , TortoiseUserDatabase from tortoise import Model from tortoise.contrib.starlette import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" class UserModel ( BaseUserModel , Model ): pass class User ( BaseUser ): pass auth = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) user_db = TortoiseUserDatabase ( UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"test\" ]}) fastapi_users = FastAPIUsers ( user_db , auth , User , SECRET ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) @fastapi_users . on_after_register () def on_after_register ( user : User ): print ( f \"User {user.id} has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str ): 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 BaseUser , FastAPIUsers from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base DATABASE_URL = \"sqlite:///./test.db\" SECRET = \"SECRET\" 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 ( database , users ) class User ( BaseUser ): pass auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , SECRET ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) @fastapi_users . on_after_register () def on_after_register ( user : User ): print ( f \"User {user.id} has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str ): 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 BaseUser , FastAPIUsers from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase DATABASE_URL = \"mongodb://localhost:27017\" SECRET = \"SECRET\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] user_db = MongoDBUserDatabase ( collection ) class User ( BaseUser ): pass auth_backends = [ JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ), ] app = FastAPI () fastapi_users = FastAPIUsers ( user_db , auth_backends , User , SECRET ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) @fastapi_users . on_after_register () def on_after_register ( user : User ): print ( f \"User {user.id} has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str ): print ( f \"User {user.id} has forgot their password. Reset token: {token} \" ) Tortoise ORM from fastapi import FastAPI from fastapi_users import BaseUser , FastAPIUsers from fastapi_users.authentication import JWTAuthentication from fastapi_users.db.tortoise import BaseUserModel , TortoiseUserDatabase from tortoise import Model from tortoise.contrib.starlette import register_tortoise DATABASE_URL = \"sqlite://./test.db\" SECRET = \"SECRET\" class UserModel ( BaseUserModel , Model ): pass class User ( BaseUser ): pass auth = JWTAuthentication ( secret = SECRET , lifetime_seconds = 3600 ) user_db = TortoiseUserDatabase ( UserModel ) app = FastAPI () register_tortoise ( app , db_url = DATABASE_URL , modules = { \"models\" : [ \"test\" ]}) fastapi_users = FastAPIUsers ( user_db , auth , User , SECRET ) app . include_router ( fastapi_users . router , prefix = \"/users\" , tags = [ \"users\" ]) @fastapi_users . on_after_register () def on_after_register ( user : User ): print ( f \"User {user.id} has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str ): 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_active ( bool ) \u2013 Whether or not the user is a superuser. Useful to implement administration logic. Default to False . Use the model \u00b6 The model is exposed as a Pydantic model mixin. from fastapi_users import BaseUser class User ( BaseUser ): 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_active ( bool ) \u2013 Whether or not the user is a superuser. Useful to implement administration logic. Default to False .","title":"User model"},{"location":"configuration/model/#use-the-model","text":"The model is exposed as a Pydantic model mixin. from fastapi_users import BaseUser class User ( BaseUser ): pass You can of course add you own properties there to fit to your needs!","title":"Use the model"},{"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/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 model 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. 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 , 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 one argument : the user that has just registered. 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 ): 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 two arguments : the user which has requested to reset their password and a ready-to-use JWT token that will be accepted by the reset password route. 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 ): print ( f \"User {user.id} has forgot their password. Reset token: {token} \" ) 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 model 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. 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 , 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 one argument : the user that has just registered. 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 ): 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 two arguments : the user which has requested to reset their password and a ready-to-use JWT token that will be accepted by the reset password route. 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 ): print ( f \"User {user.id} has forgot their password. Reset token: {token} \" )","title":"After forgot password"},{"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. 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.","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 cookie_name . Defaults to fastapiusersauth . You can also 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\" , ) 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 . 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 cookie_name . Defaults to fastapiusersauth . You can also 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\" , ) 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/#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 . 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/#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.db import MongoDBUserDatabase DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] app = FastAPI () user_db = MongoDBUserDatabase ( 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.db import MongoDBUserDatabase DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] app = FastAPI () user_db = MongoDBUserDatabase ( collection ) 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.db import MongoDBUserDatabase DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] app = FastAPI () user_db = MongoDBUserDatabase ( 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.db import MongoDBUserDatabase DATABASE_URL = \"mongodb://localhost:27017\" client = motor . motor_asyncio . AsyncIOMotorClient ( DATABASE_URL ) db = client [ \"database_name\" ] collection = db [ \"users\" ] app = FastAPI () user_db = MongoDBUserDatabase ( collection ) 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.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base 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 ( 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.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base 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 ( 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.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base 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 ( 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 declare the users variable, which is the actual SQLAlchemy table behind the table class. We also use our 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.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base 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 ( 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.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base 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 ( 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.db import SQLAlchemyBaseUserTable , SQLAlchemyUserDatabase from sqlalchemy.ext.declarative import DeclarativeMeta , declarative_base 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 ( 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 declare the users variable, which is the actual SQLAlchemy table behind the table class. We also use our 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 model. from fastapi import FastAPI from fastapi_users.db.tortoise import BaseUserModel , TortoiseUserDatabase from tortoise import Model from tortoise.contrib.starlette import register_tortoise DATABASE_URL = \"sqlite://./test.db\" class UserModel ( BaseUserModel , Model ): pass user_db = TortoiseUserDatabase ( UserModel ) app = FastAPI () register_tortoise ( app , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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 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.db.tortoise import BaseUserModel , TortoiseUserDatabase from tortoise import Model from tortoise.contrib.starlette import register_tortoise DATABASE_URL = \"sqlite://./test.db\" class UserModel ( BaseUserModel , Model ): pass user_db = TortoiseUserDatabase ( UserModel ) app = FastAPI () register_tortoise ( app , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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.db.tortoise import BaseUserModel , TortoiseUserDatabase from tortoise import Model from tortoise.contrib.starlette import register_tortoise DATABASE_URL = \"sqlite://./test.db\" class UserModel ( BaseUserModel , Model ): pass user_db = TortoiseUserDatabase ( 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 model. from fastapi import FastAPI from fastapi_users.db.tortoise import BaseUserModel , TortoiseUserDatabase from tortoise import Model from tortoise.contrib.starlette import register_tortoise DATABASE_URL = \"sqlite://./test.db\" class UserModel ( BaseUserModel , Model ): pass user_db = TortoiseUserDatabase ( UserModel ) app = FastAPI () register_tortoise ( app , modules = { \"models\" : [ \"path_to_your_package\" ]}) 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/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.db.tortoise import BaseUserModel , TortoiseUserDatabase from tortoise import Model from tortoise.contrib.starlette import register_tortoise DATABASE_URL = \"sqlite://./test.db\" class UserModel ( BaseUserModel , Model ): pass user_db = TortoiseUserDatabase ( UserModel ) app = FastAPI () register_tortoise ( app , modules = { \"models\" : [ \"path_to_your_package\" ]})","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.db.tortoise import BaseUserModel , TortoiseUserDatabase from tortoise import Model from tortoise.contrib.starlette import register_tortoise DATABASE_URL = \"sqlite://./test.db\" class UserModel ( BaseUserModel , Model ): pass user_db = TortoiseUserDatabase ( 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 /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\" } 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-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/#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. 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. 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 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 ): print ( f \"User {user.id} has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str ): 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 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 ): print ( f \"User {user.id} has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str ): 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 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 ): print ( f \"User {user.id} has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str ): 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 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 ): print ( f \"User {user.id} has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str ): 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 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 ): print ( f \"User {user.id} has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str ): 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 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 ): print ( f \"User {user.id} has registered.\" ) @fastapi_users . on_after_forgot_password () def on_after_forgot_password ( user : User , token : str ): 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_active ( 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_active ( 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/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 one argument : the user that has just registered. 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 ): 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 two arguments : the user which has requested to reset their password and a ready-to-use JWT token that will be accepted by the reset password route. 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 ): print ( f \"User {user.id} has forgot their password. Reset token: {token} \" ) 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 one argument : the user that has just registered. 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 ): 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 two arguments : the user which has requested to reset their password and a ready-to-use JWT token that will be accepted by the reset password route. 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 ): print ( f \"User {user.id} has forgot their password. Reset token: {token} \" )","title":"After forgot password"},{"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. 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.","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 cookie_name . Defaults to fastapiusersauth . You can also 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\" , ) 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 . 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 cookie_name . Defaults to fastapiusersauth . You can also 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\" , ) 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/#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 . 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/#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 /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\" } 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-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/#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 diff --git a/sitemap.xml b/sitemap.xml index 3d0e68e9..53d6c68e 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,67 +2,67 @@ None - 2019-12-29 + 2020-01-04 daily None - 2019-12-29 + 2020-01-04 daily None - 2019-12-29 + 2020-01-04 daily None - 2019-12-29 + 2020-01-04 daily None - 2019-12-29 + 2020-01-04 daily None - 2019-12-29 + 2020-01-04 daily None - 2019-12-29 + 2020-01-04 daily None - 2019-12-29 + 2020-01-04 daily None - 2019-12-29 + 2020-01-04 daily None - 2019-12-29 + 2020-01-04 daily None - 2019-12-29 + 2020-01-04 daily None - 2019-12-29 + 2020-01-04 daily None - 2019-12-29 + 2020-01-04 daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 8812692a..71b4c7d9 100644 Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ diff --git a/src/db_mongodb.py b/src/db_mongodb.py index 6ee9eb90..53adfe47 100644 --- a/src/db_mongodb.py +++ b/src/db_mongodb.py @@ -1,7 +1,25 @@ 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"] @@ -11,4 +29,4 @@ collection = db["users"] app = FastAPI() -user_db = MongoDBUserDatabase(collection) +user_db = MongoDBUserDatabase(UserDB, collection) diff --git a/src/db_sqlalchemy.py b/src/db_sqlalchemy.py index e9204585..8710e47c 100644 --- a/src/db_sqlalchemy.py +++ b/src/db_sqlalchemy.py @@ -1,9 +1,27 @@ 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) @@ -22,7 +40,7 @@ engine = sqlalchemy.create_engine( Base.metadata.create_all(engine) users = UserTable.__table__ -user_db = SQLAlchemyUserDatabase(database, users) +user_db = SQLAlchemyUserDatabase(UserDB, database, users) app = FastAPI() diff --git a/src/db_tortoise.py b/src/db_tortoise.py index 6b9072b2..9585f3e4 100644 --- a/src/db_tortoise.py +++ b/src/db_tortoise.py @@ -1,16 +1,33 @@ from fastapi import FastAPI -from fastapi_users.db.tortoise import BaseUserModel, TortoiseUserDatabase -from tortoise import Model +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(BaseUserModel, Model): +class UserModel(TortoiseBaseUserModel): pass -user_db = TortoiseUserDatabase(UserModel) +user_db = TortoiseUserDatabase(UserDB, UserModel) app = FastAPI() register_tortoise(app, modules={"models": ["path_to_your_package"]}) diff --git a/src/full_mongodb.py b/src/full_mongodb.py index a9c7a127..f7b84702 100644 --- a/src/full_mongodb.py +++ b/src/full_mongodb.py @@ -1,6 +1,6 @@ import motor.motor_asyncio from fastapi import FastAPI -from fastapi_users import BaseUser, FastAPIUsers +from fastapi_users import FastAPIUsers, models from fastapi_users.authentication import JWTAuthentication from fastapi_users.db import MongoDBUserDatabase @@ -8,24 +8,35 @@ 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(collection) - - -class User(BaseUser): - pass - +user_db = MongoDBUserDatabase(UserDB, collection) auth_backends = [ JWTAuthentication(secret=SECRET, lifetime_seconds=3600), ] app = FastAPI() -fastapi_users = FastAPIUsers(user_db, auth_backends, User, SECRET) +fastapi_users = FastAPIUsers( + user_db, auth_backends, User, UserCreate, UserUpdate, UserDB, SECRET, +) app.include_router(fastapi_users.router, prefix="/users", tags=["users"]) diff --git a/src/full_sqlalchemy.py b/src/full_sqlalchemy.py index f8091d4e..6a97235c 100644 --- a/src/full_sqlalchemy.py +++ b/src/full_sqlalchemy.py @@ -1,7 +1,7 @@ import databases import sqlalchemy from fastapi import FastAPI -from fastapi_users import BaseUser, FastAPIUsers +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 @@ -10,8 +10,23 @@ DATABASE_URL = "sqlite:///./test.db" SECRET = "SECRET" -database = databases.Database(DATABASE_URL) +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() @@ -22,15 +37,10 @@ class UserTable(Base, SQLAlchemyBaseUserTable): engine = sqlalchemy.create_engine( DATABASE_URL, connect_args={"check_same_thread": False} ) - Base.metadata.create_all(engine) users = UserTable.__table__ -user_db = SQLAlchemyUserDatabase(database, users) - - -class User(BaseUser): - pass +user_db = SQLAlchemyUserDatabase(UserDB, database, users) auth_backends = [ @@ -38,7 +48,9 @@ auth_backends = [ ] app = FastAPI() -fastapi_users = FastAPIUsers(user_db, auth_backends, User, SECRET) +fastapi_users = FastAPIUsers( + user_db, auth_backends, User, UserCreate, UserUpdate, UserDB, SECRET, +) app.include_router(fastapi_users.router, prefix="/users", tags=["users"]) diff --git a/src/full_tortoise.py b/src/full_tortoise.py index 8a631fcc..72121786 100644 --- a/src/full_tortoise.py +++ b/src/full_tortoise.py @@ -1,28 +1,44 @@ from fastapi import FastAPI -from fastapi_users import BaseUser, FastAPIUsers +from fastapi_users import FastAPIUsers, models from fastapi_users.authentication import JWTAuthentication -from fastapi_users.db.tortoise import BaseUserModel, TortoiseUserDatabase -from tortoise import Model +from fastapi_users.db import TortoiseBaseUserModel, TortoiseUserDatabase from tortoise.contrib.starlette import register_tortoise DATABASE_URL = "sqlite://./test.db" SECRET = "SECRET" -class UserModel(BaseUserModel, Model): +class User(models.BaseUser): pass -class User(BaseUser): +class UserCreate(User, models.BaseUserCreate): pass -auth = JWTAuthentication(secret=SECRET, lifetime_seconds=3600) -user_db = TortoiseUserDatabase(UserModel) +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"]}) -fastapi_users = FastAPIUsers(user_db, auth, User, SECRET) + +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"])