0
votes

im starting to work with Angular, and im trying to create a simple route guard, to redirect user to login page, if my service return unauthorized.

To do that i created this route schema ->

const routes: Routes = [
  {
    path: '',
    component: LoggedComponent,
    children: [
      {path: '', component: HomeComponent}
    ],
    canActivate: [RouteGuard]
  },
  {
    path: '',
    component: AuthComponent,
    children: [
      {path: '', redirectTo: '/login', pathMatch: 'full'},
      {path: 'login', component: LoginComponent},
      {path: 'signin', component: SigninComponent}
    ]
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

And this is my guard service -> PS: Im setting a default value false.

import {Subject, Observable} from 'rxjs';

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

  authorized: Subject<boolean> = new Subject();

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): boolean {
    this.setObservable(false)
    return false;

  }

  getObservable(): Observable<boolean> {
    console.log(`starts to observe`)
    return this.authorized.asObservable();
  }

  setObservable(newState: boolean) {
    console.log(`new observable state: ${newState}`)
    this.authorized.next(newState)
  }
  
}

Ok, since the value is returning false as default, I expect the route to be automatically redirected to the AuthComponent, because Auth is the second option at my routes[]. Right?

So...

At the AuthComponent i stated to observe the authorized status:

import {RouteGuard} from '@acn-collections-ws/shared';

@Component({
  selector: 'acn-collections-ws-auth',
  templateUrl: './auth.component.html',
  styleUrls: ['./auth.component.scss']
})
export class AuthComponent implements OnInit {

  constructor(private guard: RouteGuard, router: Router) { 
    console.log('im here');
    this.guard.getObservable().subscribe(authorized => {
    })
  }

  ngOnInit(): void {
  }

}

But AuthComponent dosent load. it seems that when the canActivate parameter returns false, it does not go to the AuthComponent, it does not load anything. When the authorized (canActivate) returns true, it runs normally. Has anyone had a similar problem and can help me?

1

1 Answers

0
votes

This is how I do it when authenticating using Firebase:

export class GuardGuard implements CanActivate {

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

  async canActivate() {

    const user = await this.authService.isLogged();

    if(user){
      return true;
    }
    else {
      this.router.navigate(['login']);
      return false;
    }

  }

}

If the user's logged return true so it loads the requested route if not redirects to the login route and return false.

And this is the routing:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginComponent } from './modules/login/pages/login/login.component';
import { SignupComponent } from './modules/login/pages/signup/signup.component';
import { HeroComponent } from './shared/components/hero/hero.component';
import { NotFoundComponent } from './shared/components/not-found/not-found.component';
import { GuardGuard } from './shared/guards/guard.guard';

const routes: Routes = [
  { path: 'home', component: HeroComponent },
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'signup', component: SignupComponent },
  { path: 'login', component: LoginComponent },
  { path: 'tasks', loadChildren: ()=> import('./modules/task/task.module').then(m => m.TaskModule), canActivate: [GuardGuard] },
  { path: 'profile', loadChildren: ()=> import('./modules/user/user.module').then(m => m.UserModule), canActivate: [GuardGuard] },
  { path: '**', component: NotFoundComponent }
];