#136: EMail Auth on different browsers ...
This commit is contained in:
parent
162c5b042f
commit
097a6cb360
|
|
@ -20,21 +20,31 @@ export class AuthController {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Schritt 1: Hole den Benutzer anhand der E-Mail-Adresse
|
// Step 1: Get the user by email address
|
||||||
const userRecord = await this.firebaseAdmin.auth().getUserByEmail(email);
|
const userRecord = await this.firebaseAdmin.auth().getUserByEmail(email);
|
||||||
|
|
||||||
if (userRecord.emailVerified) {
|
if (userRecord.emailVerified) {
|
||||||
return { message: 'Email is already verified' };
|
// Even if already verified, we'll still return a valid token
|
||||||
|
const customToken = await this.firebaseAdmin.auth().createCustomToken(userRecord.uid);
|
||||||
|
return {
|
||||||
|
message: 'Email is already verified',
|
||||||
|
token: customToken,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schritt 2: Aktualisiere den Benutzerstatus
|
// Step 2: Update the user status to set emailVerified to true
|
||||||
// Hinweis: Wir können den oobCode nicht serverseitig validieren.
|
|
||||||
// Wir nehmen an, dass der oobCode korrekt ist, da er von Firebase generiert wurde.
|
|
||||||
await this.firebaseAdmin.auth().updateUser(userRecord.uid, {
|
await this.firebaseAdmin.auth().updateUser(userRecord.uid, {
|
||||||
emailVerified: true,
|
emailVerified: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
return { message: 'Email successfully verified' };
|
// Step 3: Generate a custom Firebase token for the user
|
||||||
|
// This token can be used on the client side to authenticate with Firebase
|
||||||
|
const customToken = await this.firebaseAdmin.auth().createCustomToken(userRecord.uid);
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: 'Email successfully verified',
|
||||||
|
token: customToken,
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(error.message || 'Failed to verify email', HttpStatus.BAD_REQUEST);
|
throw new HttpException(error.message || 'Failed to verify email', HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,35 @@
|
||||||
<div class="container mx-auto p-4 text-center min-h-screen bg-gray-100">
|
<div class="container mx-auto py-8 px-4 max-w-md">
|
||||||
|
<div class="bg-white p-6 rounded-lg shadow-md text-center">
|
||||||
|
<!-- Loading state -->
|
||||||
<ng-container *ngIf="verificationStatus === 'pending'">
|
<ng-container *ngIf="verificationStatus === 'pending'">
|
||||||
<p class="text-lg text-gray-600">Verifying your email...</p>
|
<div class="flex justify-center mb-4">
|
||||||
|
<div class="w-10 h-10 border-4 border-blue-500 border-t-transparent rounded-full animate-spin"></div>
|
||||||
|
</div>
|
||||||
|
<p class="text-gray-700">Verifying your email address...</p>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Success state -->
|
||||||
<ng-container *ngIf="verificationStatus === 'success'">
|
<ng-container *ngIf="verificationStatus === 'success'">
|
||||||
|
<div class="flex justify-center mb-4">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
<h2 class="text-2xl font-bold text-green-600 mb-5">Your email has been verified</h2>
|
<h2 class="text-2xl font-bold text-green-600 mb-5">Your email has been verified</h2>
|
||||||
<!-- <p class="text-gray-700 mb-4">You can now sign in with your new account</p> -->
|
<p class="text-gray-700 mb-4">You will be redirected to your account page in 5 seconds</p>
|
||||||
<a routerLink="/account" class="inline-block px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors">Follow this link to access your Account Page </a>
|
<a routerLink="/account" class="inline-block px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors"> Go to Account Page Now </a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Error state -->
|
||||||
<ng-container *ngIf="verificationStatus === 'error'">
|
<ng-container *ngIf="verificationStatus === 'error'">
|
||||||
<h2 class="text-2xl font-bold text-red-600 mb-2">Verification failed</h2>
|
<div class="flex justify-center mb-4">
|
||||||
<p class="text-gray-700">{{ errorMessage }}</p>
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-red-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h2 class="text-2xl font-bold text-red-600 mb-3">Verification Failed</h2>
|
||||||
|
<p class="text-gray-700 mb-4">{{ errorMessage }}</p>
|
||||||
|
<a routerLink="/login" class="inline-block px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors"> Return to Login </a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, RouterModule } from '@angular/router';
|
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { AuthService } from '../../services/auth.service';
|
import { AuthService } from '../../services/auth.service';
|
||||||
import { UserService } from '../../services/user.service';
|
import { UserService } from '../../services/user.service';
|
||||||
|
|
@ -16,7 +16,7 @@ export class EmailAuthorizedComponent implements OnInit {
|
||||||
verificationStatus: 'pending' | 'success' | 'error' = 'pending';
|
verificationStatus: 'pending' | 'success' | 'error' = 'pending';
|
||||||
errorMessage: string | null = null;
|
errorMessage: string | null = null;
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute, private http: HttpClient, private authService: AuthService, private userService: UserService) {}
|
constructor(private route: ActivatedRoute, private router: Router, private http: HttpClient, private authService: AuthService, private userService: UserService) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
const oobCode = this.route.snapshot.queryParamMap.get('oobCode');
|
const oobCode = this.route.snapshot.queryParamMap.get('oobCode');
|
||||||
|
|
@ -32,12 +32,32 @@ export class EmailAuthorizedComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private verifyEmail(oobCode: string, email: string): void {
|
private verifyEmail(oobCode: string, email: string): void {
|
||||||
this.http.post(`${environment.apiBaseUrl}/bizmatch/auth/verify-email`, { oobCode, email }).subscribe({
|
this.http.post<{ message: string; token: string }>(`${environment.apiBaseUrl}/bizmatch/auth/verify-email`, { oobCode, email }).subscribe({
|
||||||
next: async () => {
|
next: async response => {
|
||||||
this.verificationStatus = 'success';
|
this.verificationStatus = 'success';
|
||||||
//await this.authService.refreshToken();
|
|
||||||
await this.authService.refreshUserClaims();
|
try {
|
||||||
|
// Use the custom token from the server to sign in with Firebase
|
||||||
|
await this.authService.signInWithCustomToken(response.token);
|
||||||
|
|
||||||
|
// Try to get user info
|
||||||
|
try {
|
||||||
const user = await this.userService.getByMail(email);
|
const user = await this.userService.getByMail(email);
|
||||||
|
console.log('User retrieved:', user);
|
||||||
|
} catch (userError) {
|
||||||
|
console.error('Error getting user:', userError);
|
||||||
|
// Don't change verification status - it's still a success
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect to dashboard after a short delay
|
||||||
|
setTimeout(() => {
|
||||||
|
this.router.navigate(['/account']);
|
||||||
|
}, 5000);
|
||||||
|
} catch (authError) {
|
||||||
|
console.error('Error signing in with custom token:', authError);
|
||||||
|
// Keep success status for verification, but add warning about login
|
||||||
|
this.errorMessage = 'Email verified, but there was an issue signing you in. Please try logging in manually.';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
error: err => {
|
error: err => {
|
||||||
this.verificationStatus = 'error';
|
this.verificationStatus = 'error';
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
|
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
|
||||||
import { Injectable, inject } from '@angular/core';
|
import { Injectable, inject } from '@angular/core';
|
||||||
import { FirebaseApp } from '@angular/fire/app';
|
import { FirebaseApp } from '@angular/fire/app';
|
||||||
import { GoogleAuthProvider, UserCredential, createUserWithEmailAndPassword, getAuth, signInWithEmailAndPassword, signInWithPopup } from 'firebase/auth';
|
import { GoogleAuthProvider, UserCredential, createUserWithEmailAndPassword, getAuth, signInWithCustomToken, signInWithEmailAndPassword, signInWithPopup } from 'firebase/auth';
|
||||||
import { BehaviorSubject, Observable, catchError, firstValueFrom, map, of, shareReplay, take, tap } from 'rxjs';
|
import { BehaviorSubject, Observable, catchError, firstValueFrom, map, of, shareReplay, take, tap } from 'rxjs';
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
import { MailService } from './mail.service';
|
import { MailService } from './mail.service';
|
||||||
|
|
@ -274,4 +274,31 @@ export class AuthService {
|
||||||
return await this.refreshToken();
|
return await this.refreshToken();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add this new method to sign in with a custom token
|
||||||
|
async signInWithCustomToken(token: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
// Sign in to Firebase with the custom token
|
||||||
|
const userCredential = await signInWithCustomToken(this.auth, token);
|
||||||
|
|
||||||
|
// Store the authentication token
|
||||||
|
if (userCredential.user) {
|
||||||
|
const idToken = await userCredential.user.getIdToken();
|
||||||
|
localStorage.setItem('authToken', idToken);
|
||||||
|
localStorage.setItem('refreshToken', userCredential.user.refreshToken);
|
||||||
|
|
||||||
|
if (userCredential.user.photoURL) {
|
||||||
|
localStorage.setItem('photoURL', userCredential.user.photoURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load user role from the token
|
||||||
|
this.loadRoleFromToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error signing in with custom token:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue