From 89bd0f28c541fa521e7c60ffbe2597e40e84f85d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Barbeau?= Date: Thu, 15 Mar 2018 10:11:38 -0400 Subject: [PATCH] feat(auth): secure token with trust hosts --- src/demo-app/environments/environment.prod.ts | 10 ++-------- src/demo-app/environments/environment.ts | 10 ++-------- src/lib/auth/shared/auth.interceptor.ts | 14 ++++++++++++-- src/lib/auth/shared/auth.interface.ts | 1 + src/lib/core/config/config.service.ts | 10 +++++++--- src/lib/environment.interface.ts | 12 ++++++++++++ src/lib/index.ts | 2 ++ 7 files changed, 38 insertions(+), 21 deletions(-) create mode 100644 src/lib/environment.interface.ts diff --git a/src/demo-app/environments/environment.prod.ts b/src/demo-app/environments/environment.prod.ts index bd8aad5510..b95974f4a0 100644 --- a/src/demo-app/environments/environment.prod.ts +++ b/src/demo-app/environments/environment.prod.ts @@ -3,17 +3,11 @@ // `ng build --env=prod` then `environment.prod.ts` will be used instead. // The list of which env maps to which file can be found in `.angular-cli.json`. -import { SearchSourcesOptions, LanguageOptions, AuthOptions, - ContextServiceOptions } from '../../lib'; +import { IgoEnvironment } from '../../lib'; interface Environment { production: boolean; - igo: { - searchSources?: SearchSourcesOptions; - language?: LanguageOptions; - auth?: AuthOptions; - context?: ContextServiceOptions; - }; + igo: IgoEnvironment; }; export const environment: Environment = { diff --git a/src/demo-app/environments/environment.ts b/src/demo-app/environments/environment.ts index 66512397db..7c6f190d23 100644 --- a/src/demo-app/environments/environment.ts +++ b/src/demo-app/environments/environment.ts @@ -3,17 +3,11 @@ // `ng build --env=prod` then `environment.prod.ts` will be used instead. // The list of which env maps to which file can be found in `.angular-cli.json`. -import { SearchSourcesOptions, LanguageOptions, AuthOptions, - ContextServiceOptions } from '../../lib'; +import { IgoEnvironment } from '../../lib'; interface Environment { production: boolean; - igo: { - searchSources?: SearchSourcesOptions; - language?: LanguageOptions; - auth?: AuthOptions; - context?: ContextServiceOptions; - }; + igo: IgoEnvironment; }; export const environment: Environment = { diff --git a/src/lib/auth/shared/auth.interceptor.ts b/src/lib/auth/shared/auth.interceptor.ts index 41bd32cd62..64522f073f 100644 --- a/src/lib/auth/shared/auth.interceptor.ts +++ b/src/lib/auth/shared/auth.interceptor.ts @@ -3,18 +3,28 @@ import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; +import { ConfigService } from '../../core/config/config.service'; import { TokenService } from './token.service'; @Injectable() export class AuthInterceptor implements HttpInterceptor { - constructor(private tokenService: TokenService) {} + private trustHosts: string[] = []; + + constructor(private tokenService: TokenService, private config: ConfigService) { + this.trustHosts = this.config.getConfig('auth.trustHosts') || []; + this.trustHosts.push(window.location.hostname); + } intercept(req: HttpRequest, next: HttpHandler): Observable> { const token = this.tokenService.get(); - if (!token) { + const element = document.createElement('a'); + element.href = req.url; + + if (!token && !this.trustHosts.includes(element.hostname)) { return next.handle(req); } + const authHeader = `Bearer ${token}`; const authReq = req.clone({headers: req.headers.set('Authorization', authHeader)}); return next.handle(authReq); diff --git a/src/lib/auth/shared/auth.interface.ts b/src/lib/auth/shared/auth.interface.ts index 5868e8f63c..02e982544a 100644 --- a/src/lib/auth/shared/auth.interface.ts +++ b/src/lib/auth/shared/auth.interface.ts @@ -21,6 +21,7 @@ export interface AuthOptions { intern?: AuthInternOptions; facebook?: AuthFacebookOptions; google?: AuthGoogleOptions; + trustHosts?: string[]; } export interface User { diff --git a/src/lib/core/config/config.service.ts b/src/lib/core/config/config.service.ts index 32370c0a0c..a46149fe98 100644 --- a/src/lib/core/config/config.service.ts +++ b/src/lib/core/config/config.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Injector } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; import { catchError } from 'rxjs/operators'; @@ -12,7 +12,7 @@ export class ConfigService { private config: Object = {}; - constructor(private http: HttpClient) {} + constructor(private injector: Injector) {} /** * Use to get the data found in config file @@ -28,11 +28,15 @@ export class ConfigService { if (options.default) { this.config = options.default; } + if (!options.path) { return true; } + + const http = this.injector.get(HttpClient); + return new Promise((resolve, reject) => { - this.http.get(options.path).pipe( + http.get(options.path).pipe( catchError((error: any): any => { console.log(`Configuration file ${options.path} could not be read`); resolve(true); diff --git a/src/lib/environment.interface.ts b/src/lib/environment.interface.ts new file mode 100644 index 0000000000..34f4c96f54 --- /dev/null +++ b/src/lib/environment.interface.ts @@ -0,0 +1,12 @@ +import { SearchSourcesOptions, LanguageOptions, AuthOptions, + ContextServiceOptions, CatalogServiceOptions, ImportExportServiceOptions +} from './'; + +export interface IgoEnvironment { + searchSources?: SearchSourcesOptions; + language?: LanguageOptions; + auth?: AuthOptions; + context?: ContextServiceOptions; + catalog?: CatalogServiceOptions; + importExport?: ImportExportServiceOptions; +} diff --git a/src/lib/index.ts b/src/lib/index.ts index 434836e1fc..5a75d689a6 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -19,3 +19,5 @@ export * from './shared'; export * from './share-map'; export * from './tool'; export * from './utils'; + +export * from './environment.interface';