# Authentication Service with Active Directory Integration This authentication service provides JWT-based authentication with Active Directory integration and Traefik ForwardAuth support for Kubernetes environments. ## Features - πŸ” **Active Directory Authentication**: Validates credentials against your AD server - 🎫 **JWT Tokens**: Secure token-based authentication with configurable expiration - πŸͺ **Cookie & Local Storage**: Tokens stored securely in HTTP-only cookies and locally - πŸš€ **Traefik Integration**: ForwardAuth middleware for seamless Kubernetes access control - πŸ“± **Responsive UI**: Clean, modern login interface - πŸ”’ **Security Headers**: Proper CORS, security headers, and token validation ## Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ User Browser │───▢│ Auth Service │───▢│ Active Directoryβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ 1. Login Form β”‚ β”‚ 2. Validate AD β”‚ β”‚ 3. LDAP Auth β”‚ β”‚ 4. Store Token │◀───│ Create JWT β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β–Ό β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Protected API │◀───│ Traefik Forward β”‚ β”‚ β”‚ β”‚ Auth Middleware β”‚ β”‚ 5. Access with β”‚ β”‚ 6. Validate JWT β”‚ β”‚ JWT Token β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ## Quick Start To build image, let's drone io work! As we use drone.io simply push git repository ### 1. Configure Active Directory Update the `values.yaml` file with your AD configuration: ```yaml authService: activeDirectory: server: "ldap://your-ad-server.yourdomain.com" baseDN: "DC=yourdomain,DC=com" userSearchBase: "CN=Users,DC=yourdomain,DC=com" bindUser: "CN=ServiceAccount,CN=Users,DC=yourdomain,DC=com" bindPassword: "your-service-account-password" ``` ### 3. Configure Traefik ForwardAuth The service automatically creates a ForwardAuth middleware that: ```yaml apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: auth-forward spec: forwardAuth: address: http://auth-service:8080/auth/verify authResponseHeaders: - "X-Auth-User" - "X-Auth-Email" - "X-Auth-Groups" - "X-Auth-Display-Name" ``` ### 4. Protect Your Services Add the ForwardAuth middleware to any IngressRoute: ```yaml apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: protected-service spec: routes: - match: Host(`api.yourdomain.com`) kind: Rule services: - name: your-api-service port: 8000 middlewares: - name: auth-forward # This protects the entire service ``` ## How It Works ### Authentication Flow 1. **User visits protected resource** β†’ Traefik ForwardAuth redirects to login 2. **User enters AD credentials** β†’ Service validates against Active Directory 3. **JWT token created** β†’ Stored in HTTP-only cookie + localStorage 4. **Subsequent requests** β†’ Traefik validates JWT via ForwardAuth 5. **Access granted** β†’ User headers passed to backend service ### Token Storage The system uses a dual-storage approach: - **HTTP-only Cookie**: Secure, automatic transmission, protected from XSS - **localStorage**: Available to JavaScript for SPA applications ### Security Features - βœ… **LDAP over TLS** support for secure AD communication - βœ… **JWT token expiration** with configurable timeouts - βœ… **HTTP-only cookies** prevent XSS token theft - βœ… **Secure headers** for production deployment - βœ… **CORS protection** with configurable origins ## API Endpoints ### Authentication Endpoints | Endpoint | Method | Description | |----------|--------|-------------| | `/` | GET | Login page (HTML) | | `/dashboard` | GET | Dashboard page (HTML) | | `/auth/login` | POST | Authenticate user | | `/auth/verify` | POST | Verify JWT token (ForwardAuth) | | `/auth/logout` | GET | Logout user | | `/auth/user` | GET | Get current user info | | `/health` | GET | Health check | ### ForwardAuth Integration When Traefik calls `/auth/verify`, the service: 1. **Checks for token** in Authorization header or cookies 2. **Validates JWT** signature and expiration 3. **Returns user headers** for backend services: - `X-Auth-User`: Username - `X-Auth-Email`: User email - `X-Auth-Groups`: AD group memberships - `X-Auth-Display-Name`: User's display name ## Configuration ### Environment Variables | Variable | Description | Default | |----------|-------------|---------| | `JWT_SECRET` | Secret key for JWT signing | (required) | | `TOKEN_EXPIRE_HOURS` | Token expiration in hours | 8 | | `AD_SERVER` | LDAP server URL | (required) | | `AD_BASE_DN` | Base DN for AD | (required) | | `AD_USER_SEARCH_BASE` | User search base | (required) | | `AD_BIND_USER` | Service account for LDAP | (optional) | | `AD_BIND_PASSWORD` | Service account password | (optional) | ### Kubernetes Secrets Create the required secrets: ```bash kubectl create secret generic auth-secrets \ --from-literal=jwt-secret="your-super-secret-key" \ --from-literal=ad-bind-user="CN=ServiceAccount,CN=Users,DC=yourdomain,DC=com" \ --from-literal=ad-bind-password="your-service-password" ``` ## Advanced Usage ### Custom Group-Based Access The service passes AD group memberships in the `X-Auth-Groups` header. You can use this in your backend services: ```python # In your FastAPI backend from fastapi import Header def check_admin_access(x_auth_groups: str = Header(None)): groups = x_auth_groups.split(',') if x_auth_groups else [] if 'CN=Admins,CN=Groups,DC=yourdomain,DC=com' not in groups: raise HTTPException(status_code=403, detail="Admin access required") ``` ### Multiple Protection Levels You can create different ForwardAuth middlewares for different access levels: ```yaml # Admin-only middleware apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: admin-auth spec: forwardAuth: address: http://auth-service:8080/auth/verify-admin authResponseHeaders: - "X-Auth-User" - "X-Auth-Groups" ``` ### Token Refresh The service automatically handles token refresh. Configure shorter expiration times and implement refresh logic in your frontend: ```javascript // Check token expiration const token = localStorage.getItem('auth_token'); const payload = JSON.parse(atob(token.split('.')[1])); const expiry = new Date(payload.exp * 1000); if (expiry < new Date()) { // Redirect to login for refresh window.location.href = '/auth/login'; } ``` ## Monitoring ### Health Checks The service includes health check endpoints: ```bash curl http://auth-service:8080/health ``` ### Logging The service logs authentication attempts and failures: ``` INFO: Successfully authenticated user: john.doe ERROR: Authentication failed for user: invalid.user ERROR: LDAP connection failed: timeout ``` ## Security Considerations 1. **Use HTTPS**: Always deploy with TLS certificates 2. **Secure JWT Secret**: Use a strong, unique JWT secret 3. **Network Security**: Restrict access to AD servers 4. **Token Expiration**: Use reasonable token expiration times 5. **Service Account**: Use a dedicated AD service account with minimal permissions 6. **Audit Logs**: Monitor authentication logs for suspicious activity ## Troubleshooting ### Common Issues 1. **LDAP Connection Failed** - Check AD server connectivity - Verify LDAP URL format - Check firewall rules 2. **Authentication Failed** - Verify AD credentials - Check user search base DN - Confirm user exists in specified OU 3. **ForwardAuth Not Working** - Verify Traefik middleware configuration - Check service connectivity - Review Traefik logs 4. **Token Issues** - Verify JWT secret consistency - Check token expiration - Validate cookie settings ### Debug Mode Enable debug logging by setting log level: ```yaml env: - name: LOG_LEVEL value: "DEBUG" ``` This will provide detailed authentication flow logs. # Trigger build with Jsonnet # Webhook test mer. 01 oct. 2025 17:11:01 CEST # DNS fix test mer. 01 oct. 2025 17:25:00 CEST # RBAC fix test jeu. 02 oct. 2025 09:06:56 CEST