diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 6545c5f..012f122 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -4,7 +4,6 @@ import {FooterComponent} from "@component/common/footer/footer.component";
import localeRu from '@angular/common/locales/ru';
import {registerLocaleData} from '@angular/common';
import {FocusNextDirective} from "@/directives/focus-next.directive";
-import {TokenRefreshService} from "@service/token-refresh.service";
import {HeaderComponent} from "@component/common/header/header.component";
@Component({
@@ -17,8 +16,7 @@ import {HeaderComponent} from "@component/common/header/header.component";
`
})
export class AppComponent {
- constructor(tokenRefreshService: TokenRefreshService) {
+ constructor() {
registerLocaleData(localeRu);
- tokenRefreshService.startTokenRefresh();
}
}
diff --git a/src/services/auth.service.ts b/src/services/auth.service.ts
index 0b870a4..709cfa3 100644
--- a/src/services/auth.service.ts
+++ b/src/services/auth.service.ts
@@ -1,6 +1,6 @@
-import {EventEmitter, Injectable} from '@angular/core';
+import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders} from "@angular/common/http";
-import {Observable, tap} from "rxjs";
+import {map, Observable, throwError} from "rxjs";
import {TokenResponse} from "@api/v1/tokenResponse";
import ApiService from "@api/api.service";
@@ -21,7 +21,7 @@ export class AuthToken {
this.endpoint = refreshEndpoint;
}
- static httpHeader(token: AuthToken): HttpHeaders {
+ public static httpHeader(token: AuthToken): HttpHeaders {
let header = new HttpHeaders();
if (token.authProvider === AvailableAuthenticationProvider.Bearer)
@@ -35,8 +35,6 @@ export class AuthToken {
providedIn: 'root',
})
export class AuthService {
- public expireTokenChange = new EventEmitter();
-
constructor(private http: HttpClient) {
}
@@ -56,12 +54,12 @@ export class AuthService {
return result <= new Date() ? new Date() : result;
}
- public refreshToken(): Observable {
+ public refreshToken(): Observable {
const token = localStorage.getItem(ApiService.tokenKey);
console.log(token);
if (!token)
- throw new Error("token is not found");
+ return throwError(() => new Error("Token is not found"));
const authToken = JSON.parse(token) as AuthToken;
@@ -69,14 +67,16 @@ export class AuthService {
case AvailableAuthenticationProvider.Bearer:
return this.http.get(authToken.endpoint, {withCredentials: true})
.pipe(
- tap(response => {
+ map(response => {
const newExpireDate = new Date(response.expiresIn);
const oldExpireDate = new Date(authToken.expiresIn);
if (newExpireDate.getTime() !== oldExpireDate.getTime()) {
AuthService.setToken(response, AvailableAuthenticationProvider.Bearer, authToken.endpoint);
- this.expireTokenChange.emit(newExpireDate);
+ return newExpireDate;
}
+
+ return newExpireDate;
})
);
}
diff --git a/src/services/token-refresh.service.ts b/src/services/token-refresh.service.ts
index 957f86d..2672d52 100644
--- a/src/services/token-refresh.service.ts
+++ b/src/services/token-refresh.service.ts
@@ -1,4 +1,4 @@
-import {BehaviorSubject, filter, interval, Subscription, switchMap} from "rxjs";
+import {BehaviorSubject, catchError, of, Subject, Subscription} from "rxjs";
import {Injectable} from "@angular/core";
import {AuthService} from "@service/auth.service";
import {environment} from "@environment";
@@ -8,64 +8,70 @@ import ApiService from "@api/api.service";
providedIn: 'root',
})
export class TokenRefreshService {
- private tokenRefreshSubscription: Subscription | undefined;
private tokenRefreshing$ = new BehaviorSubject(false);
+ private refreshTokenTimeout: any;
private refreshTokenExpireMs: number = environment.retryDelay;
constructor(private authService: AuthService) {
- this.setRefreshTokenExpireMs(AuthService.tokenExpiresIn.getTime() - 1000 - Date.now());
-
- authService.expireTokenChange.subscribe(date => {
- console.debug('Expire token change event received:', date);
- this.setRefreshTokenExpireMs(date.getTime() - 1000 - Date.now());
- });
+ this.setRefreshTokenExpireMs(AuthService.tokenExpiresIn);
}
- public startTokenRefresh(date: Date | null = null): void {
- if (date)
- this.refreshTokenExpireMs = new Date(date).getTime() - 1000 - Date.now();
+ private startTokenRefresh(): void {
+ this.refreshTokenTimeout = setTimeout(() => {
+ this.refreshToken();
- console.debug(this.tokenRefreshSubscription);
- if (this.tokenRefreshSubscription && !this.tokenRefreshSubscription.closed)
+ if (this.refreshTokenExpireMs > 0)
+ this.startTokenRefresh();
+ }, this.refreshTokenExpireMs);
+ }
+
+ private refreshToken(): void {
+ if (this.tokenRefreshing$.value) {
+ console.warn('Refreshing token was started...');
return;
+ }
- this.tokenRefreshSubscription = interval(this.refreshTokenExpireMs).pipe(
- filter(isRefreshing => !isRefreshing),
- switchMap(() => {
- this.tokenRefreshing$.next(true);
- console.debug('Send query to refresh token');
- return this.authService.refreshToken();
- })
- ).subscribe({
- next: (_) => {
+ console.log('Start Refreshing token...');
+ this.tokenRefreshing$.next(true);
+
+ this.authService.refreshToken()
+ .pipe(
+ catchError(error => {
+ console.warn('Error refreshing token', error);
+ localStorage.removeItem(ApiService.tokenKey);
+ this.refreshTokenExpireMs = -1;
+ return of(undefined);
+ }))
+ .subscribe(data => {
+ if (data) {
+ console.log('Token refreshed');
+ this.setRefreshTokenExpireMs(data);
+ }
this.tokenRefreshing$.next(false);
- },
- error: error => {
- this.tokenRefreshing$.next(false);
- localStorage.removeItem(ApiService.tokenKey);
- }
- });
+ console.log('Token refresh process completed');
+ });
}
- public getTokenRefreshing$(): BehaviorSubject {
+ public getTokenRefreshing$(): Subject {
return this.tokenRefreshing$;
}
- public stopTokenRefresh(): void {
- if (this.tokenRefreshSubscription && !this.tokenRefreshSubscription.closed) {
- this.tokenRefreshSubscription.unsubscribe();
- this.tokenRefreshSubscription = undefined;
- }
- }
+ public setRefreshTokenExpireMs(expireMs: number | string | Date | null = null): void {
+ let expireMsNumber: number;
+ if (expireMs === null)
+ expireMsNumber = -1;
+ else if (expireMs instanceof Date || typeof expireMs === 'string')
+ expireMsNumber = new Date(expireMs).getTime() - 1000 - Date.now();
+ else
+ expireMsNumber = expireMs;
- public setRefreshTokenExpireMs(expireMs: number): void {
- if (expireMs < environment.retryDelay)
- expireMs = environment.retryDelay;
+ if (expireMsNumber < environment.retryDelay)
+ expireMsNumber = environment.retryDelay;
- this.refreshTokenExpireMs = expireMs;
+ this.refreshTokenExpireMs = expireMsNumber;
+ console.log('New refresh token interval:', this.refreshTokenExpireMs);
- console.log(expireMs);
- this.stopTokenRefresh();
+ clearTimeout(this.refreshTokenTimeout);
this.startTokenRefresh();
}
}