2


I’m working on a web application using Angular and i came across a problem. There is an Authentication service that logs in a user. I’m sending a request to the server with the credentials and waiting for a response. The problem is that I try to navigate from the login component to the home component In the subscription of the responded

  login(formValues) {
    this.auth.logInUser(formValues.username, formValues.password)
    .subscribe(response =>{
      if(!response){
        this.invalidLogin=true;
      } else {
        this.router.navigate(['stream']);
      }
    })
  }

But every other component has a canActivateGuard that checks whether the current user is logged in (the data that i'm waiting from the server).

export const appRoutes: Routes = [
    {path: 'login', resolve: LiveStreamResolver, component: LoginComponent},
    {path: 'reports', component: ReportsComponent, resolve: LiveStreamResolver, canActivate: [AuthGuardService]},
    {path: 'calendar', component: CalendarComponent, resolve: LiveStreamResolver, canActivate: [AuthGuardService]},
    {path: 'stream', component: LiveStreamComponent},
    {path: '', redirectTo: 'login', pathMatch: 'full'}
];

constructor(public auth: AuthenticationService) { }

  canActivate(): boolean {
    return !!this.auth.currUser;
  }

Is there a way to resolve before the canActivate check is done? Is there any others solutions maybe?
Any other advises for how to guard the components would be welcomed :D

NVelichkovski
  • 31
  • 1
  • 7

2 Answers2

1

I came across the same issue and here is how I resolved it.

You can return Observable<boolean> from canActivate method. Try returning Observable instead of pure boolean.

Also, another option is, you can return promise.

Have a look at CanActivate.

Here is the code sample:

AuthenticationService

    @Injectable()
    export class AuthenticationService {

        private isAuthenticatedSubject = new ReplaySubject<boolean>(0);
        public isAuthenticated = this.isAuthenticatedSubject.asObservable();

    constructor() { }

    /* Call this method once user successfully logged in. It will update the isAuthenticatedSubject*/
    setAuth() {
       this.isAuthenticatedSubject.next(true);
     }

   }

AuthgaurdService

@Injectable()
export class AuthgaurdService implements CanActivate {

    constructor(
        private router: Router,
        private authService: AuthenticationService) { }

    canActivate(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): Observable<boolean> {
        // this will return Observable<boolean>
        return this.authService.isAuthenticated.pipe(take(1));
    }
}
Rukshan Dangalla
  • 2,500
  • 2
  • 24
  • 29
  • How do you control if the observable fails or user is not authenticated? The page hangs out / does nothing – Otto Apr 20 '19 at 11:27
0

You can use obervable , here is an exemple :

constructor(private authService: AuthService, private router: Router) {}

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
    if (this.authService.isLoggedIn()) {
        return true;
    }
    this.router.navigate(['/login']);
    return false;
}
willmaz
  • 2,376
  • 1
  • 20
  • 24