I'm new to angular and i'm trying to implementate a login functionality.
The problem is that after my user hits login it should storage the token and then redirect to the Home page, but the canActivate returns false.
Obs: I'm using observable cuz i need to hide my navBar in the login page, and the best way that i found is by using *ngIf and getting the value of isLoggedIn observable.
AuthService.ts
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Router } from "@angular/router";
import { ToastrService } from "ngx-toastr";
import { BehaviorSubject, Observable, Subject } from "rxjs";
import { BaseService } from "./base.service";
@Injectable()
export class AuthService extends BaseService{
private loggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
get isLoggedIn(){
return this.loggedIn.asObservable();
}
constructor(http: HttpClient, private router : Router, private toastr : ToastrService) {
super(http);
}
login(body: any){
return this.post('User/login', body).subscribe(
(res: any) => {
localStorage.setItem('token', res.token);
this.loggedIn.next(true);
this.router.navigate(['/home']);
},
err => {
if (err.status)
this.toastr.error('FAIL!.');}
)
}
logout(){
console.log(this.isLoggedIn)
this.loggedIn.next(false);
localStorage.removeItem('token');
this.router.navigate(['/login']);
}
}
home.component.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from '../services/auth.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
isLoggedIn$!: Observable<boolean> | Promise<boolean> | boolean;
constructor(private router : Router, private authService : AuthService) { }
ngOnInit(): void {
this.isLoggedIn$ = this.authService.isLoggedIn;
}
onLogout(){
this.authService.logout();
}
}
auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, CanActivateChild } from '@angular/router';
import { ToastrService } from 'ngx-toastr';
import { Observable } from 'rxjs';
import { map, take } from 'rxjs/operators';
import { AuthService } from '../services/auth.service';
@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild {
constructor(private router: Router, private toastr : ToastrService, private authService : AuthService) {
}
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
return this.authService.isLoggedIn.pipe(
take(1),
map((isLoggedIn: boolean) => {
if (!isLoggedIn) {
this.router.navigate(['/login']);
this.toastr.error("User not loged in!");
return false;
}
return true;
})
);
}
}
app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth/auth.guard';
const routes: Routes = [
{
path: '',
redirectTo: "/login",
pathMatch: 'full'
},
{
path: 'home', canActivate: [AuthGuard],
loadChildren: () => import('./home/home.module').then(m => m.HomeModule)
},
{
path: 'login',
loadChildren: () => import('./login/login.module').then(m => m.LoginModule)
},
{
path: 'registration',
loadChildren: () => import('./registration/registration.module').then(m => m.RegistrationModule)
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }