89 lines
2.7 KiB
TypeScript
89 lines
2.7 KiB
TypeScript
import {EventEmitter, Injectable} from '@angular/core';
|
|
import {HttpClient, HttpHeaders} from "@angular/common/http";
|
|
import {catchError, Observable, of, tap} from "rxjs";
|
|
import {TokenResponse} from "@api/v1/tokenResponse";
|
|
import ApiService from "@api/api.service";
|
|
|
|
export enum AvailableAuthenticationProvider {
|
|
Bearer
|
|
}
|
|
|
|
export class AuthToken {
|
|
accessToken: string;
|
|
expiresIn: Date;
|
|
authProvider: AvailableAuthenticationProvider;
|
|
endpoint: string;
|
|
|
|
constructor(accessToken: string, expiresIn: Date, authProvider: AvailableAuthenticationProvider, refreshEndpoint: string) {
|
|
this.accessToken = accessToken;
|
|
this.expiresIn = expiresIn;
|
|
this.authProvider = authProvider;
|
|
this.endpoint = refreshEndpoint;
|
|
}
|
|
|
|
static httpHeader(token: AuthToken): HttpHeaders {
|
|
let header = new HttpHeaders();
|
|
|
|
if (token.authProvider === AvailableAuthenticationProvider.Bearer)
|
|
header = header.set('Authorization', `Bearer ${token.accessToken}`);
|
|
|
|
return header;
|
|
}
|
|
}
|
|
|
|
@Injectable({
|
|
providedIn: 'root',
|
|
})
|
|
export class AuthService {
|
|
public expireTokenChange = new EventEmitter<Date>();
|
|
public tokenChangeError = new EventEmitter();
|
|
|
|
constructor(private http: HttpClient) {
|
|
}
|
|
|
|
public static setToken(token: TokenResponse, provider: AvailableAuthenticationProvider, refreshEndpoint: string) {
|
|
localStorage.setItem(ApiService.tokenKey, JSON.stringify(
|
|
new AuthToken(token.accessToken, token.expiresIn, provider, refreshEndpoint)
|
|
));
|
|
}
|
|
|
|
public static get tokenExpiresIn(): Date {
|
|
const token = localStorage.getItem(ApiService.tokenKey);
|
|
|
|
if (!token)
|
|
return new Date();
|
|
|
|
const result = new Date((JSON.parse(token) as AuthToken).expiresIn);
|
|
return result <= new Date() ? new Date() : result;
|
|
}
|
|
|
|
public refreshToken(): Observable<TokenResponse> {
|
|
const token = localStorage.getItem(ApiService.tokenKey);
|
|
|
|
if (!token)
|
|
return of();
|
|
|
|
const authToken = JSON.parse(token) as AuthToken;
|
|
|
|
switch (authToken.authProvider) {
|
|
case AvailableAuthenticationProvider.Bearer:
|
|
return this.http.get<TokenResponse>(authToken.endpoint, {withCredentials: true})
|
|
.pipe(
|
|
catchError(error => {
|
|
this.tokenChangeError.emit();
|
|
throw error;
|
|
}),
|
|
tap(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);
|
|
}
|
|
})
|
|
);
|
|
}
|
|
}
|
|
}
|