When I login API sends to me the token and token-life-time , when token-life-time is going to be end , I refresh my token by sending request to API and receive new token and new refresh-token-time.
When I refresh or navigate to another page (at the moment when token-life-time is over) my interceptor sends old value of token from LocalStorage
and API gives me an error 'Not correct token' when I again refresh or navigate to another page it sends correct token.
But it repeats when the token-life-time is going to be over as described above.
Here is my token-interceptor.service.ts
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { LoginService } from '../services/login.service';
@Injectable()
export class TokenInterceptorService implements HttpInterceptor {
constructor(
private loginService: LoginService
) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (
this.loginService.isLogged
) {
const token = localStorage.getItem('access-token');
const headers = new HttpHeaders().set('Authorization', `Bearer ${token}`);
request = request.clone({ headers: headers });
}
return next.handle(request);
}
}
It takes token and send request to API.
I have the login.service.ts
with login and refresh function .Login function put token value into the LocalStorage
and Refresh function refreshes the token in LocalStorage
if isNeedToRefresh
var is true and it works well.
refresh(): Observable<boolean> {
return this.http.post(`${environment.auth}/refresh`, {
token_hash: localStorage.getItem('refresh-token')
}).pipe(
map((res: any) => {
if (res.access && res.refresh) {
localStorage.setItem('access-token', res.access.hash);
localStorage.setItem('expires-at-access', res.access.expires_at);
localStorage.setItem('refresh-token', res.refresh.hash);
localStorage.setItem('expires-at-refresh', res.refresh.expires_at);
return true;
} else {
this.notificationService.error(res && res.result_descr || '');
return false;
}
}),
catchError(() => of(false))
);
}
Here is where I refresh the token in login.component.ts
ngOnInit() {
if (this.loginService.isLogged) {
if (this.loginService.isNeedToRefresh === true) {
this.loginService.refresh().subscribe((res: boolean) => {
if (res === true) {
this.router.navigate(['']);
}
});
} else if (this.loginService.isNeedToRefresh === false) {
this.router.navigate(['']);
}
}
}
Also I update my token in app.component.ts
ngOnInit() {
$(document).on('click', '[href="#"]', e => e.preventDefault());
this.router.events.subscribe((val) => {
if (val instanceof NavigationEnd) {
if (!(val.url.indexOf('/login') === 0)) {
this.authWatcher();
}
}
});
}
authWatcher() {
if (this.loginService.isLogged) {
if (this.loginService.isNeedToRefresh === true) {
this.loginService.refresh().subscribe((refresh: boolean) => {
if (refresh === false) {
this.authModalRef = this.modalService.show(this.staticModal, { backdrop: 'static' });
} else {
this.loginService.checkToken().subscribe((check: boolean) => {
if (!check) {
this.logoutService.logout();
this.router.navigate(['login']);
}
});
}
});
}
}
What's the best way for my interceptor to work well ?
Little update , here is how I check isNeedToRefresh
get isNeedToRefresh(): boolean {
const accessExpireTimestamp = new Date(
localStorage.getItem('expires-at-access')
).getTime();
const refreshExpireTimestamp = new Date(
localStorage.getItem('expires-at-refresh')
).getTime();
const nowTimestamp = new Date().getTime();
if (nowTimestamp >= accessExpireTimestamp) {
if (nowTimestamp >= refreshExpireTimestamp) {
return null; // Refresh token expired
} else {
return true; // Refresh token not expired
}
}
return false;
}