Reputation: 3761
This is my app-routing.module.ts
:
const routes: Routes = [
{ path: '', redirectTo: '/app/elements', pathMatch: 'full' },
{path: 'app', component:ElementsComponent, children:[
{ path: 'details/:id', component: ElementDetailComponent, canActivate:[AuthGuard]},
{ path: 'elements', component: ElementListComponent, canActivate:[AuthGuard] },
{ path: 'user/signup', component: SignupComponent },
{ path: 'user/login', component: LoginComponent },
{ path: 'user/logout', component: LogoutComponent }
]}
];
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ],
providers: [AuthGuard]
})
export class AppRoutingModule {}
As you can see for the path ''
I am redirecting to /app/elements
which is kind of my home page. This was working fine until I implemented the AuthGuard
which looks like:
@Injectable()
export class AuthGuard implements CanActivate{
public allowed: boolean;
constructor(private af: AngularFire, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
this.af.auth.subscribe((auth) => {
if(auth == null) {
this.router.navigate(['/app/user/login']);
this.allowed = false;
} else {
this.allowed = true;
}
});
return this.allowed;
}
}
Now, if the user is not logged in and goes to http://localhost:4200/
, the redirect works and it tries to go to http://localhost:4200/app/elements
, the guard detects the user is not logged in and it redirects to the login page.
The problem is if the user is logged in and tries to go to http://localhost:4200/
. In this case, nothing happens, the user stays at that URL with the page blank.
Why the redirect is not working in that case? Is there a way to fix that?
Upvotes: 1
Views: 1615
Reputation: 37343
the canActivate
returns before the firebase
observable resolves, so canActivate
will always return false, but canActivate
can return a promise or an Observable.
that should work :
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.af.auth
.map(auth => auth != null) // null means not authenticated
.do(isAuthenticated => { // change routes if not authenticated
if(!isAuthenticated) {
this.router.navigate(['/app/user/login']);
}
});
}
Upvotes: 4
Reputation: 1
You can use a service that keeps the the state of the authentication. After that just use a code without subscription. Because it's executed async and brakes the code.
public canActivate() {
if (this.authService.isAuthenticated)
return true;
this.router.navigate(['/app/user/login']);
return false;
}
Upvotes: 0