Search code examples
angulartypescriptangular6angular-router-guards

Angular 6 guards blocking even when it shoundn't


I'm having a problem with angular 6 route guard. When I hit the login button, it won't redirect me to the intended route. My html calls the login() function, while the loginService.isAutenticated returns true when the doLogin() method is executed, it returns false in the guard itself.

loginComponent.ts

import { Component, OnInit } from '@angular/core';
import { User } from '../common/user.model';
import { LoginService } from './login.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css'],
  providers: [LoginService]
})
export class LoginComponent implements OnInit {

  private usuario: User = new User();
  msg: string;

  constructor(private service: LoginService) { }

  ngOnInit() {
  }

  login() {
   this.service.fazerLogin(this.usuario);
  }

  limpar() {
    this.usuario.nome = '';
    this.usuario.senha = '';
  }

}

loginService.ts

import { Injectable } from '@angular/core';
import { User } from '../common/user.model';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Router } from '@angular/router';


@Injectable()
export class LoginService {

  url = 'api';
  constructor(private http: HttpClient,
              private router: Router
             ) { }

  isAuthenticated = false;

  doLogin(user: User) {

    if (user.name === 'admin' && user.pass === 'admin') {
      this.isAuthenticated = true;
      this.router.navigate(['/principal']);

    } else {
      console.log('Auth Failed');
    }
  }

  userIsAuthenticated() {
    return this.isAuthenticated;
  }
}

app.routes.ts

import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { PrincipalComponent } from './principal/principal.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { PendenciasComponent } from './pendencias/pendencias.component';
import { TesteComponent } from './teste/teste.component';
import { AuthGuard } from './guards/auth.guard';

const appRoutes: Routes = [
    { path: '', component: LoginComponent},
    { path: 'login', component: LoginComponent },
    { path: 'principal', component: PrincipalComponent,
      canActivate: [AuthGuard],
      children: [
        { path: 'pendencias', component: PendenciasComponent,
          canActivate: [AuthGuard]
        },
        { path: 'teste', component: TesteComponent,
          canActivate: [AuthGuard]
        },

      ]
    },
    { path: '**', component: PageNotFoundComponent },
  ];

export const routing = RouterModule.forRoot(appRoutes);

auth.guard.ts

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, CanActivateChild, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { LoginService } from '../login/login.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  constructor (private loginService: LoginService,
               private router: Router
              ) {}


  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | boolean {
      // if (this.loginService.usuarioEstaAutenticado()) {
      if (this.loginService.isAuthenticated) {
        console.log('canActivate retornou true');

        return true;
      }
      this.router.navigate(['/login']);
      console.log(this.loginService.isAuthenticated);

      console.log('canActivate retornou false');
      return false;

  }
}

Solution

  • Don't make the loginService be provided by the component if you need to inject it in the auth guard also. If you do that, your service will be not singleton and I think here you expect the instance to be shared between the component and the guard. Make the LoginService provided by the Module