Auth And Local Mode
SPAPS auth is easiest to reason about as two stacked checks. First, the request identifies the calling application with an API key. Second, the request identifies the user with a JWT, or in local mode with a selected local persona. Most confusing auth bugs come from mixing those two identities.
Mental Model
When To Use Which Layer
| Need | Use |
|---|---|
| Identify the client app | get_application |
| Require a signed-in user | get_current_user |
| Allow signed-in or anonymous behavior | get_optional_user |
| Require admin access | require_admin_user or require_roles |
| Develop without real auth | DEVELOPMENT_ENVIRONMENT=local and local-mode helpers |
Local Vs Production Checklist
| Mode | First command | Expected signal | Stop if |
|---|---|---|---|
| Local persona mode | curl -fsS http://localhost:3301/health/local-mode | Local mode is named, with the local test app hints | SPAPS_LOCAL_MODE and DEVELOPMENT_ENVIRONMENT disagree |
| CLI local runtime | npx spaps quickstart --json | Output names local-mode or provisioning hints | The quickstart cannot identify the runtime mode |
| Production auth | curl -fsS http://localhost:3301/health/ready | Readiness passes without local bypass hints | Local bypass is enabled in a production-shaped environment |
| Browser publishable key | Use the frontend origin that owns the app | The key is constrained by route and origin | A publishable key works from an unlisted origin |
Example Route
from typing import Annotated
from fastapi import Depends, APIRouter
from spaps_server_quickstart.middleware.spaps_deps import get_current_user
router = APIRouter()
@router.get("/me")
async def me(user: Annotated[object, Depends(get_current_user)]) -> dict[str, str]:
return {"user_id": str(user.id)}Common Mistakes
A valid JWT is not enough if it was minted for a different application. get_current_user
enforces token application matching against the API-key application.
- Treating a publishable key as a server key. Publishable keys are origin and endpoint constrained.
- Forgetting that local mode still resolves explicit real API keys.
- Enabling local auth bypass in an environment that startup validation treats as production.