# OAuth 2.0 Integration Konzept für Certigo ## 1. Übersicht ### 1.1 Ziel Integration von OAuth 2.0 als zusätzliche Authentifizierungsmethode neben dem bestehenden Basic Authentication System. Benutzer sollen sich mit externen OAuth-Providern (z.B. Google, Microsoft, GitHub) anmelden können. ### 1.2 Anforderungen - **Hybrides System**: OAuth und Basic Auth parallel unterstützen - **User Linking**: OAuth-Benutzer mit bestehenden lokalen Accounts verknüpfen können - **Automatische User-Erstellung**: Neue OAuth-Benutzer automatisch anlegen - **Berechtigungssystem**: OAuth-Benutzer in bestehendes Permission-System integrieren - **Session Management**: Sichere Session-Verwaltung für OAuth-Logins - **Multi-Provider**: Unterstützung mehrerer OAuth-Provider gleichzeitig --- ## 2. Architektur ### 2.1 OAuth Flow (Authorization Code Flow) ``` ┌─────────┐ ┌──────────┐ ┌─────────────┐ ┌──────────┐ │ Browser │ │ Frontend │ │ Backend │ │ OAuth │ │ │ │ │ │ │ │ Provider │ └────┬────┘ └────┬─────┘ └──────┬──────┘ └────┬─────┘ │ │ │ │ │ 1. Login Button │ │ │ │──────────────────>│ │ │ │ │ │ │ │ │ 2. GET /api/oauth/{provider}/auth │ │ │─────────────────────>│ │ │ │ │ │ │ │ │ 3. Redirect to OAuth │ │ │ │ Authorization URL │ │ │<─────────────────────│ │ │ │ │ │ │ 4. Redirect to │ │ │ │ OAuth Provider │ │ │ │<──────────────────│ │ │ │ │ │ │ │ 5. User Auth │ │ │ │────────────────────────────────────────────────────────────────>│ │ │ │ │ │ 6. Callback with │ │ │ │ Authorization │ │ │ │ Code │ │ │ │<────────────────────────────────────────────────────────────────│ │ │ │ │ │ 7. Callback to │ │ │ │ /api/oauth/ │ │ │ │ {provider}/ │ │ │ │ callback │ │ │ │──────────────────>│ │ │ │ │ 8. POST /api/oauth/{provider}/callback │ │ │ (code=xxx) │ │ │ │─────────────────────>│ │ │ │ │ │ │ │ │ 9. Exchange Code for │ │ │ │ Access Token │ │ │ │──────────────────────>│ │ │ │ │ │ │ │ 10. Get User Info │ │ │ │──────────────────────>│ │ │ │ │ │ │ │ 11. User Info │ │ │ │<──────────────────────│ │ │ │ │ │ │ │ 12. Create/Update │ │ │ │ User in DB │ │ │ │ │ │ │ │ 13. Create Session │ │ │ │ │ │ │ 14. Return Session │ │ │ │ Token │ │ │ │<─────────────────────│ │ │ │ │ │ │ 15. Store Session │ │ │ │ & Redirect │ │ │ │<──────────────────│ │ │ │ │ │ │ ``` ### 2.2 Komponenten #### Backend - **OAuth Handler**: `/api/oauth/{provider}/auth` - Initiierung des OAuth Flows - **OAuth Callback Handler**: `/api/oauth/{provider}/callback` - Verarbeitung des Authorization Codes - **OAuth Provider Manager**: Verwaltung mehrerer OAuth-Provider - **Session Manager**: Verwaltung von OAuth-Sessions (JWT oder Session-Tokens) - **User Linking Service**: Verknüpfung von OAuth-Accounts mit lokalen Accounts #### Frontend - **OAuth Login Component**: Buttons für verschiedene OAuth-Provider - **OAuth Callback Handler**: Verarbeitung des Redirects nach OAuth-Authentifizierung - **Session Storage**: Speicherung von Session-Tokens (HttpOnly Cookies bevorzugt) --- ## 3. Datenbank-Schema ### 3.1 Erweiterte Users-Tabelle ```sql -- Migration: Erweitere users-Tabelle um OAuth-Felder ALTER TABLE users ADD COLUMN auth_method TEXT DEFAULT 'basic'; -- 'basic' | 'oauth' | 'hybrid' ALTER TABLE users ADD COLUMN oauth_provider TEXT; -- 'google' | 'microsoft' | 'github' | NULL ALTER TABLE users ADD COLUMN oauth_provider_id TEXT; -- Externe User-ID vom OAuth-Provider ALTER TABLE users ADD COLUMN oauth_email TEXT; -- Email vom OAuth-Provider (kann von lokaler Email abweichen) ALTER TABLE users ADD COLUMN password_hash TEXT; -- NULL für reine OAuth-User ``` ### 3.2 Neue Tabelle: oauth_sessions ```sql CREATE TABLE IF NOT EXISTS oauth_sessions ( id TEXT PRIMARY KEY, user_id TEXT NOT NULL, provider TEXT NOT NULL, access_token TEXT, -- Verschlüsselt gespeichert refresh_token TEXT, -- Verschlüsselt gespeichert expires_at DATETIME NOT NULL, created_at DATETIME NOT NULL, last_used_at DATETIME, ip_address TEXT, user_agent TEXT, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ); CREATE INDEX idx_oauth_sessions_user_id ON oauth_sessions(user_id); CREATE INDEX idx_oauth_sessions_expires_at ON oauth_sessions(expires_at); ``` ### 3.3 Neue Tabelle: oauth_providers ```sql CREATE TABLE IF NOT EXISTS oauth_providers ( id TEXT PRIMARY KEY, -- 'google', 'microsoft', 'github' name TEXT NOT NULL, enabled BOOLEAN DEFAULT 1, client_id TEXT NOT NULL, client_secret TEXT NOT NULL, -- Verschlüsselt gespeichert authorization_url TEXT NOT NULL, token_url TEXT NOT NULL, user_info_url TEXT NOT NULL, scopes TEXT, -- JSON Array: ["openid", "email", "profile"] created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL ); ``` ### 3.4 Neue Tabelle: user_oauth_links ```sql -- Für Benutzer, die mehrere OAuth-Provider verknüpfen wollen CREATE TABLE IF NOT EXISTS user_oauth_links ( id TEXT PRIMARY KEY, user_id TEXT NOT NULL, provider TEXT NOT NULL, provider_user_id TEXT NOT NULL, provider_email TEXT, linked_at DATETIME NOT NULL, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, UNIQUE(provider, provider_user_id) ); CREATE INDEX idx_user_oauth_links_user_id ON user_oauth_links(user_id); CREATE INDEX idx_user_oauth_links_provider ON user_oauth_links(provider, provider_user_id); ``` --- ## 4. OAuth Provider Konfiguration ### 4.1 Unterstützte Provider #### Google OAuth 2.0 - **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth` - **Token URL**: `https://oauth2.googleapis.com/token` - **User Info URL**: `https://www.googleapis.com/oauth2/v2/userinfo` - **Scopes**: `["openid", "email", "profile"]` #### Microsoft Azure AD - **Authorization URL**: `https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize` - **Token URL**: `https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token` - **User Info URL**: `https://graph.microsoft.com/v1.0/me` - **Scopes**: `["openid", "email", "profile"]` #### GitHub - **Authorization URL**: `https://github.com/login/oauth/authorize` - **Token URL**: `https://github.com/login/oauth/access_token` - **User Info URL**: `https://api.github.com/user` - **Scopes**: `["user:email"]` ### 4.2 Provider-Konfiguration (Environment Variables / Config File) ```yaml oauth: providers: google: enabled: true client_id: "${GOOGLE_CLIENT_ID}" client_secret: "${GOOGLE_CLIENT_SECRET}" redirect_uri: "http://localhost:5173/api/oauth/google/callback" scopes: ["openid", "email", "profile"] microsoft: enabled: true tenant: "${MICROSOFT_TENANT_ID}" client_id: "${MICROSOFT_CLIENT_ID}" client_secret: "${MICROSOFT_CLIENT_SECRET}" redirect_uri: "http://localhost:5173/api/oauth/microsoft/callback" scopes: ["openid", "email", "profile"] github: enabled: false client_id: "${GITHUB_CLIENT_ID}" client_secret: "${GITHUB_CLIENT_SECRET}" redirect_uri: "http://localhost:5173/api/oauth/github/callback" scopes: ["user:email"] ``` --- ## 5. API-Endpunkte ### 5.1 OAuth Initiation **GET** `/api/oauth/{provider}/auth` Initiert den OAuth Flow für einen bestimmten Provider. **Query Parameters:** - `redirect_uri` (optional): Custom Redirect URI nach erfolgreichem Login **Response:** - `302 Redirect` zur OAuth Provider Authorization URL **Beispiel:** ``` GET /api/oauth/google/auth → Redirect zu: https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=...&scope=...&response_type=code&state=... ``` ### 5.2 OAuth Callback **GET** `/api/oauth/{provider}/callback` Verarbeitet den Authorization Code vom OAuth-Provider. **Query Parameters:** - `code`: Authorization Code vom Provider - `state`: CSRF Protection Token (optional, aber empfohlen) **Response:** ```json { "success": true, "user": { "id": "uuid", "username": "user@example.com", "email": "user@example.com", "isAdmin": false, "enabled": true, "authMethod": "oauth", "oauthProvider": "google" }, "sessionToken": "jwt-token-here", "redirectTo": "/" } ``` **Fehler-Response:** ```json { "success": false, "error": "Invalid authorization code", "errorCode": "OAUTH_INVALID_CODE" } ``` ### 5.3 OAuth Logout **POST** `/api/oauth/logout` Beendet die OAuth-Session. **Headers:** - `Authorization: Bearer {sessionToken}` **Response:** ```json { "success": true, "message": "Logged out successfully" } ``` ### 5.4 OAuth Provider Status **GET** `/api/oauth/providers` Gibt eine Liste aller konfigurierten OAuth-Provider zurück. **Response:** ```json { "providers": [ { "id": "google", "name": "Google", "enabled": true, "authUrl": "/api/oauth/google/auth" }, { "id": "microsoft", "name": "Microsoft", "enabled": true, "authUrl": "/api/oauth/microsoft/auth" } ] } ``` ### 5.5 Link OAuth Account **POST** `/api/oauth/link` Verknüpft einen OAuth-Account mit einem bestehenden lokalen Account (für Hybrid-Auth). **Headers:** - `Authorization: Basic {credentials}` (lokaler Account) **Body:** ```json { "provider": "google", "code": "authorization-code-from-oauth" } ``` **Response:** ```json { "success": true, "message": "OAuth account linked successfully" } ``` --- ## 6. Session Management ### 6.1 Session-Token (JWT) **Token-Struktur:** ```json { "sub": "user-uuid", "auth_method": "oauth", "provider": "google", "exp": 1234567890, "iat": 1234567890, "session_id": "session-uuid" } ``` **Token-Speicherung:** - **Backend**: In `oauth_sessions` Tabelle - **Frontend**: HttpOnly Cookie (bevorzugt) oder localStorage (Fallback) - **Lifetime**: 24 Stunden (konfigurierbar) - **Refresh**: Automatisches Refresh bei Ablauf (falls Refresh Token vorhanden) ### 6.2 Session-Validierung **Middleware**: `oauthSessionMiddleware` Prüft OAuth-Session-Token in folgenden Headers: 1. `Authorization: Bearer {token}` 2. Cookie: `oauth_session` **Flow:** ``` Request → oauthSessionMiddleware → Check Token → Validate Session → Continue ↓ Invalid 401 Unauthorized ``` --- ## 7. User Management ### 7.1 Automatische User-Erstellung **Flow:** 1. OAuth-Callback empfängt User-Info vom Provider 2. Prüfe ob User mit `oauth_provider_id` existiert 3. Falls nicht: - Erstelle neuen User - Setze `auth_method = 'oauth'` - Setze `oauth_provider` und `oauth_provider_id` - Setze `password_hash = NULL` - Setze `enabled = true` (oder konfigurierbar) - Setze `isAdmin = false` - Weise Standard-Berechtigungsgruppe zu (optional) 4. Falls ja: - Update `last_login_at` (falls Feld existiert) - Update Session ### 7.2 User Linking (Hybrid Auth) **Szenario**: Benutzer hat bereits lokalen Account, möchte OAuth hinzufügen **Flow:** 1. User loggt sich mit Basic Auth ein 2. User klickt "Link Google Account" 3. OAuth Flow wird initiiert 4. Nach erfolgreicher OAuth-Auth: - Verknüpfe OAuth-Account mit lokalem Account - Setze `auth_method = 'hybrid'` - Erstelle Eintrag in `user_oauth_links` 5. User kann sich nun mit beiden Methoden anmelden ### 7.3 User Mapping **Email-basierte Verknüpfung:** - Falls OAuth-Email mit lokalem Account übereinstimmt → Auto-Link (optional, konfigurierbar) - Falls nicht → Neue User-Erstellung oder manuelle Verknüpfung erforderlich --- ## 8. Sicherheit ### 8.1 CSRF Protection **State Parameter:** - Generiere zufälligen `state` Token bei OAuth-Initiation - Speichere in Session/Cookie - Validiere bei Callback **Implementierung:** ```go state := generateRandomToken(32) storeStateInSession(state) redirectURL := fmt.Sprintf("%s?state=%s&...", oauthURL, state) ``` ### 8.2 Token-Verschlüsselung **Access/Refresh Tokens:** - Verschlüsselt in Datenbank speichern (AES-256) - Nie im Klartext loggen - Automatische Löschung bei Ablauf ### 8.3 Rate Limiting **OAuth-Endpunkte:** - `/api/oauth/{provider}/auth`: 10 Requests/Minute pro IP - `/api/oauth/{provider}/callback`: 5 Requests/Minute pro IP ### 8.4 Secure Cookies **Session Cookies:** - `HttpOnly`: true - `Secure`: true (HTTPS only) - `SameSite`: Lax oder Strict - `Path`: `/api` --- ## 9. Frontend-Integration ### 9.1 Login-Seite Erweiterung **Aktuelle Login-Seite** (`frontend/src/pages/Login.jsx`) erweitern: ```jsx // OAuth Login Buttons hinzufügen
// Oder: Separater OAuth-Login-Bereich
oder
``` ### 9.2 OAuth Callback Handler **Neue Route**: `frontend/src/pages/OAuthCallback.jsx` ```jsx useEffect(() => { const params = new URLSearchParams(window.location.search) const code = params.get('code') const state = params.get('state') const provider = extractProviderFromURL() // z.B. '/oauth/google/callback' if (code) { handleOAuthCallback(provider, code, state) } }, []) ``` ### 9.3 AuthContext Erweiterung **Erweitere** `frontend/src/contexts/AuthContext.jsx`: ```jsx const loginWithOAuth = async (provider) => { // Redirect zu Backend OAuth Initiation window.location.href = `/api/oauth/${provider}/auth` } const handleOAuthCallback = async (provider, code, state) => { const response = await fetch(`/api/oauth/${provider}/callback?code=${code}&state=${state}`) const data = await response.json() if (data.success) { // Store session token localStorage.setItem('oauth_session', data.sessionToken) setUser(data.user) setIsAuthenticated(true) navigate('/') } } ``` --- ## 10. Migration & Backward Compatibility ### 10.1 Bestehende User **Migration:** - Alle bestehenden User haben `auth_method = 'basic'` - `oauth_provider` und `oauth_provider_id` sind `NULL` - `password_hash` bleibt bestehen ### 10.2 API-Kompatibilität **Bestehende Endpunkte:** - Funktionieren weiterhin mit Basic Auth - Neue Middleware prüft zuerst OAuth-Session, dann Basic Auth **Middleware-Order:** ``` Request → oauthSessionMiddleware → basicAuthMiddleware → Handler ↓ Invalid ↓ Invalid Try Basic Auth 401 Unauthorized ``` ### 10.3 User-Erstellung **Admin-Erstellung:** - Admins können weiterhin lokale User erstellen - OAuth-User können manuell zu Admins gemacht werden --- ## 11. Konfiguration & Deployment ### 11.1 Environment Variables ```bash # OAuth Provider Credentials GOOGLE_CLIENT_ID=xxx GOOGLE_CLIENT_SECRET=xxx MICROSOFT_CLIENT_ID=xxx MICROSOFT_CLIENT_SECRET=xxx MICROSOFT_TENANT_ID=xxx GITHUB_CLIENT_ID=xxx GITHUB_CLIENT_SECRET=xxx # OAuth Settings OAUTH_SESSION_SECRET=xxx # Für Session-Token Signing OAUTH_SESSION_LIFETIME=24h OAUTH_REDIRECT_BASE_URL=http://localhost:5173 OAUTH_AUTO_CREATE_USERS=true OAUTH_AUTO_LINK_BY_EMAIL=false ``` ### 11.2 Provider-Registrierung **Google:** 1. Google Cloud Console → APIs & Services → Credentials 2. OAuth 2.0 Client ID erstellen 3. Authorized redirect URIs: `http://localhost:5173/api/oauth/google/callback` **Microsoft:** 1. Azure Portal → App Registrations 2. Neue App registrieren 3. Redirect URIs: `http://localhost:5173/api/oauth/microsoft/callback` **GitHub:** 1. GitHub Settings → Developer settings → OAuth Apps 2. Neue OAuth App erstellen 3. Authorization callback URL: `http://localhost:5173/api/oauth/github/callback` --- ## 12. Testing & Rollout ### 12.1 Test-Plan **Phase 1: Backend-Integration** - [ ] OAuth Provider Manager implementieren - [ ] OAuth Handler Endpunkte - [ ] Session Management - [ ] Datenbank-Migrationen **Phase 2: Frontend-Integration** - [ ] OAuth Login Buttons - [ ] Callback Handler - [ ] Session Storage - [ ] AuthContext Erweiterung **Phase 3: Testing** - [ ] Unit Tests für OAuth Flow - [ ] Integration Tests - [ ] Security Tests (CSRF, Token Validation) - [ ] User Acceptance Testing **Phase 4: Rollout** - [ ] Staging Deployment - [ ] Production Deployment - [ ] Monitoring & Logging ### 12.2 Rollback-Plan **Falls Probleme auftreten:** 1. OAuth-Endpunkte deaktivieren (Feature Flag) 2. Bestehende Basic Auth bleibt funktionsfähig 3. Datenbank-Migrationen sind rückwärtskompatibel --- ## 13. Monitoring & Logging ### 13.1 Logging **OAuth-Events:** - OAuth Flow Initiation - OAuth Callback (Erfolg/Fehler) - User-Erstellung via OAuth - Session-Erstellung/Löschung - Token-Refresh **Structured Logging:** ```go logOAuthEvent("oauth_login_initiated", map[string]interface{}{ "provider": "google", "user_id": userID, "ip_address": ip, "trace_id": traceID, }) ``` ### 13.2 Metrics **Zu tracken:** - Anzahl OAuth-Logins pro Provider - Erfolgsrate OAuth Flows - Session-Dauer - Fehlerrate (Invalid Code, Token Expiry, etc.) --- ## 14. Zukünftige Erweiterungen ### 14.1 Multi-Factor Authentication - OAuth als Second Factor für Basic Auth User ### 14.2 SSO (Single Sign-On) - SAML 2.0 Support - OpenID Connect ### 14.3 Social Login - Weitere Provider: Facebook, Twitter, LinkedIn ### 14.4 Account Management - UI für Verknüpfung mehrerer OAuth-Accounts - Entkopplung von OAuth-Accounts --- ## 15. Abhängigkeiten ### 15.1 Backend (Go) ```go // OAuth Libraries github.com/golang/oauth2 github.com/coreos/go-oidc/v3/oidc // Für OpenID Connect // JWT github.com/golang-jwt/jwt/v5 // Encryption golang.org/x/crypto ``` ### 15.2 Frontend Keine zusätzlichen Dependencies nötig (native Fetch API für OAuth Flow) --- ## 16. Risiken & Mitigation ### 16.1 Risiken | Risiko | Wahrscheinlichkeit | Impact | Mitigation | |--------|-------------------|--------|------------| | OAuth Provider Downtime | Mittel | Hoch | Fallback auf Basic Auth | | Token-Leak | Niedrig | Sehr Hoch | HttpOnly Cookies, Token Rotation | | CSRF-Angriffe | Mittel | Hoch | State Parameter Validation | | Account Takeover | Niedrig | Sehr Hoch | Email-Verification, Rate Limiting | ### 16.2 Security Best Practices - ✅ HTTPS nur (in Production) - ✅ State Parameter für CSRF Protection - ✅ Token-Verschlüsselung in DB - ✅ Session Timeout - ✅ Rate Limiting - ✅ Audit Logging --- ## 17. Zusammenfassung ### 17.1 Vorteile - **Benutzerfreundlichkeit**: Ein-Klick-Login mit bekannten Accounts - **Sicherheit**: Keine Passwort-Verwaltung für OAuth-User - **Skalierbarkeit**: Externe Provider übernehmen Authentifizierung - **Flexibilität**: Hybrid-System unterstützt beide Methoden ### 17.2 Herausforderungen - **Komplexität**: Zusätzliche Infrastruktur und Code - **Abhängigkeit**: Abhängig von externen Providern - **Migration**: Bestehende User müssen unterstützt werden - **Testing**: Mehr Test-Szenarien durch Multi-Provider --- **Erstellt am**: 2025-01-XX **Version**: 1.0 **Status**: Konzept - Noch nicht implementiert