9.9 KiB
Built-in OAuth/OIDC Server Implementation Summary
Overview
Implemented Phase 1 (Backend Core) and Phase 2 (Caddy Integration) for Issue #14: Built-in OAuth/OIDC Server (SSO - Plus Feature).
Phase 1: Backend Core
1. Docker Configuration
File: /projects/cpmp/Dockerfile
- Updated
xcaddy buildcommand to includegithub.com/greenpau/caddy-securityplugin - This enables caddy-security functionality in the Caddy binary
2. Database Models
Created three new models in /projects/cpmp/backend/internal/models/:
auth_user.go - AuthUser Model
- Local user accounts for SSO
- Fields: UUID, Username, Email, Name, PasswordHash, Enabled, Roles, MFAEnabled, MFASecret, LastLoginAt
- Methods:
SetPassword()- Bcrypt password hashingCheckPassword()- Password verificationHasRole()- Role checking
auth_provider.go - AuthProvider Model
- External OAuth/OIDC provider configurations
- Fields: UUID, Name, Type (google, github, oidc, saml), ClientID, ClientSecret, IssuerURL, AuthURL, TokenURL, UserInfoURL, Scopes, RoleMapping, IconURL, DisplayName
- Supports generic OIDC providers and specific ones (Google, GitHub, etc.)
auth_policy.go - AuthPolicy Model
- Access control policies for proxy hosts
- Fields: UUID, Name, Description, AllowedRoles, AllowedUsers, AllowedDomains, RequireMFA, SessionTimeout
- Method:
IsPublic()- checks if policy allows unrestricted access
3. ProxyHost Model Enhancement
File: /projects/cpmp/backend/internal/models/proxy_host.go
- Added
AuthPolicyIDfield (nullable foreign key) - Added
AuthPolicyrelationship - Enables linking proxy hosts to authentication policies
4. API Handlers
File: /projects/cpmp/backend/internal/api/handlers/auth_handlers.go
Created three handler structs with full CRUD operations:
AuthUserHandler
List()- Get all auth usersGet()- Get user by UUIDCreate()- Create new user (with password validation)Update()- Update user (supports partial updates)Delete()- Delete user (prevents deletion of last admin)Stats()- Get user statistics (total, enabled, with MFA)
AuthProviderHandler
List()- Get all OAuth providersGet()- Get provider by UUIDCreate()- Register new OAuth providerUpdate()- Update provider configurationDelete()- Remove OAuth provider
AuthPolicyHandler
List()- Get all access policiesGet()- Get policy by UUIDCreate()- Create new policyUpdate()- Update policy rulesDelete()- Remove policy (prevents deletion if in use)
5. API Routes
File: /projects/cpmp/backend/internal/api/routes/routes.go
Registered new endpoints under /api/v1/security/:
GET /security/users
GET /security/users/stats
GET /security/users/:uuid
POST /security/users
PUT /security/users/:uuid
DELETE /security/users/:uuid
GET /security/providers
GET /security/providers/:uuid
POST /security/providers
PUT /security/providers/:uuid
DELETE /security/providers/:uuid
GET /security/policies
GET /security/policies/:uuid
POST /security/policies
PUT /security/policies/:uuid
DELETE /security/policies/:uuid
Added new models to AutoMigrate:
models.AuthUsermodels.AuthProvidermodels.AuthPolicy
Phase 2: Caddy Integration
1. Caddy Configuration Types
File: /projects/cpmp/backend/internal/caddy/types.go
Added new types for caddy-security integration:
SecurityApp
- Top-level security app configuration
- Contains Authentication and Authorization configs
AuthenticationConfig & AuthPortal
- Portal configuration for authentication
- Supports multiple backends (local, OAuth, SAML)
- Cookie and token management settings
AuthBackend
- Configuration for individual auth backends
- Supports local users and OAuth providers
AuthorizationConfig & AuthzPolicy
- Policy definitions for access control
- Role-based and user-based restrictions
- MFA requirements
New Handler Functions
SecurityAuthHandler()- Authentication middlewareSecurityAuthzHandler()- Authorization middleware
2. Config Generation
File: /projects/cpmp/backend/internal/caddy/config.go
Updated GenerateConfig() Signature
Added new parameters:
authUsers []models.AuthUserauthProviders []models.AuthProviderauthPolicies []models.AuthPolicy
New Function: generateSecurityApp()
Generates the caddy-security app configuration:
- Creates authentication portal "cpmp_portal"
- Configures local backend with user credentials
- Adds OAuth providers dynamically
- Generates authorization policies from database
New Function: convertAuthUsersToConfig()
Converts AuthUser models to caddy-security user config format:
- Maps username, email, password hash
- Converts comma-separated roles to arrays
- Filters disabled users
Route Handler Integration
When generating routes for proxy hosts:
- Checks if host has an
AuthPolicyID - Injects
SecurityAuthHandler("cpmp_portal")before other handlers - Injects
SecurityAuthzHandler(policy.Name)for policy enforcement - Maintains compatibility with legacy Forward Auth
3. Manager Updates
File: /projects/cpmp/backend/internal/caddy/manager.go
Updated ApplyConfig() to:
- Fetch enabled auth users from database
- Fetch enabled auth providers from database
- Fetch enabled auth policies from database
- Preload AuthPolicy relationships for proxy hosts
- Pass auth data to
GenerateConfig()
4. Test Updates
Updated all test files to pass empty slices for new auth parameters:
client_test.goconfig_test.govalidator_test.gomanager_test.go
Architecture Flow
1. User Management UI → API → Database (AuthUser, AuthProvider, AuthPolicy)
2. ApplyConfig() → Fetch auth data → GenerateConfig()
3. GenerateConfig() → Create SecurityApp config
4. For each ProxyHost with AuthPolicyID:
- Inject SecurityAuthHandler (authentication)
- Inject SecurityAuthzHandler (authorization)
5. Caddy receives full config with security app
6. Incoming requests → Caddy → Security handlers → Backend services
Database Schema
auth_users
- id, uuid, created_at, updated_at
- username, email, name
- password_hash
- enabled, roles
- mfa_enabled, mfa_secret
- last_login_at
auth_providers
- id, uuid, created_at, updated_at
- name, type, enabled
- client_id, client_secret
- issuer_url, auth_url, token_url, user_info_url
- scopes, role_mapping
- icon_url, display_name
auth_policies
- id, uuid, created_at, updated_at
- name, description, enabled
- allowed_roles, allowed_users, allowed_domains
- require_mfa, session_timeout
proxy_hosts (updated)
- Added: auth_policy_id (nullable FK)
Configuration Example
When a proxy host has auth_policy_id = 1 (pointing to "Admins Only" policy):
{
"apps": {
"security": {
"authentication": {
"portals": {
"cpmp_portal": {
"backends": [
{
"name": "local",
"method": "local",
"config": {
"users": [
{
"username": "admin",
"email": "admin@example.com",
"password": "$2a$10$...",
"roles": ["admin"]
}
]
}
}
]
}
}
},
"authorization": {
"policies": {
"Admins Only": {
"allowed_roles": ["admin"],
"require_mfa": false
}
}
}
},
"http": {
"servers": {
"cpm_server": {
"routes": [
{
"match": [{"host": ["app.example.com"]}],
"handle": [
{"handler": "authentication", "portal": "cpmp_portal"},
{"handler": "authorization", "policy": "Admins Only"},
{"handler": "reverse_proxy", "upstreams": [{"dial": "backend:8080"}]}
]
}
]
}
}
}
}
}
Security Considerations
- Password Storage: Uses bcrypt for secure password hashing
- Secrets: ClientSecret and MFASecret fields are never exposed in JSON responses
- Admin Protection: Cannot delete the last admin user
- Policy Enforcement: Cannot delete policies that are in use
- MFA Support: Framework ready for TOTP implementation
Next Steps (Phase 3 & 4)
Phase 3: Frontend Management UI
- Create
/src/pages/Security/directory - Implement Users management page
- Implement Providers management page
- Implement Policies management page
- Add SSO dashboard with session overview
Phase 4: Proxy Host Integration
- Update ProxyHostForm with "Access Control" tab
- Add policy selector dropdown
- Display active policy on host list
- Show authentication status indicators
Testing
All backend tests pass:
✓ internal/api/handlers
✓ internal/api/middleware
✓ internal/api/routes
✓ internal/caddy (all tests updated)
✓ internal/config
✓ internal/database
✓ internal/models
✓ internal/server
✓ internal/services
✓ internal/version
Backend compiles successfully without errors.
Acceptance Criteria Status
- ✅ Can create local users for authentication (AuthUser model + API)
- ✅ Can protect services with built-in SSO (AuthPolicy + route integration)
- ⏳ 2FA works correctly (framework ready, needs frontend implementation)
- ✅ External OIDC providers can be configured (AuthProvider model + API)
Reserved Routes
/auth/*- Reserved for caddy-security authentication portal- Portal URL:
https://yourdomain.com/auth/login - Logout URL:
https://yourdomain.com/auth/logout
Notes
- The implementation uses SQLite as the source of truth
- Configuration is "compiled" from database to Caddy JSON on each ApplyConfig
- No direct database sharing with caddy-security (config-based integration)
- Compatible with existing Forward Auth feature (both can coexist)
- MFA secret storage is ready but TOTP setup flow needs frontend work