Using Angular 2.4.8, I communicate with the backend via REST and need to include X-Auth-Token
in the header of each request. The token is stored in the session, and if it becomes outdated, the server returns a 401 status requiring the application to redirect to the login page.
To handle this, I implemented an HTTP interceptor in my project:
@Injectable()
export class HttpInterceptor extends Http {
constructor(backend: XHRBackend
, defaultOptions: RequestOptions
, private router: Router
) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
return super.request(url, options).catch((error: Response) => {
if ((error.status === 401 || error.status === 403) &&
(window.location.href.match(/\?/g) || []).length < 2) {
console.log('The authentication session expires.');
window.sessionStorage.removeItem('auth-token');
window.location.href = window.location.href + '/login';
return Observable.empty();
}
return Observable.throw(error);
});
}
}
This implementation works well but when using plain redirects instead of the router, the entire application reloads. To resolve this discrepancy, I modified the code:
// window.location.href = window.location.href + '/login';
this.router.navigate(['/login']);
However, the application fails to follow the link. How can I ensure the router navigates correctly?
Edit January 22, 2018
In my app-routing.module.ts
:
const routes: Routes = [
{
path: 'login',
component: LoginComponent,
resolve: {
boolean: InitResolverService
}
},
{
path: '**',
redirectTo: 'system'
}
];
@NgModule({
imports: [
RouterModule.forRoot(
routes
// , { enableTracing: true } // <-- debugging purposes only
)
],
exports: [
RouterModule
]
})
export class AppRoutingModule { }
The InitResolverService
includes logic for initial navigation and emits true
upon completion of the stream.
Additionally, in the LoginComponent
:
@Component({
selector: 'app-login',
templateUrl: 'login.component.html',
styleUrls: ['login.component.less']
})
export class LoginComponent implements OnInit {
private username: FormControl;
private password: FormControl;
public form: FormGroup;
public displayDialog = false;
isLoginButtonEnabled = true;
isResetButtonVisible = false;
constructor(
private authService: AuthenticationService,
private router: Router,
private route: ActivatedRoute,
private initService: InitResolverService
) {
this.username = new FormControl(Validators.required);
this.password = new FormControl(Validators.required);
this.form = new FormGroup({
Username: this.username,
Password: this.password
});
this.form.setValue({
Username: '',
Password: ''
});
this.displayDialog = true;
}
ngOnInit() {
this.initService.showSplash();
this.authService.canActivate(this.route.snapshot, this.router.routerState.snapshot).subscribe(x => {
if (x) {
this.router.navigate(['/']);
}
});
}
}