Files
Maison/arti-api/auth-service/pipeline/MULTI-DOMAIN-GUIDE.md
2026-02-10 12:12:11 +01:00

306 lines
7.9 KiB
Markdown

# Multi-Domain Authentication for *.aipice.fr
This guide shows how to use a single authentication service to protect multiple subdomains under `aipice.fr`.
## 🎯 Architecture Overview
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ auth.aipice.fr │ │ arti-api.aipice │ │ *.aipice.fr │
│ │ │ .fr │ │ │
│ Auth Service │───▶│ Protected API │ │ Other Services │
│ (Login Page) │ │ (with auth) │ │ (with auth) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└────────────────────────┼────────────────────────┘
┌─────────────────┐
│ Active Directory│
│ Validation │
└─────────────────┘
```
## 🚀 Quick Setup for aipice.fr
### 1. Deploy the Authentication Service
```bash
# Run the deployment script
./deploy-aipice.sh
# This will:
# - Create wildcard certificate for *.aipice.fr
# - Deploy auth service at auth.aipice.fr
# - Protect arti-api.aipice.fr with authentication
# - Create reusable ForwardAuth middleware
```
### 2. Access Your Services
- **Authentication**: https://auth.aipice.fr
- **Protected API**: https://arti-api.aipice.fr (requires login)
- **Public endpoints**: https://arti-api.aipice.fr/ and /health (no auth)
## 🔒 How Multi-Domain Protection Works
### Authentication Flow
1. **User visits** `https://arti-api.aipice.fr/users`
2. **Traefik checks** auth via ForwardAuth middleware
3. **No token?** → Redirect to `https://auth.aipice.fr/?return_url=https://arti-api.aipice.fr/users`
4. **User logs in** → JWT token stored in cookie for `.aipice.fr` domain
5. **User redirected** back to `https://arti-api.aipice.fr/users`
6. **Traefik validates** token → Access granted
### Cross-Domain Cookie Sharing
The auth service sets cookies with `domain=.aipice.fr`, making them available to all subdomains:
```python
response.set_cookie(
key="auth_token",
value=token,
domain=".aipice.fr", # Works for all *.aipice.fr
httponly=True,
secure=True,
samesite="lax"
)
```
## 🛡️ Protecting Additional Services
To protect any new subdomain (e.g., `grafana.aipice.fr`), simply add the ForwardAuth middleware:
```yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: grafana-protected
spec:
entryPoints:
- websecure
routes:
- match: Host(`grafana.aipice.fr`)
kind: Rule
services:
- name: grafana
port: 3000
middlewares:
- name: auth-forward
namespace: infrastructure--artifactory--service # Where auth service is deployed
tls:
secretName: wildcard-aipice-fr
```
## 📋 Configuration Examples
### Multiple Protection Levels
You can create different auth requirements for different services:
```yaml
# Public service (no auth)
- match: Host(`public.aipice.fr`)
services:
- name: public-service
port: 80
# Basic auth required
- match: Host(`internal.aipice.fr`)
services:
- name: internal-service
port: 80
middlewares:
- name: auth-forward
# Admin-only access (custom verification)
- match: Host(`admin.aipice.fr`)
services:
- name: admin-service
port: 80
middlewares:
- name: admin-auth-forward # Custom middleware with admin check
```
### Group-Based Access Control
Use Active Directory groups for fine-grained access:
```python
# In your backend service
def require_admin_group(x_auth_groups: str = Header(None)):
groups = x_auth_groups.split(',') if x_auth_groups else []
admin_groups = [
'CN=Domain Admins,CN=Users,DC=aipice,DC=fr',
'CN=IT Team,CN=Groups,DC=aipice,DC=fr'
]
if not any(group in groups for group in admin_groups):
raise HTTPException(status_code=403, detail="Admin access required")
```
## 🔧 Advanced Configuration
### Environment Variables
The auth service supports these domain-specific variables:
```yaml
env:
- name: ALLOWED_DOMAINS
value: "aipice.fr,yourdomain.com" # Multiple domains supported
- name: AUTH_DOMAIN
value: "auth.aipice.fr"
- name: CORS_ORIGINS
value: "https://*.aipice.fr,https://*.yourdomain.com"
```
### Wildcard Certificate
For automatic SSL across all subdomains:
```yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-aipice-fr
spec:
secretName: wildcard-aipice-fr
issuerRef:
name: letsencrypt
kind: ClusterIssuer
commonName: "*.aipice.fr"
dnsNames:
- "aipice.fr"
- "*.aipice.fr"
```
## 🎨 Customizing the Login Page
Update the login page branding for your domain:
```html
<!-- In templates/login.html -->
<div class="login-header">
<h1>🔐 Aipice Access</h1>
<p>Sign in to access Aipice services</p>
</div>
```
## 📊 Monitoring and Logs
### Check Authentication Status
```bash
# View auth service logs
kubectl logs -n infrastructure--artifactory--service deployment/auth-service
# Check ForwardAuth requests
kubectl logs -n traefik deployment/traefik | grep "auth-forward"
# Test authentication
curl -H "Authorization: Bearer $TOKEN" https://auth.aipice.fr/auth/verify
```
### Common Log Entries
```
INFO: Successfully authenticated user: john.doe accessing arti-api.aipice.fr
INFO: No token found, redirecting to: https://auth.aipice.fr/?return_url=https://grafana.aipice.fr/
WARNING: Access denied for domain: suspicious.domain.com
```
## 🔍 Troubleshooting
### Issue: "Page isn't redirecting properly"
**Cause**: Redirect loop between auth service and protected service.
**Solution**: Ensure auth service domain is excluded from ForwardAuth:
```yaml
routes:
- match: Host(`auth.aipice.fr`)
# No auth-forward middleware here!
services:
- name: auth-service
```
### Issue: "Authentication required" but user is logged in
**Cause**: Cookie domain mismatch or token expiration.
**Solution**: Check cookie domain and token validity:
```bash
# Check token in browser console
localStorage.getItem('auth_token')
# Verify token server-side
curl -H "Authorization: Bearer $TOKEN" https://auth.aipice.fr/auth/verify
```
### Issue: Cross-domain cookie not working
**Cause**: Cookie domain not set correctly.
**Solution**: Ensure cookie domain starts with dot:
```python
domain=".aipice.fr" # ✅ Works for all subdomains
domain="aipice.fr" # ❌ Only works for exact domain
```
## 📈 Scaling Considerations
### High Availability
```yaml
spec:
replicas: 3 # Multiple auth service instances
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
```
### Performance Tuning
```yaml
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"
```
### Caching
Consider adding Redis for token caching in high-traffic scenarios:
```yaml
- name: REDIS_URL
value: "redis://redis-service:6379"
```
## 🎯 Real-World Example
Here's a complete setup for a company using multiple services:
```yaml
# Services protected by auth.aipice.fr:
# - arti-api.aipice.fr (Artifactory API)
# - grafana.aipice.fr (Monitoring)
# - jenkins.aipice.fr (CI/CD)
# - nextcloud.aipice.fr (File sharing)
# - wiki.aipice.fr (Documentation)
# All use the same ForwardAuth middleware
# All share the same authentication cookie
# All redirect to auth.aipice.fr when needed
# All respect Active Directory group memberships
```
This gives you enterprise-grade authentication across your entire `*.aipice.fr` infrastructure with a single, centralized auth service!