Authorization and authentication are 2 different topics. Authentication is related to login and authorization is related to permission. Even if a person is logged in, they may not have the necessary permissions to perform certain actions.
Consider our blog application - anyone who knows our endpoints could make a DELETE request and remove someone else's blog post! Even worse, a malicious person could send delete requests for every single blog post in our system! ðŸ˜
So we need to verify if the person making the request has the necessary permissions. In our case, we want only the blog authors to be able to modify or delete their own posts.
Protecting the Route
Now let's attach this dependency to our delete route so only the blog authors can delete their posts:
@router.delete("/blogs/{slug}", status_code=status.HTTP_200_OK)
def delete_blog(slug: str, current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
if delete_blog_by_slug(slug, current_user, db):
return {"detail": "Blog deleted successfully"}
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Blog not found")
The magic happens with current_user: User = Depends(get_current_user)
. This ensures:
- The user must be authenticated (have a valid token)
- We get access to the current user's information
- We can check if they own the resource they're trying to modify
Implementing Resource-Based Authorization
Now we can compare the user_id
of the current user with the owner of the blog post to allow or deny the operation. Let's integrate permissions with our delete endpoint:
def delete_blog_by_slug(slug: str, current_user: User, db: Session) -> Optional[bool]:
statement = select(Blog).where(Blog.slug == slug)
result = db.exec(statement)
db_blog = result.first()
if not db_blog:
return None
if db_blog.user_id != current_user.id:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="You are not allowed to delete this blog")
db.delete(db_blog)
db.commit()
return True
The key authorization check happens here:
if db_blog.user_id != current_user.id:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="You are not allowed to delete this blog")
Only users who created the blog post can delete it. If someone tries to delete a blog they don't own, they get a proper 403 Forbidden response.