@bi8/am-uaa
Version:
ng update @angular/cli yarn add @angular/cli
122 lines (107 loc) • 3.92 kB
text/typescript
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';
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()));
});*/
}
}