I installed two defenders in Angular 4 - one that redirects users to the login page when they try to get to the secure route, and one that redirects users to the welcome page from Home.
The guards themselves work great ... but I noticed a very strange behavior. Adding redirection through this.router.navigate
to GuardTraveler protects the application in a state where I cannot access protected routes from the first guard even after logging in. I just keep getting sent to the homepage.
Here are my guards:
export class AuthGuardLoggedInUser implements CanActivate {
private isLoggedIn: boolean;
private working: boolean;
constructor (@Inject(Store) private _store:Store<AppStore>, @Inject(Router) private _router: Router)
{
_store.select(state => state.AuthNState).subscribe(auth =>
{
this.isLoggedIn = auth.connected
this.working = auth.working
})
}
canActivate() {
if (this.working)
{
let promise: Promise<boolean> = new Promise((resolve, reject) => {
let sub = this._store.select(state => state.AuthNState).subscribe(auth =>
{
if (!auth.working) {
resolve(auth.connected)
sub.unsubscribe()
if (!auth.connected) this._router.navigate(['/i/login']);
}
})
});
return promise
}
else if (this.isLoggedIn){
return true
}
else {
this._router.navigate(['/i/login']);
}
export class WelcomeTraveler implements CanActivate {
private hasAlreadyVisitedWelcomePage: boolean;
private isLoggedIn: boolean;
private working: boolean;
constructor (@Inject(Store) private _store:Store<AppStore>, @Inject(Router) private _router: Router)
{
_store.select(state => state.AuthNState).subscribe(auth =>
{
this.isLoggedIn = auth.connected
this.working = auth.working
})
}
canActivate() {
if (this.working)
{
let promise: Promise<boolean> = new Promise((resolve, reject) => {
let sub = this._store.select(state => state.AuthNState).subscribe(auth =>
{
if (!auth.working) {
resolve(auth.connected)
sub.unsubscribe()
this.hasAlreadyVisitedWelcomePage = true
this._router.navigate(['/i/welcome']);
}
})
});
return promise
}
else if (this.isLoggedIn){
return true
}
else if (!this.hasAlreadyVisitedWelcomePage){
this.hasAlreadyVisitedWelcomePage = true
this._router.navigate(['/i/welcome']);
}
else return true
}
}
And here is a fragment of the routing table:
export var AppRoutes = RouterModule.forRoot([
{
path: '',
component: HomeComponent,
canActivate: [WelcomeTraveler]
}, {
path: 'i/getstarted',
component: GetStartedPageComponent,
canActivate: [AuthGuardLoggedInUser]
}, {
path: 'i/login',
component: LoginPageComponent
}, {
path: 'i/profile',
component: ProfilePageComponent,
canActivate: [AuthGuardLoggedInUser]
}, {
path: 'i/welcome',
component: WelcomePageComponent
}])
this.router.navigate
WelcomeTraveler
, , , ! "" ( ). , .
?