176 lines
4.5 KiB
Markdown
176 lines
4.5 KiB
Markdown
|
|
# OIDC/SSO Automation
|
||
|
|
|
||
|
|
This document explains the fully automated OIDC/SSO setup between Zitadel and Nextcloud.
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
The infrastructure now supports **fully automated** OIDC application provisioning, eliminating manual configuration steps. This makes the system scalable to dozens or hundreds of servers.
|
||
|
|
|
||
|
|
## How It Works
|
||
|
|
|
||
|
|
### 1. Automated OIDC App Creation
|
||
|
|
|
||
|
|
When deploying a new client, the Ansible playbook automatically:
|
||
|
|
|
||
|
|
1. **Authenticates with Zitadel** using admin credentials
|
||
|
|
2. **Creates OIDC application** via Zitadel Management API
|
||
|
|
3. **Retrieves client credentials** (client ID and secret)
|
||
|
|
4. **Configures Nextcloud** with the OIDC provider
|
||
|
|
|
||
|
|
### 2. Zero Manual Steps
|
||
|
|
|
||
|
|
The entire SSO setup happens automatically during deployment:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
ansible-playbook -i hcloud.yml playbooks/deploy.yml
|
||
|
|
```
|
||
|
|
|
||
|
|
No need to:
|
||
|
|
- Login to Zitadel console
|
||
|
|
- Manually create OIDC apps
|
||
|
|
- Copy/paste client credentials
|
||
|
|
- Configure Nextcloud manually
|
||
|
|
|
||
|
|
### 3. Scalability
|
||
|
|
|
||
|
|
This automation makes it trivial to deploy **dozens of servers**:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# terraform.tfvars
|
||
|
|
clients = {
|
||
|
|
client1 = { ... }
|
||
|
|
client2 = { ... }
|
||
|
|
client3 = { ... }
|
||
|
|
# Add as many as needed!
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Each client gets:
|
||
|
|
- Its own Zitadel instance
|
||
|
|
- Its own Nextcloud instance
|
||
|
|
- Automatic OIDC configuration
|
||
|
|
- Unique credentials
|
||
|
|
|
||
|
|
## Technical Implementation
|
||
|
|
|
||
|
|
### Components
|
||
|
|
|
||
|
|
1. **`get_admin_token.sh`**: Authenticates with Zitadel using admin credentials
|
||
|
|
2. **`create_oidc_app.py`**: Creates OIDC app via Zitadel Management API
|
||
|
|
3. **`oidc-apps.yml`**: Ansible task orchestrating the automation
|
||
|
|
4. **`nextcloud/oidc.yml`**: Configures Nextcloud with OIDC provider
|
||
|
|
|
||
|
|
### Authentication Flow
|
||
|
|
|
||
|
|
```
|
||
|
|
1. Ansible → get_admin_token.sh → Zitadel OAuth2
|
||
|
|
2. Receives → JWT access token
|
||
|
|
3. Ansible → create_oidc_app.py → Zitadel Management API
|
||
|
|
4. Creates → OIDC application
|
||
|
|
5. Returns → Client ID + Client Secret
|
||
|
|
6. Ansible → Nextcloud occ command
|
||
|
|
7. Configures → OIDC provider
|
||
|
|
```
|
||
|
|
|
||
|
|
### API Endpoints Used
|
||
|
|
|
||
|
|
- **Token**: `POST https://{domain}/oauth/v2/token`
|
||
|
|
- **Projects**: `POST https://{domain}/management/v1/projects/_search`
|
||
|
|
- **Create App**: `POST https://{domain}/management/v1/projects/{id}/apps/oidc`
|
||
|
|
|
||
|
|
### Security Considerations
|
||
|
|
|
||
|
|
- Admin credentials are stored in **encrypted SOPS secrets**
|
||
|
|
- Access tokens are **ephemeral** (generated per-deployment)
|
||
|
|
- Client secrets are **never logged** (no_log: true)
|
||
|
|
- API calls use **HTTPS only**
|
||
|
|
|
||
|
|
## Configuration Options
|
||
|
|
|
||
|
|
### Zitadel OIDC App Settings
|
||
|
|
|
||
|
|
The automation creates apps with these settings:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
- Response Type: Authorization Code
|
||
|
|
- Grant Types: Authorization Code, Refresh Token
|
||
|
|
- App Type: Web Application
|
||
|
|
- Auth Method: Client Secret Basic
|
||
|
|
- Token Type: JWT
|
||
|
|
- Role Assertions: Enabled
|
||
|
|
- UserInfo Assertions: Enabled
|
||
|
|
```
|
||
|
|
|
||
|
|
### Nextcloud OIDC Provider
|
||
|
|
|
||
|
|
Configured with:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
- Provider Name: Zitadel
|
||
|
|
- Client ID: <auto-generated>
|
||
|
|
- Client Secret: <auto-generated>
|
||
|
|
- Discovery URI: https://{domain}/.well-known/openid-configuration
|
||
|
|
```
|
||
|
|
|
||
|
|
## Testing
|
||
|
|
|
||
|
|
After deployment, verify SSO works:
|
||
|
|
|
||
|
|
1. Visit: `https://nextcloud.{client}.vrije.cloud`
|
||
|
|
2. Click "Login with SSO" or "Zitadel"
|
||
|
|
3. Redirected to Zitadel login
|
||
|
|
4. Enter Zitadel credentials
|
||
|
|
5. Redirected back to Nextcloud (logged in)
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### OIDC App Not Created
|
||
|
|
|
||
|
|
Check Ansible output for errors in:
|
||
|
|
- `Get admin access token for API calls`
|
||
|
|
- `Create OIDC application for Nextcloud`
|
||
|
|
|
||
|
|
Common issues:
|
||
|
|
- Admin password incorrect
|
||
|
|
- Zitadel API not accessible
|
||
|
|
- Network connectivity issues
|
||
|
|
|
||
|
|
### Nextcloud OIDC Not Configured
|
||
|
|
|
||
|
|
Check if credentials were passed:
|
||
|
|
- `nextcloud_oidc_client_id` should be defined
|
||
|
|
- `nextcloud_oidc_client_secret` should be defined
|
||
|
|
|
||
|
|
Verify in Nextcloud:
|
||
|
|
```bash
|
||
|
|
docker exec -u www-data nextcloud php occ user_oidc:provider
|
||
|
|
```
|
||
|
|
|
||
|
|
### SSO Login Fails
|
||
|
|
|
||
|
|
Check redirect URI matches exactly:
|
||
|
|
```
|
||
|
|
https://nextcloud.{client}.vrije.cloud/apps/user_oidc/code
|
||
|
|
```
|
||
|
|
|
||
|
|
Check Zitadel application settings:
|
||
|
|
- Redirect URIs configured correctly
|
||
|
|
- Grant types include Authorization Code
|
||
|
|
- Application is active (not disabled)
|
||
|
|
|
||
|
|
## Future Enhancements
|
||
|
|
|
||
|
|
Potential improvements:
|
||
|
|
|
||
|
|
1. **Service Account**: Use dedicated service account instead of admin
|
||
|
|
2. **Token Caching**: Cache access tokens to reduce API calls
|
||
|
|
3. **Multi-App Support**: Automate Collabora, OnlyOffice, etc.
|
||
|
|
4. **Role Mapping**: Sync Zitadel roles to Nextcloud groups
|
||
|
|
5. **User Provisioning**: Auto-create users on first SSO login
|
||
|
|
|
||
|
|
## References
|
||
|
|
|
||
|
|
- [Zitadel Management API](https://zitadel.com/docs/apis/resources/mgmt)
|
||
|
|
- [Nextcloud OIDC App](https://github.com/nextcloud/user_oidc)
|
||
|
|
- [OAuth 2.0 Authorization Code Flow](https://oauth.net/2/grant-types/authorization-code/)
|