Authentication
Overview
Section titled “Overview”ARROW uses Zitadel as its centralized identity and access management (IAM) platform. Zitadel provides single sign-on (SSO), user lifecycle management, and multi-tenancy support through organization mapping.
Integration Architecture
Section titled “Integration Architecture”ARROW integrates with Zitadel using a service account for automated user management:
graph TD
A[ARROW Frontend] -->|SSO Login| B[Zitadel]
C[ARROW Backend] -->|Service Account| B
B -->|OAuth Tokens| A
C -->|User Management| B
D[Organizations] -->|Mapped to| E[Zitadel Orgs]
C -->|Project Access| F[Arrow Project]
C -->|VPN Access| G[NetBird Project]
Key Integration Points
Section titled “Key Integration Points”| Component | Integration |
|---|---|
| User Authentication | OAuth 2.0 / OIDC SSO via Zitadel |
| User Provisioning | Automated user creation in Zitadel |
| Organization Mapping | ARROW orgs map to Zitadel orgs |
| Project Access | Users added to Arrow and NetBird projects |
| Status Sync | Bidirectional active/inactive sync |
Configuration
Section titled “Configuration”System Integration Record
Section titled “System Integration Record”Zitadel integration is configured through the system_integrations collection with type: "zitadel":
{ "type": "zitadel", "domain": "your-instance.zitadel.cloud", "client_id": "application-client-id", "client_secret": "application-client-secret", "project_id": "arrow-project-id", "service_account_json": "{...}"}Configuration Fields
Section titled “Configuration Fields”| Field | Description |
|---|---|
domain | Zitadel instance domain (e.g., your-instance.zitadel.cloud) |
client_id | OAuth client ID for the ARROW application |
client_secret | OAuth client secret |
project_id | Zitadel project ID for ARROW application |
service_account_json | Service account credentials for API access |
Service Account JSON Format
Section titled “Service Account JSON Format”The service account JSON follows Zitadel’s JWT Profile format:
{ "type": "serviceaccount", "keyId": "key-id-from-zitadel", "key": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n", "userId": "service-account-user-id"}| Field | Description |
|---|---|
type | Must be serviceaccount |
keyId | Key identifier from Zitadel |
key | RSA private key in PEM format |
userId | Service account user ID |
Obtaining Service Account Credentials
Section titled “Obtaining Service Account Credentials”- Navigate to Zitadel Console > Service Users
- Create a new service user with Manager role
- Generate a new key (JWT Profile)
- Download the JSON key file
- Store the JSON in ARROW’s
service_account_jsonfield
User Lifecycle Management
Section titled “User Lifecycle Management”ARROW automatically manages users in Zitadel when users are created, updated, or deleted.
User Creation Flow
Section titled “User Creation Flow”When a user is added to ARROW, the handleUserCreationWithZitadel function (lines 351-756 in backend/hooks/user_permissions.go) orchestrates the following:
sequenceDiagram
participant Admin
participant Arrow
participant Zitadel
participant NetBird
Admin->>Arrow: Create User
Arrow->>Zitadel: Get Service Account Token
Zitadel-->>Arrow: Access Token
Arrow->>Zitadel: Create User in Org Context
Zitadel-->>Arrow: User Created (userId)
Arrow->>Zitadel: Add to Arrow Project
Arrow->>Zitadel: Add to NetBird Project
Arrow->>Arrow: Sync User Permissions
Arrow->>NetBird: Create VPN User
Arrow-->>Admin: User Created Successfully
Creation Steps
Section titled “Creation Steps”- Acquire service account token - JWT assertion grant to Zitadel
- Switch organization context - Use
zitadel_org_idfrom ARROW organization - Create user in Zitadel - With email and profile information
- Assign project memberships - Add to Arrow project and NetBird project
- Trigger email verification - User receives verification email
- Sync permissions - Aggregate role permissions to user record
- Create VPN user - Provision NetBird user account
Organization Context Switching
Section titled “Organization Context Switching”ARROW organizations map to Zitadel organizations via the zitadel_org_id field:
| ARROW Field | Zitadel Mapping |
|---|---|
organizations.zitadel_org_id | Zitadel organization ID |
organizations.netbird_project_id | NetBird project for VPN access |
When creating users, ARROW switches to the appropriate Zitadel organization context to ensure proper multi-tenancy isolation.
User Status Synchronization
Section titled “User Status Synchronization”ARROW maintains bidirectional sync of user active/inactive status with Zitadel.
Background Sync Job
Section titled “Background Sync Job”A cron job runs every 30 minutes (configured in backend/api/zitadel/handlers.go, lines 20-36) to synchronize status:
scheduler.Every(30).Minutes().Do(func() { SyncUserStatusFromZitadel(app)})Sync Behavior
Section titled “Sync Behavior”| Zitadel Status | ARROW Action |
|---|---|
| Active | Ensure ARROW user is active |
| Inactive | Mark ARROW user as inactive |
| Deleted | Handle as inactive |
Manual Sync Endpoint
Section titled “Manual Sync Endpoint”Administrators can trigger immediate status sync:
POST /api/zitadel/users/sync-statusUser Activation/Deactivation
Section titled “User Activation/Deactivation”ARROW provides endpoints to manage user status:
| Endpoint | Action |
|---|---|
POST /api/zitadel/users/{id}/activate | Activate user in Zitadel |
POST /api/zitadel/users/{id}/deactivate | Deactivate user in Zitadel |
Organization Mapping
Section titled “Organization Mapping”ARROW supports multi-tenancy by mapping organizations to Zitadel organizations.
Mapping Configuration
Section titled “Mapping Configuration”Each ARROW organization can be linked to a Zitadel organization:
| Field | Description |
|---|---|
zitadel_org_id | Zitadel organization identifier |
netbird_project_id | NetBird project for VPN access |
Organization Mapping Endpoints
Section titled “Organization Mapping Endpoints”| Endpoint | Description |
|---|---|
GET /api/zitadel/organizations | List available Zitadel organizations |
GET /api/zitadel/org-mapping | Get current ARROW-Zitadel mappings |
POST /api/zitadel/org-mapping | Update organization mapping |
Multi-Tenancy Benefits
Section titled “Multi-Tenancy Benefits”Organization mapping provides:
- Isolated user pools - Users belong to specific Zitadel organizations
- Separate billing - Organization-level Zitadel subscriptions
- Custom branding - Per-organization login pages
- Independent admin - Organization admins manage their own users
Project Management
Section titled “Project Management”ARROW manages access to multiple Zitadel projects for different functionality.
Arrow Project
Section titled “Arrow Project”The main ARROW application project:
| Purpose | Provides |
|---|---|
| Application access | Login to ARROW portal |
| Role-based access | Admin, Manager, User roles |
| API access | Authenticated API calls |
NetBird Project
Section titled “NetBird Project”Per-organization VPN access project:
| Purpose | Provides |
|---|---|
| VPN authentication | NetBird VPN login |
| Device access | Connect to ARROW-managed devices |
| Access policies | Consultant-device access control |
Project Membership Endpoints
Section titled “Project Membership Endpoints”| Endpoint | Description |
|---|---|
POST /api/zitadel/projects/{id}/members | Add user to project |
DELETE /api/zitadel/projects/{id}/members/{userId} | Remove user from project |
Arrow Manager Project
Section titled “Arrow Manager Project”Separate application for management functions:
| Feature | Description |
|---|---|
| Site administration | Cross-organization management |
| System configuration | Global settings |
| Integration management | Zitadel/NetBird configuration |
Token Management
Section titled “Token Management”ARROW uses OAuth 2.0 tokens for API authentication with Zitadel.
Token Acquisition Flow
Section titled “Token Acquisition Flow”Service account tokens are acquired using JWT Profile assertion:
sequenceDiagram
participant Arrow
participant Zitadel
Arrow->>Arrow: Create JWT Assertion
Arrow->>Zitadel: POST /oauth/v2/token
Note over Arrow,Zitadel: grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
Zitadel-->>Arrow: Access Token + Expiry
Arrow->>Arrow: Cache Token
JWT Assertion
Section titled “JWT Assertion”The JWT assertion includes:
| Claim | Value |
|---|---|
iss | Service account user ID |
sub | Service account user ID |
aud | Zitadel issuer URL |
iat | Current timestamp |
exp | Expiration (typically 1 hour) |
Token Introspection
Section titled “Token Introspection”ARROW validates tokens through Zitadel’s introspection endpoint:
POST /oauth/v2/introspectRate Limiting
Section titled “Rate Limiting”Token endpoints are rate-limited to prevent abuse:
| Limit | Value |
|---|---|
| Requests per second | 3 |
| Burst | 5 |
Token Caching Strategy
Section titled “Token Caching Strategy”ARROW caches access tokens to minimize API calls:
- Store token with expiry - Cache token until near expiration
- Refresh proactively - Request new token before expiry
- Handle failures gracefully - Retry with exponential backoff
Security Considerations
Section titled “Security Considerations”Service Account Security
Section titled “Service Account Security”- Store service account JSON securely (environment variable or secrets manager)
- Rotate keys periodically
- Use minimum required permissions
- Monitor service account activity
Token Security
Section titled “Token Security”- Never log access tokens
- Use HTTPS for all token exchanges
- Validate token signatures
- Check token expiration
Multi-Tenancy Isolation
Section titled “Multi-Tenancy Isolation”- Verify organization context for all operations
- Prevent cross-organization data access
- Audit organization switching events
Implementation Reference
Section titled “Implementation Reference”Key Source Files
Section titled “Key Source Files”| File | Purpose |
|---|---|
backend/hooks/user_permissions.go | User creation with Zitadel (lines 351-756) |
backend/api/zitadel/handlers.go | Status sync and API endpoints (lines 20-36) |
backend/api/zitadel/client.go | Zitadel API client |
Related Collections
Section titled “Related Collections”| Collection | Relevant Fields |
|---|---|
system_integrations | type, domain, client_id, project_id, service_account_json |
organizations | zitadel_org_id, netbird_project_id |
users | zitadel_user_id, email, active |
Related Documentation
Section titled “Related Documentation”- User Management - Role and permission management
- Network Access Control - VPN access integration
- Admin Features - Admin impersonation