DEV Community

Fiyinfoluwa Ojo
Fiyinfoluwa Ojo

Posted on

Permissions & Ownership: Preventing Unauthorized Access in FastAPI

The Problem

Without ownership checks, any logged in user can
delete or modify anyone else's data.

User A creates an item. User B deletes it.
That's a serious security flaw.

The Solution : user_id on Every Item

class Item(Base):
    __tablename__ = "items"
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    price = Column(Numeric(10, 2), nullable=False)
    user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
Enter fullscreen mode Exit fullscreen mode

When an item is created, the logged in user's ID
is automatically saved as the owner.

Ownership Check on Delete & Update

@app.delete("/items/{item_id}")
def delete_item(item_id: int, current_user: dict = Depends(verify_token)):
    item = db.query(Item).filter(Item.id == item_id).first()
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")
    if item.user_id != current_user["user_id"]:
        raise HTTPException(status_code=403, detail="Forbidden — you don't own this item")
    db.delete(item)
    db.commit()
Enter fullscreen mode Exit fullscreen mode

Two checks:

  1. Does the item exist? If not → 404
  2. Does the item belong to you? If not → 403

The Difference Between 401 and 403

  • 401 Unauthorized → you're not logged in
  • 403 Forbidden → you're logged in but not allowed

These are NOT the same thing and should never
be used interchangeably.

Postman Tests

User B tries to delete User A's item : 403

403 error

User A deletes their own item : success

Success

Lessons Learned

Ownership checks are non negotiable in any
multi user system. Always verify that the
logged in user owns the resource before
allowing modifications or deletions.

Day 17 done. 13 more to go.

GDGoCBowen30dayChallenge

Top comments (0)