implemented a token interceptor

pull/4/head
FlayInAHook 4 years ago
parent 65bc305649
commit 036a9d27f1

@ -1,7 +1,7 @@
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { DragDropModule } from '@angular/cdk/drag-drop'; import { DragDropModule } from '@angular/cdk/drag-drop';
@ -39,6 +39,7 @@ import { TableOverviewComponent } from './pages/table-overview/table-overview.co
import { CellComponent } from './components/tableComponents/cell/cell.component'; import { CellComponent } from './components/tableComponents/cell/cell.component';
import { MenuListItemComponent } from './components/menu-list-item/menu-list-item.component'; import { MenuListItemComponent } from './components/menu-list-item/menu-list-item.component';
import { NavService }from './components/menu-list-item/nav.service'; import { NavService }from './components/menu-list-item/nav.service';
import { TokenInterceptor } from './helper/token.interceptor'
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -80,7 +81,9 @@ import { NavService }from './components/menu-list-item/nav.service';
MatPaginatorModule, MatPaginatorModule,
MatSortModule MatSortModule
], ],
providers: [NavService], providers: [NavService,
{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true }],
bootstrap: [AppComponent], bootstrap: [AppComponent],
}) })
export class AppModule { export class AppModule {

@ -0,0 +1,60 @@
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse } from '@angular/common/http';
import { AuthService } from '../services/auth.service';
import { Observable, throwError, BehaviorSubject } from 'rxjs';
import { catchError, filter, take, switchMap } from 'rxjs/operators';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
private isRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(public authService: AuthService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.authService.getRequestToken()) {
request = this.addToken(request, this.authService.getRequestToken());
}
return next.handle(request).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
console.log("catching error");
return this.handle401Error(request, next);
} else {
return throwError(error);
}
}));
}
private addToken(request: HttpRequest<any>, token: string) {
return request.clone({
setHeaders: {
'Authorization': `Bearer ${token}`
}
});
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
return this.authService.refreshToken().pipe(
switchMap((token: any) => {
this.isRefreshing = false;
this.refreshTokenSubject.next(token.jwt);
return next.handle(this.addToken(request, token.jwt));
}));
} else {
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => {
return next.handle(this.addToken(request, jwt));
}));
}
}
}

@ -9,6 +9,8 @@ import { BehaviorSubject } from 'rxjs';
}) })
export class AuthService { export class AuthService {
public loggedIn: BehaviorSubject<boolean>; public loggedIn: BehaviorSubject<boolean>;
private readonly REQUEST_TOKEN = 'requestToken';
private readonly REFRESH_TOKEN = 'refreshToken';
constructor(private http: HttpClient) { constructor(private http: HttpClient) {
this.loggedIn = new BehaviorSubject<boolean>(false); this.loggedIn = new BehaviorSubject<boolean>(false);
@ -16,15 +18,15 @@ export class AuthService {
} }
private checkIfUserIsLoggedIn(): void { private checkIfUserIsLoggedIn(): void {
this.loggedIn.next(!!this.requestToken); this.loggedIn.next(!!this.getRequestToken());
} }
public get requestToken(): string { public getRequestToken(): string {
return localStorage.getItem('requestToken'); return localStorage.getItem(this.REQUEST_TOKEN);
} }
public get refreshToken(): string { public getRefreshToken(): string {
return localStorage.getItem('refreshToken'); return localStorage.getItem(this.REFRESH_TOKEN);
} }
login(email: string, password: string) { login(email: string, password: string) {
@ -33,8 +35,7 @@ export class AuthService {
.pipe( .pipe(
map((response) => { map((response) => {
// store request and refresh token in local storage to keep user logged in between page refreshes // store request and refresh token in local storage to keep user logged in between page refreshes
localStorage.setItem('requestToken', response.request_token); this.storeTokens(response);
localStorage.setItem('refreshToken', response.refresh_token);
this.checkIfUserIsLoggedIn(); this.checkIfUserIsLoggedIn();
}) })
); );
@ -43,11 +44,34 @@ export class AuthService {
logout() { logout() {
// remove token from local storage to log user out // remove token from local storage to log user out
return this.http return this.http
.post<any>(`${environment.authUrl}/logout`, { request_token: this.requestToken }).pipe(finalize(() => { .post<any>(`${environment.authUrl}/logout`, { request_token: this.getRequestToken() }).pipe(finalize(() => {
localStorage.removeItem('requestToken'); this.removeTokens();
localStorage.removeItem('refreshToken');
this.checkIfUserIsLoggedIn(); this.checkIfUserIsLoggedIn();
} }
)); ));
} }
refreshToken() {
return this.http.post<any>(`${environment.authUrl}/new-token`, {
'refresh_token': this.getRefreshToken()
}).pipe(tap((tokens: any) => {
this.storeTokens(tokens);
}));
}
private storeRequestToken(jwt: string) {
localStorage.setItem(this.REQUEST_TOKEN, jwt);
}
private storeTokens(tokens: any) {
localStorage.setItem(this.REQUEST_TOKEN, tokens.request_token);
localStorage.setItem(this.REFRESH_TOKEN, tokens.refresh_token);
}
private removeTokens() {
localStorage.removeItem(this.REQUEST_TOKEN);
localStorage.removeItem(this.REFRESH_TOKEN);
}
} }

Loading…
Cancel
Save