# 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