Get Current User¶
In the previous chapter the security system (which is based on the dependency injection system) was giving thepath operation function atoken as astr:
fromtypingimportAnnotatedfromfastapiimportDepends,FastAPIfromfastapi.securityimportOAuth2PasswordBearerapp=FastAPI()oauth2_scheme=OAuth2PasswordBearer(tokenUrl="token")@app.get("/items/")asyncdefread_items(token:Annotated[str,Depends(oauth2_scheme)]):return{"token":token}🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportDepends,FastAPIfromfastapi.securityimportOAuth2PasswordBearerapp=FastAPI()oauth2_scheme=OAuth2PasswordBearer(tokenUrl="token")@app.get("/items/")asyncdefread_items(token:str=Depends(oauth2_scheme)):return{"token":token}But that is still not that useful.
Let's make it give us the current user.
Create a user model¶
First, let's create a Pydantic user model.
The same way we use Pydantic to declare bodies, we can use it anywhere else:
fromtypingimportAnnotatedfromfastapiimportDepends,FastAPIfromfastapi.securityimportOAuth2PasswordBearerfrompydanticimportBaseModelapp=FastAPI()oauth2_scheme=OAuth2PasswordBearer(tokenUrl="token")classUser(BaseModel):username:stremail:str|None=Nonefull_name:str|None=Nonedisabled:bool|None=Nonedeffake_decode_token(token):returnUser(username=token+"fakedecoded",email="john@example.com",full_name="John Doe")asyncdefget_current_user(token:Annotated[str,Depends(oauth2_scheme)]):user=fake_decode_token(token)returnuser@app.get("/users/me")asyncdefread_users_me(current_user:Annotated[User,Depends(get_current_user)]):returncurrent_user🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportDepends,FastAPIfromfastapi.securityimportOAuth2PasswordBearerfrompydanticimportBaseModelapp=FastAPI()oauth2_scheme=OAuth2PasswordBearer(tokenUrl="token")classUser(BaseModel):username:stremail:str|None=Nonefull_name:str|None=Nonedisabled:bool|None=Nonedeffake_decode_token(token):returnUser(username=token+"fakedecoded",email="john@example.com",full_name="John Doe")asyncdefget_current_user(token:str=Depends(oauth2_scheme)):user=fake_decode_token(token)returnuser@app.get("/users/me")asyncdefread_users_me(current_user:User=Depends(get_current_user)):returncurrent_userCreate aget_current_user dependency¶
Let's create a dependencyget_current_user.
Remember that dependencies can have sub-dependencies?
get_current_user will have a dependency with the sameoauth2_scheme we created before.
The same as we were doing before in thepath operation directly, our new dependencyget_current_user will receive atoken as astr from the sub-dependencyoauth2_scheme:
fromtypingimportAnnotatedfromfastapiimportDepends,FastAPIfromfastapi.securityimportOAuth2PasswordBearerfrompydanticimportBaseModelapp=FastAPI()oauth2_scheme=OAuth2PasswordBearer(tokenUrl="token")classUser(BaseModel):username:stremail:str|None=Nonefull_name:str|None=Nonedisabled:bool|None=Nonedeffake_decode_token(token):returnUser(username=token+"fakedecoded",email="john@example.com",full_name="John Doe")asyncdefget_current_user(token:Annotated[str,Depends(oauth2_scheme)]):user=fake_decode_token(token)returnuser@app.get("/users/me")asyncdefread_users_me(current_user:Annotated[User,Depends(get_current_user)]):returncurrent_user🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportDepends,FastAPIfromfastapi.securityimportOAuth2PasswordBearerfrompydanticimportBaseModelapp=FastAPI()oauth2_scheme=OAuth2PasswordBearer(tokenUrl="token")classUser(BaseModel):username:stremail:str|None=Nonefull_name:str|None=Nonedisabled:bool|None=Nonedeffake_decode_token(token):returnUser(username=token+"fakedecoded",email="john@example.com",full_name="John Doe")asyncdefget_current_user(token:str=Depends(oauth2_scheme)):user=fake_decode_token(token)returnuser@app.get("/users/me")asyncdefread_users_me(current_user:User=Depends(get_current_user)):returncurrent_userGet the user¶
get_current_user will use a (fake) utility function we created, that takes a token as astr and returns our PydanticUser model:
fromtypingimportAnnotatedfromfastapiimportDepends,FastAPIfromfastapi.securityimportOAuth2PasswordBearerfrompydanticimportBaseModelapp=FastAPI()oauth2_scheme=OAuth2PasswordBearer(tokenUrl="token")classUser(BaseModel):username:stremail:str|None=Nonefull_name:str|None=Nonedisabled:bool|None=Nonedeffake_decode_token(token):returnUser(username=token+"fakedecoded",email="john@example.com",full_name="John Doe")asyncdefget_current_user(token:Annotated[str,Depends(oauth2_scheme)]):user=fake_decode_token(token)returnuser@app.get("/users/me")asyncdefread_users_me(current_user:Annotated[User,Depends(get_current_user)]):returncurrent_user🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportDepends,FastAPIfromfastapi.securityimportOAuth2PasswordBearerfrompydanticimportBaseModelapp=FastAPI()oauth2_scheme=OAuth2PasswordBearer(tokenUrl="token")classUser(BaseModel):username:stremail:str|None=Nonefull_name:str|None=Nonedisabled:bool|None=Nonedeffake_decode_token(token):returnUser(username=token+"fakedecoded",email="john@example.com",full_name="John Doe")asyncdefget_current_user(token:str=Depends(oauth2_scheme)):user=fake_decode_token(token)returnuser@app.get("/users/me")asyncdefread_users_me(current_user:User=Depends(get_current_user)):returncurrent_userInject the current user¶
So now we can use the sameDepends with ourget_current_user in thepath operation:
fromtypingimportAnnotatedfromfastapiimportDepends,FastAPIfromfastapi.securityimportOAuth2PasswordBearerfrompydanticimportBaseModelapp=FastAPI()oauth2_scheme=OAuth2PasswordBearer(tokenUrl="token")classUser(BaseModel):username:stremail:str|None=Nonefull_name:str|None=Nonedisabled:bool|None=Nonedeffake_decode_token(token):returnUser(username=token+"fakedecoded",email="john@example.com",full_name="John Doe")asyncdefget_current_user(token:Annotated[str,Depends(oauth2_scheme)]):user=fake_decode_token(token)returnuser@app.get("/users/me")asyncdefread_users_me(current_user:Annotated[User,Depends(get_current_user)]):returncurrent_user🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportDepends,FastAPIfromfastapi.securityimportOAuth2PasswordBearerfrompydanticimportBaseModelapp=FastAPI()oauth2_scheme=OAuth2PasswordBearer(tokenUrl="token")classUser(BaseModel):username:stremail:str|None=Nonefull_name:str|None=Nonedisabled:bool|None=Nonedeffake_decode_token(token):returnUser(username=token+"fakedecoded",email="john@example.com",full_name="John Doe")asyncdefget_current_user(token:str=Depends(oauth2_scheme)):user=fake_decode_token(token)returnuser@app.get("/users/me")asyncdefread_users_me(current_user:User=Depends(get_current_user)):returncurrent_userNotice that we declare the type ofcurrent_user as the Pydantic modelUser.
This will help us inside of the function with all the completion and type checks.
Tip
You might remember that request bodies are also declared with Pydantic models.
HereFastAPI won't get confused because you are usingDepends.
Check
The way this dependency system is designed allows us to have different dependencies (different "dependables") that all return aUser model.
We are not restricted to having only one dependency that can return that type of data.
Other models¶
You can now get the current user directly in thepath operation functions and deal with the security mechanisms at theDependency Injection level, usingDepends.
And you can use any model or data for the security requirements (in this case, a Pydantic modelUser).
But you are not restricted to using some specific data model, class or type.
Do you want to have anid andemail and not have anyusername in your model? Sure. You can use these same tools.
Do you want to just have astr? Or just adict? Or a database class model instance directly? It all works the same way.
You actually don't have users that log in to your application but robots, bots, or other systems, that have just an access token? Again, it all works the same.
Just use any kind of model, any kind of class, any kind of database that you need for your application.FastAPI has you covered with the dependency injection system.
Code size¶
This example might seem verbose. Keep in mind that we are mixing security, data models, utility functions andpath operations in the same file.
But here's the key point.
The security and dependency injection stuff is written once.
And you can make it as complex as you want. And still, have it written only once, in a single place. With all the flexibility.
But you can have thousands of endpoints (path operations) using the same security system.
And all of them (or any portion of them that you want) can take advantage of re-using these dependencies or any other dependencies you create.
And all these thousands ofpath operations can be as small as 3 lines:
fromtypingimportAnnotatedfromfastapiimportDepends,FastAPIfromfastapi.securityimportOAuth2PasswordBearerfrompydanticimportBaseModelapp=FastAPI()oauth2_scheme=OAuth2PasswordBearer(tokenUrl="token")classUser(BaseModel):username:stremail:str|None=Nonefull_name:str|None=Nonedisabled:bool|None=Nonedeffake_decode_token(token):returnUser(username=token+"fakedecoded",email="john@example.com",full_name="John Doe")asyncdefget_current_user(token:Annotated[str,Depends(oauth2_scheme)]):user=fake_decode_token(token)returnuser@app.get("/users/me")asyncdefread_users_me(current_user:Annotated[User,Depends(get_current_user)]):returncurrent_user🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportDepends,FastAPIfromfastapi.securityimportOAuth2PasswordBearerfrompydanticimportBaseModelapp=FastAPI()oauth2_scheme=OAuth2PasswordBearer(tokenUrl="token")classUser(BaseModel):username:stremail:str|None=Nonefull_name:str|None=Nonedisabled:bool|None=Nonedeffake_decode_token(token):returnUser(username=token+"fakedecoded",email="john@example.com",full_name="John Doe")asyncdefget_current_user(token:str=Depends(oauth2_scheme)):user=fake_decode_token(token)returnuser@app.get("/users/me")asyncdefread_users_me(current_user:User=Depends(get_current_user)):returncurrent_userRecap¶
You can now get the current user directly in yourpath operation function.
We are already halfway there.
We just need to add apath operation for the user/client to actually send theusername andpassword.
That comes next.







