import { shareReplay, tap } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http'; import { Observable, of, Observer } from 'rxjs'; import { AuthTokenService } from './auth-token.service'; import { ConfigService } from '@arrow/bom/config'; export interface IPublicCertificate { alg: string; value: string; } export interface IAuthResult { access_token: string; token_type?: string; refresh_token?: string; expires_in?: number; } @Injectable() export class AuthService { constructor( private http: HttpClient, private authTokenService: AuthTokenService, private config: ConfigService ) {} private SERVICE_URL = `${this.config.getSecurityApi()}/oauth/token`; private _requestNewTokens(refreshToken): Observable { const body = new HttpParams() .set('grant_type', 'refresh_token') .set('refresh_token', refreshToken) .set('client_id', this.authTokenService.getClientId()); const headers = new HttpHeaders().set( 'Content-Type', 'application/x-www-form-urlencoded' ); return this.http.post(this.SERVICE_URL, body, { headers }); } /** * Request and Store the new access and refresh token in local storage */ private _requestAndSetTokensInLocalStorage(refreshToken: string) { return this._requestNewTokens(refreshToken).pipe( tap(newTokens => { this.authTokenService.setTokens(newTokens); return newTokens; }), shareReplay() ); } public checkAndRenewTokens(): Observable { const accessToken = this.authTokenService.getValidAccessToken(); const refreshToken = this.authTokenService.getValidRefreshToken(); if (accessToken) return of({ access_token: accessToken }); if (!accessToken && refreshToken) return this._requestAndSetTokensInLocalStorage(refreshToken); return new Observable((observer: Observer) => { observer.error(new Error('Both access and refresh tokens are not valid')); observer.complete(); }); } }