Ojasa Mirai

Ojasa Mirai

FastAPI

Loading...

Learning Level

🟢 Beginner🔵 Advanced
🚀 Authentication Basics📚 API Keys📚 Basic Auth📚 JWT Tokens📚 OAuth2📚 Scopes📚 Securing Endpoints📚 Token Refresh📚 Role-Based Access
Fastapi/Authentication/Scopes

Scopes

Learn essential concepts of scopes in FastAPI.

What You'll Learn

This section covers OAuth2 scopes, including:

  • Understanding permission scopes
  • Defining custom scopes
  • Validating scope requirements
  • Best practices for scope design

Core Concepts

OAuth2 scopes are permissions that allow fine-grained access control. They define what an authenticated user or application can do.

Common Scopes

# Read scope - allowed to view data
scopes = {
    "read": "Read data",
    "write": "Write data",
    "delete": "Delete data",
    "admin": "Admin access"
}

# Fine-grained scopes
scopes = {
    "users:read": "View user information",
    "users:write": "Create/update users",
    "users:delete": "Delete users",
    "orders:read": "View orders",
    "orders:write": "Create/update orders",
    "payments:process": "Process payments"
}

Implementing Scopes

from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm, HTTPAuthorizationCredentials
from typing import List

app = FastAPI()

# Define available scopes
scopes = {
    "read": "Read access",
    "write": "Write access",
    "admin": "Admin access"
}

oauth2_scheme = OAuth2PasswordBearer(
    tokenUrl="token",
    scopes=scopes
)

class TokenData(BaseModel):
    username: str = None
    scopes: List[str] = []

async def get_current_user(token: str = Depends(oauth2_scheme)):
    payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
    username: str = payload.get("sub")
    token_scopes = payload.get("scopes", [])

    if username is None:
        raise HTTPException(status_code=401, detail="Invalid token")

    return TokenData(scopes=token_scopes, username=username)

@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    user = fake_users_db.get(form_data.username)
    if not user:
        raise HTTPException(status_code=401, detail="Invalid credentials")

    # Grant scopes based on user role
    user_scopes = ["read"]
    if user.get("is_admin"):
        user_scopes.extend(["write", "admin"])

    access_token = create_access_token(
        data={"sub": user["username"], "scopes": user_scopes}
    )
    return {"access_token": access_token, "token_type": "bearer"}

@app.get("/items/", scopes=["read"])
async def read_items(current_user: TokenData = Depends(get_current_user)):
    if "read" not in current_user.scopes:
        raise HTTPException(status_code=403, detail="Insufficient permissions")
    return [{"item_id": 1, "name": "Item 1"}]

@app.post("/items/", scopes=["write"])
async def create_item(item: Item, current_user: TokenData = Depends(get_current_user)):
    if "write" not in current_user.scopes:
        raise HTTPException(status_code=403, detail="Permission denied")
    return {"item_id": 1, **item.dict()}

Real-World Usage

Scopes are essential for:

  • **Least privilege access**: Grant minimum required permissions
  • **Third-party integrations**: Control what apps can access
  • **Multi-tenant applications**: Tenant-specific permissions
  • **Fine-grained authorization**: Granular permission control

🔑 Key Takeaways

  • ✅ Understand the purpose of scopes
  • ✅ Know when to apply this pattern
  • ✅ Follow best practices consistently
  • ✅ Test thoroughly in production scenarios

Next step: Explore the advanced section for production patterns and optimization techniques.


Resources

Python Docs

Ojasa Mirai

Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.

Learn Deep • Build Real • Verify Skills • Launch Forward

Courses

PythonFastapiReactJSCloud

© 2026 Ojasa Mirai. All rights reserved.

TwitterGitHubLinkedIn