Add Keycloak realm, JWT auth, and role-based access control #4
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Lineage
plan-mcd-tracker→ Phase 4: Keycloak Realm + AuthRepo
forgejo_admin/mcd-tracker-apiUser Story
As a user
I want to authenticate via Keycloak to access my coupon data
So that my data is private and only I can manage my locations and codes.
Architecture
arch-dataflow-mcd-tracker#auth-flow-keycloak-oidc— implements the OIDC auth flow. Two clients: confidential (SvelteKit) + public/PKCE (iOS).arch-domain-mcd-tracker— User entity useskeycloak_subfrom JWT, no local user table.Context
Phases 1-3 complete. FastAPI app is live with SQLAlchemy models and Postgres. Keycloak is already running at
https://keycloak.tail5b443a.ts.netin thekeycloaknamespace. Admin credentials are in~/secrets/pal-e-services/secrets.env(KEYCLOAK_ADMIN_PASSWORD). The existingwestside-basketballrealm is the reference for how realms are configured.Follow the basketball-api auth pattern at
~/basketball-api/src/basketball_api/auth.py.File Targets
Files to create:
src/mcd_tracker_api/auth.py— JWKS fetch + cache, JWT decode (RS256), User dataclass (sub, email, username, roles),get_current_user()dependency,require_role()dependency factoryFiles to modify:
src/mcd_tracker_api/config.py— addkeycloak_realm_url: strfield (default to placeholder, overridden byMCD_TRACKER_KEYCLOAK_REALM_URLenv var)pyproject.toml— add dependencies:python-jose[cryptography],httpxtests/test_auth.py— auth tests (mock JWT for CI — Keycloak isn't available in CI)Keycloak setup (via admin API, not manual UI):
mcd-trackerviaPOST /admin/realmsusing admin credentials from~/secrets/pal-e-services/secrets.envhttps://keycloak.tail5b443a.ts.netuser,adminmcd-tracker-app: confidential, redirect URIshttps://mcd-tracker-app.tail5b443a.ts.net/*mcd-tracker-ios: public, PKCE enabled, redirect URIsmcd-tracker://callbacktestuserwith roleusertestadminwith roleadminKustomize update:
MCD_TRACKER_KEYCLOAK_REALM_URLenv var to~/pal-e-deployments/overlays/mcd-tracker/prod/deployment-patch.yamlhttps://keycloak.tail5b443a.ts.net/realms/mcd-trackerFiles NOT to touch:
src/mcd_tracker_api/models.py— no changes neededsrc/mcd_tracker_api/routes/health.py— health doesn't need authAcceptance Criteria
mcd-trackerexists with rolesuserandadminmcd-tracker-app(confidential) andmcd-tracker-ios(public + PKCE)auth.pyvalidates JWT from Keycloak JWKS endpointget_current_user()extracts sub, email, username, roles from JWTrequire_role("admin")returns 403 for non-admin usersMCD_TRACKER_KEYCLOAK_REALM_URLwired in deployment patchTest Expectations
test_auth.py— mock JWT tests: valid → extracts user, missing → 401, bad sig → 401, wrong role → 403pytest tests/ -vConstraints
auth.pypattern closely — proven in productionpython-jose[cryptography]for JWT (same as basketball-api)httpxfor JWKS fetch (same as basketball-api)http://keycloak.keycloak.svc.cluster.local:80/realms/mcd-trackerBUT use external URLhttps://keycloak.tail5b443a.ts.net/realms/mcd-trackerin deployment patch (issuer in JWT matches external URL). See basketball-api lesson: issuer mismatch between internal/external URLs.Depends(get_current_user).Checklist
Closes #3Related
project-mcd-tracker— project pagephase-mcd-tracker-4-keycloak-auth— phase notearch-dataflow-mcd-tracker— auth flow diagramplan-mcd-tracker— parent plan