Phase 2b: Keycloak Auth + Tenant Scoping
Goal: Add Keycloak OIDC token validation and tenant-scoped access control to the FastAPI service — stakeholders see only their prefix, admins see everything.
Owner: Dev agent
Repo:
forgejo_admin/minio-apiDepends on:
phase-minio-mobile-2a-fastapi-routes (API routes must exist first)Scope
- Keycloak OIDC token validation middleware — every request must have valid Bearer token
- Decode JWT, validate signature against Keycloak's JWKS endpoint
- Extract role and group claims from token
- Tenant scoping: Keycloak group claims map to MinIO bucket prefixes (e.g., group
westside→ prefixassets/westside/) - Admin role bypasses scoping — sees all buckets and prefixes
- Stakeholder role: list/get/upload scoped to their prefix, no delete, no other buckets
- 401 on missing/invalid token, 403 on out-of-scope access
- Tests: mock Keycloak tokens for unit tests, real Keycloak for integration tests
Auth Model
| Role | Buckets | Prefix | Operations |
|---|---|---|---|
| admin | All | All | Full CRUD |
| stakeholder | assets only | Scoped to group claim (e.g., <code>westside/</code>) | List, Get, Upload — no Delete |
Deliverables
- PR #5 merged (squash) — 2026-03-22
auth.py— JWKS caching + JWT validation via PyJWT,TokenUserdataclasspermissions.py— tenant scoping: group claim → prefix, admin bypass, stakeholder restrictions- Auth injected on all 15 endpoints via FastAPI
Depends(get_current_user) - 401 on missing/invalid/expired token, 403 on out-of-scope access
AUTH_DISABLED=truefor local dev — existing integration tests unaffected- 63 new tests (15 auth unit, 28 permissions unit, 20 middleware HTTP-level) — all passing
Related
phase-minio-mobile-2-api-auth— parent phasephase-minio-mobile-2a-fastapi-routes— prerequisite (API routes)phase-minio-mobile-2c-k8s-deploy— next subphase (deploy)