Using Asp Core on Angular 4 with the default template from asp core. The guard works, but on page refresh I get unwanted behavior. When refreshing a guarded route it briefly shows my login page when canActivate
is true
. Image below shows this behavior. Notice on refresh the screen flashes red (my login page).
Steps to reproduce issue:
- Create project with
dotnet new angular
- Run the
dotnet restore
andnpm install
- Add file
auth.guard.ts
(code below) - Add file
auth.service.ts
(code below) - Add login component
- Add service and guard to routes in
app.modal.shared.ts
(code below) - Add login button on home component
- Run program and click login button
- Navigate to the counter route
- Press F5 to refresh, the login page will appear before showing counter route (should not show login page as
canActivate
should betrue
)
Please let me know if you wish to see any additional code or if you have any questions. I have been pulling my hair out the past two days trying all kinds of things with Observables, maps and subscriptions with no results. Any help will be greatly appreciated. Thanks in advance!
auth.guard.ts
import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router'
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
private authService: AuthService,
private router: Router) {
}
canActivate() {
if (!this.authService.isLoggedIn()) {
this.router.navigate(['/login']);
return false;
}
return true;
}
}
auth.service.ts
import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
import { Router } from '@angular/router';
import { Response, Headers, RequestOptions } from '@angular/http';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
import { Observable } from 'rxjs/Rx';
import { BehaviorSubject } from 'rxjs/Rx';
@Injectable()
export class AuthService {
private baseUrl: string = '';
private loggedIn = false;
uid: string | null;
constructor(
private router: Router,
@Inject(PLATFORM_ID) private platformId: Object
) {
if (isPlatformBrowser(this.platformId)) {
this.loggedIn = !!localStorage.getItem('auth_token');
}
}
login() {
this.loggedIn = true;
localStorage.setItem('auth_token', 'test');
}
logout() {
localStorage.removeItem('auth_token');
localStorage.removeItem('uid');
window.location.replace('/home'); // redirect as we want all var and obj to reset
}
isLoggedIn() {
return this.loggedIn;
}
}
app.module.shared.ts
...
RouterModule.forRoot([
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'login', component: LoginComponent },
{ path: 'counter', component: CounterComponent, canActivate: [AuthGuard] },
{ path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthGuard] },
{ path: '**', redirectTo: 'home' }
])
...
EDIT: Added gif of issue.
EDIT: Found out this is an issue with server-side prerendering. I am currently looking into how to setup a token storage service and pass this to the server.