Skip to content

Instantly share code, notes, and snippets.

@caferrari
Forked from filipemansano/jwt.interceptor.ts
Last active January 3, 2018 08:12
Show Gist options
  • Save caferrari/342b049623cdfb5ff2630d7fdee8e271 to your computer and use it in GitHub Desktop.
Save caferrari/342b049623cdfb5ff2630d7fdee8e271 to your computer and use it in GitHub Desktop.
Interceptador HTTP em Angular 5 para adicionar o Token JWT nos request, e renovar o token caso expirado funcionando com múltiplas chamadas
import { Injectable, Injector } from '@angular/core';
import {
HttpInterceptor,
HttpRequest,
HttpHandler,
HttpEvent
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { finalize } from 'rxjs/operators/finalize';
import { catchError } from 'rxjs/operators/catchError';
import { switchMap } from 'rxjs/operators/switchMap';
import { take } from 'rxjs/operators';
import { filter } from 'rxjs/operators';
import 'rxjs/add/observable/throw';
import { AuthService } from '@app/core/security/auth/auth.service';
/**
* Interceptador HTTP para adicionar o Token nas requisições ao serve
* e mapear os erros a fim de verificar erro de token expirado
* tentando renova-lo caso possivel, aceitando multiplas chamadas assincronas
* com o token expirado criando uma espece de "fila" até que a 1º chamada que
* solicitou o token seja resolvida.
*
* @author Filipe Mansano
* @version 1.0
* @since 2018-01-02
*/
@Injectable()
export class JWTInterceptor implements HttpInterceptor {
isRefreshingToken: boolean = false;
tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);
constructor(private inj: Injector) { }
/**
* Função que clona o request adicionando o token nos cabeçalhos
* @param request
* @param token
*/
addToken(request: HttpRequest<any>, token: string): HttpRequest<any> {
return request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authService = this.inj.get(AuthService);
if (request.url.includes("/auth/login")) {
return next.handle(request);
}
const requestJWT = this.addToken(request, authService.getToken().token);
return next.handle(requestJWT).pipe(
catchError(err => {
if (err.status !== 401) {
return Observable.throw(err);
}
if (!err.error || !err.error.errorMessage.includes("expirado")) {
return this.tokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(token => next.handle(this.addToken(request,token)))
);
}
if (this.isRefreshingToken) {
return;
}
this.isRefreshingToken = true;
this.tokenSubject.next(null);
return authService.refreshToken().pipe(
finalize(() => {
this.isRefreshingToken = false;
}),
switchMap((newToken: string) => {
if(newToken){
this.tokenSubject.next(newToken);
return next.handle(this.addToken(request, newToken));
}
authService.logoff();
return Observable.throw("Não foi possivel obter o token");
}),
catchError(errTokenRefresh => {
authService.logoff();
return Observable.throw(errTokenRefresh);
})
);
})
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment