23 KiB
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
-- 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
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
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
-- 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)
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 Redirectzur 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 Providerstate: CSRF Protection Token (optional, aber empfohlen)
Response:
{
"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:
{
"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:
{
"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:
{
"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:
{
"provider": "google",
"code": "authorization-code-from-oauth"
}
Response:
{
"success": true,
"message": "OAuth account linked successfully"
}
6. Session Management
6.1 Session-Token (JWT)
Token-Struktur:
{
"sub": "user-uuid",
"auth_method": "oauth",
"provider": "google",
"exp": 1234567890,
"iat": 1234567890,
"session_id": "session-uuid"
}
Token-Speicherung:
- Backend: In
oauth_sessionsTabelle - 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:
Authorization: Bearer {token}- Cookie:
oauth_session
Flow:
Request → oauthSessionMiddleware → Check Token → Validate Session → Continue
↓ Invalid
401 Unauthorized
7. User Management
7.1 Automatische User-Erstellung
Flow:
- OAuth-Callback empfängt User-Info vom Provider
- Prüfe ob User mit
oauth_provider_idexistiert - Falls nicht:
- Erstelle neuen User
- Setze
auth_method = 'oauth' - Setze
oauth_providerundoauth_provider_id - Setze
password_hash = NULL - Setze
enabled = true(oder konfigurierbar) - Setze
isAdmin = false - Weise Standard-Berechtigungsgruppe zu (optional)
- Falls ja:
- Update
last_login_at(falls Feld existiert) - Update Session
- Update
7.2 User Linking (Hybrid Auth)
Szenario: Benutzer hat bereits lokalen Account, möchte OAuth hinzufügen
Flow:
- User loggt sich mit Basic Auth ein
- User klickt "Link Google Account"
- OAuth Flow wird initiiert
- Nach erfolgreicher OAuth-Auth:
- Verknüpfe OAuth-Account mit lokalem Account
- Setze
auth_method = 'hybrid' - Erstelle Eintrag in
user_oauth_links
- 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
stateToken bei OAuth-Initiation - Speichere in Session/Cookie
- Validiere bei Callback
Implementierung:
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: trueSecure: true (HTTPS only)SameSite: Lax oder StrictPath:/api
9. Frontend-Integration
9.1 Login-Seite Erweiterung
Aktuelle Login-Seite (frontend/src/pages/Login.jsx) erweitern:
// OAuth Login Buttons hinzufügen
<div className="oauth-providers">
<button onClick={() => initiateOAuth('google')}>
<img src="/icons/google.svg" /> Mit Google anmelden
</button>
<button onClick={() => initiateOAuth('microsoft')}>
<img src="/icons/microsoft.svg" /> Mit Microsoft anmelden
</button>
</div>
// Oder: Separater OAuth-Login-Bereich
<div className="divider">oder</div>
9.2 OAuth Callback Handler
Neue Route: frontend/src/pages/OAuthCallback.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:
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_providerundoauth_provider_idsindNULLpassword_hashbleibt 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
# 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:
- Google Cloud Console → APIs & Services → Credentials
- OAuth 2.0 Client ID erstellen
- Authorized redirect URIs:
http://localhost:5173/api/oauth/google/callback
Microsoft:
- Azure Portal → App Registrations
- Neue App registrieren
- Redirect URIs:
http://localhost:5173/api/oauth/microsoft/callback
GitHub:
- GitHub Settings → Developer settings → OAuth Apps
- Neue OAuth App erstellen
- 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:
- OAuth-Endpunkte deaktivieren (Feature Flag)
- Bestehende Basic Auth bleibt funktionsfähig
- 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:
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)
// 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