I have a problem. So, I want to create a route guard in Angular that doesn't allow the user to reach login page if he is logged in. I check if he is logged in if the BehaviourSubject from the AuthService emits a new user object, but when I type in the search bar the URL of the login page, the user object emitted by the subject become empty. Do you know why is this happening?
@Injectable({
providedIn: 'root'
})
export class LoggedInGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router){}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.user$.pipe(map(user => {
// check if the user object is empty
const isAuth = !(!!Object.keys(user).length);
console.log(isAuth)
if(isAuth) {
return true;
}
// navigate to /books if user is logged in
return this.router.createUrlTree(['/books']);
}));
}
}
Here is my AuthService logic:
export class AuthService {
private baseUsersUrl =
environment.firebase.databaseURL + MAIN_API_ENDPOINTS.users;
private userSource = new BehaviorSubject<User>(<User>{});
user$ = this.userSource.asObservable();
tokenExpirationTimer!: any;
constructor(private httpClient: HttpClient,private afAuth: AngularFireAuth, private router: Router) { }
login(email: string, password: string){
return this.httpClient.post<AuthResponseData>(MAIN_API_ENDPOINTS.login,{
email: email,
password: password,
returnSecureToken: true
}).pipe(
catchError(errorResponse => {
console.log(errorResponse);
let errorMessage = 'An unknown error occured!';
if(!errorResponse.error || !errorResponse.error.error) {
return throwError(errorMessage);
} else {
errorMessage = 'Email or password is incorrect'
}
return throwError(errorMessage);
}),
tap((resData) => {
this.saveUserData(email, resData.localId, resData.idToken, +resData.expiresIn);
}),
);
}
saveUserData(email: string, localId: string, idToken: string, expiresIn: number) {
const expirationDate = new Date(new Date().getTime() + expiresIn * 1000);
const currentUser: User = {
email,
id: localId,
token: idToken,
tokenExpirationDate: expirationDate
};
//token will expire in 1h
this.autoLogout(expiresIn * 1000);
document.cookie = 'token' + '=' + idToken;
}
autoLogin() {
const idToken = document.cookie.split('=')[1];
if(!idToken) {
return;
}
this.getUserData(idToken).subscribe((user) => {
this.saveUserData(user.users[0].email, user.users[0].localId, idToken, 100);
})
}
getUserData(idToken: string) {
return this.httpClient.post<any>(
MAIN_API_ENDPOINTS.userData,
{idToken: idToken});
}
And I added this route guard to the route this way:
const routes: Routes = [
{
path: 'login',
component: LoginComponent,
canActivate: [LoggedInGuard]
}]