Initial commit: TimeClock v3 - Node.js/Vue.js Zeiterfassung
Features: - Backend: Node.js/Express mit MySQL/MariaDB - Frontend: Vue.js 3 mit Composition API - UTC-Zeithandling für korrekte Zeiterfassung - Timewish-basierte Überstundenberechnung - Wochenübersicht mit Urlaubs-/Krankheits-/Feiertagshandling - Bereinigtes Arbeitsende (Generell/Woche) - Überstunden-Offset für historische Daten - Fixed Layout mit scrollbarem Content - Kompakte UI mit grünem Theme
This commit is contained in:
345
OAUTH_SETUP.md
Normal file
345
OAUTH_SETUP.md
Normal file
@@ -0,0 +1,345 @@
|
||||
# Google OAuth Setup für TimeClock
|
||||
|
||||
## Übersicht
|
||||
|
||||
TimeClock v3 unterstützt Login mit Google Account über OAuth 2.0.
|
||||
|
||||
## Google Cloud Console Setup
|
||||
|
||||
### 1. Google Cloud Projekt erstellen
|
||||
|
||||
1. Gehen Sie zu: https://console.cloud.google.com
|
||||
2. Klicken Sie auf "Projekt auswählen" → "Neues Projekt"
|
||||
3. Projektname: `TimeClock`
|
||||
4. Klicken Sie auf "Erstellen"
|
||||
|
||||
### 2. OAuth Consent Screen konfigurieren
|
||||
|
||||
1. Navigieren Sie zu: **APIs & Services** → **OAuth consent screen**
|
||||
2. Wählen Sie **External** (oder Internal für Google Workspace)
|
||||
3. Klicken Sie auf "Erstellen"
|
||||
|
||||
**App-Informationen:**
|
||||
- App name: `TimeClock`
|
||||
- User support email: Ihre E-Mail
|
||||
- Developer contact: Ihre E-Mail
|
||||
|
||||
4. Klicken Sie auf "Speichern und fortfahren"
|
||||
|
||||
**Scopes:**
|
||||
- Fügen Sie hinzu: `email`, `profile`
|
||||
- Klicken Sie auf "Speichern und fortfahren"
|
||||
|
||||
**Test users** (für Development):
|
||||
- Fügen Sie Ihre Google-E-Mail hinzu
|
||||
- Klicken Sie auf "Speichern und fortfahren"
|
||||
|
||||
### 3. OAuth 2.0 Credentials erstellen
|
||||
|
||||
1. Navigieren Sie zu: **APIs & Services** → **Credentials**
|
||||
2. Klicken Sie auf **+ CREATE CREDENTIALS** → **OAuth client ID**
|
||||
|
||||
**Application type:** Web application
|
||||
|
||||
**Name:** TimeClock Web App
|
||||
|
||||
**Authorized JavaScript origins:**
|
||||
```
|
||||
http://localhost:5010
|
||||
http://localhost:3010
|
||||
```
|
||||
|
||||
**Authorized redirect URIs:**
|
||||
```
|
||||
http://localhost:3010/api/auth/google/callback
|
||||
```
|
||||
|
||||
4. Klicken Sie auf "Erstellen"
|
||||
5. **Wichtig:** Kopieren Sie:
|
||||
- Client ID
|
||||
- Client Secret
|
||||
|
||||
### 4. Backend konfigurieren
|
||||
|
||||
Bearbeiten Sie `/backend/.env`:
|
||||
|
||||
```env
|
||||
# Google OAuth 2.0
|
||||
GOOGLE_CLIENT_ID=ihre-client-id.apps.googleusercontent.com
|
||||
GOOGLE_CLIENT_SECRET=GOCSPX-ihr-client-secret
|
||||
GOOGLE_CALLBACK_URL=http://localhost:3010/api/auth/google/callback
|
||||
```
|
||||
|
||||
### 5. Backend neu starten
|
||||
|
||||
```bash
|
||||
# Backend stoppt und neu startet automatisch (nodemon)
|
||||
# Oder manuell:
|
||||
cd backend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
**Erwartete Ausgabe:**
|
||||
```
|
||||
✅ Google OAuth konfiguriert
|
||||
```
|
||||
|
||||
Falls Sie sehen:
|
||||
```
|
||||
⚠️ Google OAuth nicht konfiguriert (GOOGLE_CLIENT_ID/SECRET fehlen)
|
||||
```
|
||||
|
||||
Dann fehlen die Credentials in der `.env` Datei.
|
||||
|
||||
## Verwendung
|
||||
|
||||
### Frontend - Login-Button
|
||||
|
||||
Auf der Login-Seite erscheint automatisch:
|
||||
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ Mit Google anmelden │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
**Workflow:**
|
||||
1. Benutzer klickt auf "Mit Google anmelden"
|
||||
2. Redirect zu Google OAuth
|
||||
3. Benutzer wählt Google-Account
|
||||
4. Google Callback → Backend
|
||||
5. Backend erstellt/findet Benutzer
|
||||
6. Redirect zu Frontend mit Token
|
||||
7. Automatischer Login ✅
|
||||
|
||||
### Backend - API-Endpunkte
|
||||
|
||||
```bash
|
||||
# OAuth Flow starten
|
||||
GET /api/auth/google
|
||||
|
||||
# OAuth Callback (von Google aufgerufen)
|
||||
GET /api/auth/google/callback
|
||||
|
||||
# OAuth-Identities abrufen (geschützt)
|
||||
GET /api/auth/identities
|
||||
Authorization: Bearer <token>
|
||||
|
||||
# OAuth-Provider entfernen (geschützt)
|
||||
DELETE /api/auth/identity/:provider
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
## Datenbank-Struktur
|
||||
|
||||
### auth_identity Tabelle
|
||||
|
||||
```sql
|
||||
CREATE TABLE `auth_identity` (
|
||||
`id` bigint PRIMARY KEY AUTO_INCREMENT,
|
||||
`version` int NOT NULL DEFAULT 0,
|
||||
`auth_info_id` bigint,
|
||||
`provider` varchar(64) NOT NULL, -- 'google', 'github', etc.
|
||||
`identity` varchar(512) NOT NULL, -- Google User ID
|
||||
UNIQUE KEY (`provider`, `identity`)
|
||||
);
|
||||
```
|
||||
|
||||
**Beispiel-Daten:**
|
||||
```
|
||||
id | auth_info_id | provider | identity
|
||||
1 | 5 | google | 123456789012345678901
|
||||
```
|
||||
|
||||
## Szenarien
|
||||
|
||||
### Szenario 1: Neuer Benutzer mit Google
|
||||
|
||||
1. Benutzer klickt "Mit Google anmelden"
|
||||
2. Google OAuth Flow
|
||||
3. **Neuer Benutzer wird erstellt:**
|
||||
- `user` Tabelle: Name aus Google-Profil
|
||||
- `auth_info` Tabelle: E-Mail, kein Passwort
|
||||
- `auth_identity` Tabelle: Google ID
|
||||
4. JWT Token wird generiert
|
||||
5. Benutzer ist eingeloggt
|
||||
|
||||
### Szenario 2: Bestehender Benutzer (E-Mail-Match)
|
||||
|
||||
1. Benutzer hat Account mit `test@gmail.com`
|
||||
2. Login mit Google (`test@gmail.com`)
|
||||
3. **Accounts werden verknüpft:**
|
||||
- `auth_identity` wird hinzugefügt
|
||||
- Benutzer kann jetzt mit Passwort ODER Google einloggen
|
||||
|
||||
### Szenario 3: Mehrere OAuth-Provider
|
||||
|
||||
Ein Benutzer kann mehrere OAuth-Provider verknüpfen:
|
||||
|
||||
```
|
||||
auth_identity:
|
||||
id | auth_info_id | provider | identity
|
||||
1 | 5 | google | google_id_123
|
||||
2 | 5 | github | github_id_456
|
||||
```
|
||||
|
||||
Login möglich mit:
|
||||
- ✅ E-Mail + Passwort
|
||||
- ✅ Google Account
|
||||
- ✅ GitHub Account
|
||||
|
||||
## Sicherheit
|
||||
|
||||
### Token-Handling
|
||||
|
||||
- OAuth Access-Token wird NICHT gespeichert
|
||||
- Nur Provider-ID in `auth_identity`
|
||||
- JWT Token wie bei normalem Login
|
||||
- Gleiche 24h Gültigkeit
|
||||
|
||||
### Account-Verknüpfung
|
||||
|
||||
- E-Mail-Match automatisch
|
||||
- Verhindert doppelte Accounts
|
||||
- Sicher durch unique constraint
|
||||
|
||||
### Rückgängig machen
|
||||
|
||||
Benutzer kann OAuth-Verknüpfung entfernen:
|
||||
|
||||
```bash
|
||||
DELETE /api/auth/identity/google
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
## Produktion
|
||||
|
||||
### 1. Google Cloud Console
|
||||
|
||||
**Authorized JavaScript origins:**
|
||||
```
|
||||
https://ihre-domain.de
|
||||
```
|
||||
|
||||
**Authorized redirect URIs:**
|
||||
```
|
||||
https://ihre-domain.de/api/auth/google/callback
|
||||
```
|
||||
|
||||
### 2. .env für Produktion
|
||||
|
||||
```env
|
||||
NODE_ENV=production
|
||||
FRONTEND_URL=https://ihre-domain.de
|
||||
|
||||
GOOGLE_CLIENT_ID=ihre-prod-client-id
|
||||
GOOGLE_CLIENT_SECRET=ihr-prod-secret
|
||||
GOOGLE_CALLBACK_URL=https://ihre-domain.de/api/auth/google/callback
|
||||
```
|
||||
|
||||
### 3. HTTPS erforderlich
|
||||
|
||||
⚠️ **Google OAuth erfordert HTTPS in Produktion!**
|
||||
|
||||
## Weitere OAuth-Provider
|
||||
|
||||
### GitHub
|
||||
|
||||
```javascript
|
||||
// backend/src/config/passport.js
|
||||
const GitHubStrategy = require('passport-github2').Strategy;
|
||||
|
||||
passport.use(new GitHubStrategy({
|
||||
clientID: process.env.GITHUB_CLIENT_ID,
|
||||
clientSecret: process.env.GITHUB_CLIENT_SECRET,
|
||||
callbackURL: process.env.GITHUB_CALLBACK_URL
|
||||
}, async (accessToken, refreshToken, profile, done) => {
|
||||
const result = await oauthService.authenticateWithProvider(profile, 'github');
|
||||
done(null, result);
|
||||
}));
|
||||
```
|
||||
|
||||
### Microsoft
|
||||
|
||||
```javascript
|
||||
const MicrosoftStrategy = require('passport-microsoft').Strategy;
|
||||
// ... ähnlich wie Google
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Google OAuth nicht konfiguriert"
|
||||
|
||||
- Prüfen Sie `.env` Datei
|
||||
- `GOOGLE_CLIENT_ID` und `GOOGLE_CLIENT_SECRET` gesetzt?
|
||||
- Backend neu starten
|
||||
|
||||
### "redirect_uri_mismatch"
|
||||
|
||||
- Callback-URL in Google Console prüfen
|
||||
- Muss EXAKT übereinstimmen mit Backend-URL
|
||||
- http vs https beachten
|
||||
|
||||
### "access_denied"
|
||||
|
||||
- Benutzer hat OAuth abgelehnt
|
||||
- Test-User in Google Console hinzufügen (Development)
|
||||
|
||||
### OAuth-Button erscheint nicht
|
||||
|
||||
- Frontend HMR reload: `Ctrl+R`
|
||||
- Browser-Cache leeren
|
||||
- Prüfen Sie Console auf Fehler
|
||||
|
||||
## Testing
|
||||
|
||||
### 1. Lokales Testing
|
||||
|
||||
```bash
|
||||
# Backend
|
||||
curl http://localhost:3010/api/auth/google
|
||||
# → Sollte zu Google redirecten
|
||||
|
||||
# Nach Callback
|
||||
curl http://localhost:3010/api/auth/me \
|
||||
-H "Authorization: Bearer <oauth_token>"
|
||||
```
|
||||
|
||||
### 2. Manuelle Verknüpfung testen
|
||||
|
||||
```bash
|
||||
# Als eingeloggter Benutzer
|
||||
curl http://localhost:3010/api/auth/identities \
|
||||
-H "Authorization: Bearer <token>"
|
||||
|
||||
# Response:
|
||||
{
|
||||
"success": true,
|
||||
"identities": [
|
||||
{
|
||||
"provider": "google",
|
||||
"identity": "123456789012345678901",
|
||||
"id": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
✅ **Implementiert:**
|
||||
- Google OAuth 2.0 Login
|
||||
- Automatische Account-Verknüpfung
|
||||
- `auth_identity` Tabelle Nutzung
|
||||
- Mehrere OAuth-Provider möglich
|
||||
- Sicheres Token-Handling
|
||||
|
||||
✅ **Ready für:**
|
||||
- Google Login
|
||||
- GitHub Login (vorbereitet)
|
||||
- Microsoft Login (vorbereitet)
|
||||
|
||||
🚀 **Einfach zu erweitern** für weitere Provider!
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user