import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { environment } from '@environment'; import { empty, from, mergeMap, Observable } from 'rxjs'; import { AppInsightsSessionService } from '../app-insights-session.service'; import { TokenService } from './token.service'; @Injectable({ providedIn: 'root' }) export class TokenInterceptor implements HttpInterceptor { constructor ( private tokenService: TokenService, private appInsightsSessionService: AppInsightsSessionService ) { } appendSessionIdHeader ( r: HttpRequest ) { return r.clone({ headers: r.headers.append('x-gc-session-id', this.appInsightsSessionService.sessionId) }); } intercept ( r: HttpRequest, next: HttpHandler ): Observable> { return from((async (request) => { // we are trying to make an internal request if we omit http/https // i.e. /some/endpoint vs http://api.something.com/some/endpoint if ( this.checkShouldProcessRequest(request.url) ) { request = this.appendSessionIdHeader(request); request = this.buildUpFullAPIURL(request); // don't add the token to token requests unless it's for logging out (revoking) request = await this.appendToken(request); } return request; })(r)) // if we got a request out of the previous observable, then we are good to go // otherwise stop the request .pipe(mergeMap(request => request ? next.handle(request) : empty())); } private async appendToken (request: HttpRequest) { if (this.checkShouldAppendToken(request.url)) { // capture whether or not we had a token before the attempted retrieval/refresh const latestToken = await this.tokenService.getLatestToken() as string; // if the refresh went through or we have a valid token if (latestToken) { const headers = request.headers.set('Authorization', `Bearer ${latestToken}`); request = request.clone({ headers }); } } return request; } private checkShouldAppendToken (url: string) { return !url.startsWith(`${environment.apiUrl}/api/token`) || (/\/(RevokeForClient|RevokeAll|FileScanToken)$/).test(url); } private buildUpFullAPIURL (request: HttpRequest) { if (!request.url.startsWith('/')) { request = request.clone({ url: '/' + request.url }); } request = request.clone({ url: `${environment.apiUrl}${request.url}` }); return request; } private checkShouldProcessRequest (url: string) { return !(/^(http|\/(InsertMissing|assets|Version|Log))/).test(url) && (url.startsWith('/api') || url.startsWith('api') || url.startsWith('filescan') || url.startsWith('/filescan')); } }