// auth.service.ts import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { Injectable, inject } from '@angular/core'; import { FirebaseApp } from '@angular/fire/app'; import { GoogleAuthProvider, UserCredential, createUserWithEmailAndPassword, getAuth, sendEmailVerification, signInWithEmailAndPassword, signInWithPopup } from 'firebase/auth'; import { firstValueFrom } from 'rxjs'; import { environment } from '../../environments/environment'; @Injectable({ providedIn: 'root', }) export class AuthService { private app = inject(FirebaseApp); private auth = getAuth(this.app); private http = inject(HttpClient); // Registrierung mit Email und Passwort async registerWithEmail(email: string, password: string): Promise { const userCredential = await createUserWithEmailAndPassword(this.auth, email, password); // E-Mail-Verifizierung senden if (userCredential.user) { await sendEmailVerification(userCredential.user); } // Token, RefreshToken und ggf. photoURL speichern const token = await userCredential.user.getIdToken(); localStorage.setItem('authToken', token); localStorage.setItem('refreshToken', userCredential.user.refreshToken); if (userCredential.user.photoURL) { localStorage.setItem('photoURL', userCredential.user.photoURL); } return userCredential; } // Login mit Email und Passwort loginWithEmail(email: string, password: string): Promise { return signInWithEmailAndPassword(this.auth, email, password).then(async userCredential => { if (userCredential.user) { const token = await userCredential.user.getIdToken(); localStorage.setItem('authToken', token); localStorage.setItem('refreshToken', userCredential.user.refreshToken); if (userCredential.user.photoURL) { localStorage.setItem('photoURL', userCredential.user.photoURL); } } return userCredential; }); } // Login mit Google loginWithGoogle(): Promise { const provider = new GoogleAuthProvider(); return signInWithPopup(this.auth, provider).then(async userCredential => { if (userCredential.user) { const token = await userCredential.user.getIdToken(); localStorage.setItem('authToken', token); localStorage.setItem('refreshToken', userCredential.user.refreshToken); if (userCredential.user.photoURL) { localStorage.setItem('photoURL', userCredential.user.photoURL); } } return userCredential; }); } // Logout: Token, RefreshToken und photoURL entfernen logout(): Promise { localStorage.removeItem('authToken'); localStorage.removeItem('refreshToken'); localStorage.removeItem('photoURL'); return this.auth.signOut(); } // Prüft, ob ein Token noch gültig ist (über die "exp"-Eigenschaft) private isTokenValid(token: string): boolean { try { const payloadBase64 = token.split('.')[1]; const payloadJson = atob(payloadBase64.replace(/-/g, '+').replace(/_/g, '/')); const payload = JSON.parse(payloadJson); const exp = payload.exp; const now = Math.floor(Date.now() / 1000); return exp > now; } catch (e) { return false; } } // Versucht, mit dem RefreshToken einen neuen Access Token zu erhalten async refreshToken(): Promise { const storedRefreshToken = localStorage.getItem('refreshToken'); if (!storedRefreshToken) { return null; } const apiKey = environment.firebaseConfig.apiKey; // Stelle sicher, dass dieser Wert in Deiner environment.ts gesetzt ist const url = `https://securetoken.googleapis.com/v1/token?key=${apiKey}`; const body = new HttpParams().set('grant_type', 'refresh_token').set('refresh_token', storedRefreshToken); const headers = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' }); try { const response: any = await firstValueFrom(this.http.post(url, body.toString(), { headers })); // response enthält z. B. id_token, refresh_token, expires_in etc. const newToken = response.id_token; const newRefreshToken = response.refresh_token; localStorage.setItem('authToken', newToken); localStorage.setItem('refreshToken', newRefreshToken); return newToken; } catch (error) { console.error('Error refreshing token:', error); return null; } } /** * Gibt einen gültigen Token zurück. * Falls der gespeicherte Token noch gültig ist, wird er zurückgegeben. * Ansonsten wird versucht, einen neuen Token mit dem RefreshToken zu holen. * Ist auch das nicht möglich, wird null zurückgegeben. */ async getToken(): Promise { const token = localStorage.getItem('authToken'); if (token && this.isTokenValid(token)) { return token; } else { return await this.refreshToken(); } } }