I am confronted with the following issue: the personal section which is protected via an AuthGuard Service is loaded twice when I navigate to it or by browser refresh. Second time it strips away the query parameters of the URL if I provide any. Here is my app router configuration:
const routes: Routes = [
{
path: 'search',
redirectTo: '',
pathMatch: 'full'
},
{
path: '',
component: BookmarksComponent
},
{
path: 'tagged/:tag',
component: TagComponent
},
{
path: 'about',
component: AboutComponent
},
{
path: 'personal',
loadChildren: 'app/personal/personal-bookmarks.module#PersonalBookmarksModule'
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
and the child router configuration
@NgModule({
imports: [RouterModule.forChild([
{
path: '',
component: PersonalBookmarksComponent,
canActivate: [AuthGuard],
children: [
{
path: '',
component: PersonalBookmarksListComponent
},
{
path: 'new',
component: NewPersonalBookmarkFormComponent
},
{
path: 'bookmarks/:id',
component: PersonalBookmarkDetailComponent
}
]
}
])],
exports: [RouterModule]
})
export class PersonalBookmarksRoutingModule {}
The AuthGuard Service (whereby if it only returns true is the same behaviour):
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private keycloakService: KeycloakService) {}
canActivate() {
console.log('AuthGuard#canActivate called');
if (this.keycloakService.isLoggedIn()) {
return true;
} else {
this.keycloakService.login();
}
}
}
And the Navbar template:
<nav class="navbar navbar-light bg-faded" id="navbar">
<a class="navbar-brand" [routerLink]="['']" routerLinkActive="active">
<img src="assets/logo.png" width="35" height="35" class="d-inline-block align-top" alt="">
Public Bookmarks
</a>
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link" [routerLink]="['personal']" routerLinkActive="active">Personal list</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['about']" routerLinkActive="active">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://www.codingpedia.org/tags/#codingmarks" target="_blank">Blog</a>
</li>
<li *ngIf="isLoggedIn else notLoggedIn" class="nav-item">
<a class="nav-link" (click)="logout()">Logout <i class="fa fa-lock"></i></a>
</li>
<ng-template #notLoggedIn>
<li *ngIf="!keycloakService.isLoggedIn()" class="nav-item">
<a class="nav-link" (click)="login()">Login <i class="fa fa-unlock"></i></a>
</li>
</ng-template>
</ul>
</nav>
The project is available on Github and the faulty behaviour can be tested at https://www.codingmarks.org/personal by logging in with username/pwd - [email protected]/Test_user1$
UPDATE Even if I remove PersonalBookmarksComponent and move AuthGuard to the PersonalBookmarks module the wrong behaviour still persist... The routes for PersonalBookmarksModule look something like the following:
const personalBookmarksRoutes: Routes = [
{
path: 'search',
redirectTo: '',
pathMatch: 'full'
},
{
path: '',
component: PersonalBookmarksListComponent,
canActivate: [AuthGuard],
},
{
path: 'new',
component: NewPersonalBookmarkFormComponent
},
{
path: 'bookmarks/:id',
component: PersonalBookmarkDetailComponent
}
];
UPDATE2: The stripping away of the query parameters was due to the redirection forced when logging in with Keycloak.
False:
public login(): Promise<any> {
let options: any;
options = {redirectUri: environment.HOST + 'personal'};
return new Promise<any>((resolve, reject) => {
KeycloakService.auth.login(options)
.success(resolve)
.error(reject);
});
}
Correct:
public login(): Promise<any> {
return new Promise<any>((resolve, reject) => {
KeycloakService.auth.login()
.success(resolve)
.error(reject);
});
}
The reason the routes are being loaded twice is because you have specified the router path to load two components when you go to navigate to this ' '
route .
change the router configuration to
@NgModule({
imports: [RouterModule.forChild([
{
path: '',
//component: PersonalBookmarksComponent, //either remove this component line completely [best way is to remove this component deceleration]
canActivate: [AuthGuard],
children: [
{
path: '', // or specify a different route to this better use a redirect option on path
component: PersonalBookmarksListComponent
},
{
path: 'new',
component: NewPersonalBookmarkFormComponent
},
{
path: 'bookmarks/:id',
component: PersonalBookmarkDetailComponent
}
]
}
])],
exports: [RouterModule]
})
U can perform the following two steps:
I believe this approach will solve your problem.
The guard is being called twice once for your component and once for your children component.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With