Zitadel RBAC Overview - Liturgical-Calendar/LiturgicalCalendarAPI GitHub Wiki
The LiturgicalCalendar API uses Zitadel as its identity provider for
OIDC-based authentication, role-based access control (RBAC), and user management, complemented by
OpenFGA for fine-grained per-resource permissions (see
OpenFGA Fine-Grained Authorization). This replaces the earlier self-hosted JWT-only
authentication (Phase 0) with an enterprise-grade identity platform.
Architecture
βββββββββββββββββββ
β PostgreSQL β
β Port: 5432 β
βββββββββ¬ββββββββββ
β
βββββββββββββββΌββββββββββββββ
β β β
βΌ βΌ βΌ
ββββββββββββββ βββββββββββββ ββββββββββββ
β Zitadel β β Login V2 β β litcal β
β database β β (shares β β database β
β (managed) β β Zitadel β β (RBAC) β
ββββββββββββββ β network) β ββββββββββββ
βββββββββββββ
βββββββββββββββ€
β β
βΌ βΌ
ββββββββββββββ βββββββββββββ
β Zitadel β β Login V2 β
β Port:8080 β β Port:8081β
β OIDC/API β β Auth UI β
ββββββββ¬ββββββ βββββββββββββ
β
βΌ
βββββββββββββββββββββ
β LiturgicalCalendarβ
β API β
β Port: 8000 β
βββββββββββββββββββββ
Components
| Service |
Port |
Purpose |
| Zitadel |
8080 |
OIDC/OAuth2 identity provider, Console, Management API |
| Login V2 |
8081 |
Next.js authentication UI with passkeys and registration |
| PostgreSQL |
5432 |
Shared database (Zitadel-managed + application RBAC) |
| API |
8000 |
LiturgicalCalendar REST API |
Middleware Pipeline
Protected routes pass through the following middleware chain:
- ErrorHandlingMiddleware - Catches exceptions and formats error responses
- LoggingMiddleware - Logs requests and responses
- HttpsEnforcementMiddleware - Requires HTTPS in production (auth/admin routes)
- OidcAvailabilityMiddleware - Returns 503 if Zitadel is not configured
- OidcAuthMiddleware - Validates OIDC tokens, extracts user info and roles
- AuthorizationMiddleware - Checks required Zitadel roles
- OpenFgaAuthorizationMiddleware - Fine-grained per-resource permission checks via OpenFGA
(see OpenFGA Fine-Grained Authorization)
Role-based authorization (Zitadel) and resource-level authorization (OpenFGA) are two distinct
layers: the role grants access to a class of endpoints, while OpenFGA determines which specific
calendars or tests the user may act on. The rationale behind this design is described in the
Calendar Governance Model.
Roles
Four roles are defined in the Zitadel project:
| Role |
Purpose |
admin |
System administrator; bypasses all permission checks |
developer |
Register applications and generate API keys |
calendar_editor |
Contribute calendar data (with per-calendar permissions) |
test_editor |
Create and modify test definitions |
Protected Routes
Authentication Endpoints (OIDC required)
| Method |
Route |
Purpose |
| POST |
/auth/access-requests |
Submit an access request (role + permissions) |
| GET |
/auth/access-requests |
View own access requests |
| GET |
/auth/access-requests/status |
Check access request status |
| GET |
/auth/admin-scopes |
Caller's admin status and resource scopes |
| GET |
/auth/test-scopes |
Caller's test editor/admin scopes |
| POST |
/auth/email-verification/resend |
Resend verification email |
Admin Endpoints (OIDC + admin role)
| Method |
Route |
Purpose |
| GET |
/admin/access-requests |
List access requests |
| POST |
/admin/access-requests/{id}/approve |
Approve request (grants role + permissions) |
| POST |
/admin/access-requests/{id}/reject |
Reject access request |
| POST |
/admin/access-requests/{id}/revoke |
Revoke granted access (role + permissions) |
| GET |
/admin/permissions |
List OpenFGA permission tuples |
| POST |
/admin/permissions |
Grant a permission |
| DELETE |
/admin/permissions |
Revoke a permission |
| GET |
/admin/permissions/check |
Check a specific permission |
| GET |
/admin/notifications |
Pending item counts |
| GET |
/admin/users |
List users with roles |
| DELETE |
/admin/users/{userId}/roles/{role} |
Revoke a user's role |
| GET |
/admin/applications |
List all applications |
| POST |
/admin/applications/{uuid}/approve |
Approve application |
| POST |
/admin/applications/{uuid}/reject |
Reject application |
| POST |
/admin/applications/{uuid}/revoke |
Revoke approved application |
Developer Endpoints (OIDC + developer role)
| Method |
Route |
Purpose |
| GET |
/applications |
List own applications |
| POST |
/applications |
Register new application |
| GET |
/applications/{uuid} |
Application details |
| PATCH |
/applications/{uuid} |
Update application |
| DELETE |
/applications/{uuid} |
Delete application |
| POST |
/applications/{uuid}/resubmit |
Resubmit rejected app |
| GET |
/applications/{uuid}/keys |
List API keys |
| POST |
/applications/{uuid}/keys |
Generate API key |
| DELETE |
/applications/{uuid}/keys/{keyId} |
Revoke API key |
| POST |
/applications/{uuid}/keys/{keyId}/rotate |
Rotate API key |
Calendar Data Endpoints (OIDC + calendar_editor + per-calendar permission)
| Method |
Route |
Purpose |
| PUT |
/data/{category}/{calendar} |
Create calendar definition |
| PATCH |
/data/{category}/{calendar} |
Update calendar definition |
| DELETE |
/data/{category}/{calendar} |
Delete calendar definition |
Test Data Endpoints (OIDC + test_editor role)
| Method |
Route |
Purpose |
| PUT |
/tests |
Create test definition |
| PATCH |
/tests |
Update test definition |
| DELETE |
/tests |
Delete test definition |
Database Schema
The application database (litcal) stores RBAC data that complements Zitadel's identity management.
Fine-grained per-calendar permissions themselves live in OpenFGA as relationship tuples
(see OpenFGA Fine-Grained Authorization); the application database stores the request workflow
and the tuple outbox:
| Table |
Purpose |
access_requests |
Unified role + permission request workflow |
openfga_outbox |
Transactional outbox for OpenFGA tuple writes/deletes |
applications |
Registered developer applications |
api_keys |
API keys with rate limiting, scope, and expiration |
user_notification_state |
Per-user notification read state |
audit_log |
Security and compliance audit trail |
Tables use UUID primary keys via PostgreSQL's pgcrypto extension.
Key Source Files
| File |
Purpose |
src/Services/ZitadelService.php |
Zitadel Management API client |
src/Http/Middleware/OidcAuthMiddleware.php |
OIDC token validation and role extraction |
src/Http/Middleware/OidcAvailabilityMiddleware.php |
Checks if Zitadel is configured |
src/Http/Middleware/AuthorizationMiddleware.php |
Zitadel role enforcement |
src/Http/Middleware/OpenFgaAuthorizationMiddleware.php |
Per-resource permission checks (OpenFGA) |
src/Services/OpenFgaClient.php |
OpenFGA API client |
src/Http/Middleware/ApiKeyMiddleware.php |
API key extraction and validation |
src/Repositories/ |
Database repositories for RBAC tables |
src/Services/RateLimiter.php |
IP-based rate limiting (login endpoint) |
Implementation Status
See the Implementation Status page for details on what is complete and what remains to be done.
Authentication & RBAC: [Home]] ](/Liturgical-Calendar/LiturgicalCalendarAPI/wiki/[[Calendar-Governance-Model) β