UNPKG

@bi8/am-uaa

Version:

ng update @angular/cli yarn add @angular/cli

122 lines (107 loc) 3.92 kB
import {Inject, Injectable} from '@angular/core'; import { HttpClient, HttpErrorResponse, HttpEvent, HttpHandler, HttpHeaders, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http'; import * as _ from 'lodash'; import {UaaEventService} from './uaa.event.service'; import {UaaEvent} from './uaa.event'; import {Observable} from 'rxjs/Observable'; import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/retry'; import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/switchMap'; import 'rxjs/add/operator/take'; import 'rxjs/add/operator/finally'; import 'rxjs/add/observable/throw'; import {BehaviorSubject} from 'rxjs/BehaviorSubject'; import {StorageService} from '@bi8/am-storage'; import {UaaConfigService} from './uaa.config.service'; import {JwtService} from './jwt.service'; import {UaaService} from './uaa.service'; @Injectable() export class UaaJwtInterceptor implements HttpInterceptor { isRefreshingToken = false; tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null); constructor(private uaaEventService: UaaEventService, private storageService: StorageService, private jwtService: JwtService, private uaaService: UaaService, private configService: UaaConfigService) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { if (!this.configService.useJwt) { return next.handle(req); } if (req.headers.has('Authorization')) { return next.handle(req); } const observable = next.handle(this.addToken(req, this.jwtService.getToken())); return observable.catch((error) => { if (error instanceof HttpErrorResponse) { switch ((<HttpErrorResponse>error).status) { case 400: return this.handle400Error(error, req, next); case 401: return this.handle401Error(req, next); default: return Observable.throw(error); } } else { return Observable.throw(error); } }); } private addToken(req: HttpRequest<any>, token: String): HttpRequest<any> { return req.clone({setHeaders: {'Authorization': `Bearer ${token}`}}); } private handle400Error(error, req, next) { if (error && error.status === 400 && error.error && error.error.error === 'invalid_grant') { return this.requireLogin(req, next); } return Observable.throw(error); } private handle401Error(req: HttpRequest<any>, next: HttpHandler) { if (!this.isRefreshingToken) { this.isRefreshingToken = true; this.tokenSubject.next(null); return this.jwtService.doRefresh().switchMap(res => { const newToken = this.jwtService.getToken(); if (newToken) { this.tokenSubject.next(newToken); return next.handle(this.addToken(req, newToken)); } return this.requireLogin(req, next); }).catch(error => { return this.requireLogin(req, next); }).finally(() => { this.isRefreshingToken = false; }); } else { return this.tokenSubject .filter(token => token != null) .take(1) .switchMap(token => { return next.handle(this.addToken(req, token)); }); } } private requireLogin(req, next): Observable<any> { this.uaaService.doLogout(); this.uaaEventService.broadcast(UaaEvent.LOGIN_REQUIRED); return next.handle(req); // Don't retry as roles might have changed /*return this.uaaEventService.getEventSourceObserver() .filter(event => event === UaaEvent.LOGIN_PROVIDED) .switchMap(event => { this.isRefreshingToken = false; return next.handle(this.addToken(req, this.jwtService.getToken())); });*/ } }