Skip to content

Instantly share code, notes, and snippets.

@umutyerebakmaz
Created August 9, 2023 15:09
Show Gist options
  • Save umutyerebakmaz/43f0555aa1865f4e7753fcec16650ff1 to your computer and use it in GitHub Desktop.
Save umutyerebakmaz/43f0555aa1865f4e7753fcec16650ff1 to your computer and use it in GitHub Desktop.
Auth Interceptor
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';
import { Observable, BehaviorSubject } from 'rxjs';
import { catchError, filter, switchMap, take } from 'rxjs/operators';
import { AuthService } from '@services/auth.service';
import { Router } from '@angular/router';
import { TokenType } from '@app/graphql.module';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
private isRefreshing = false;
private newAccessTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(private authService: AuthService, private router: Router) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const accessToken = this.authService.getAccessToken();
if (accessToken === null) {
request = request.clone({
setHeaders: {
Accept: 'charset=utf-8',
},
});
}
if (accessToken) {
request = this.setRequest(request, accessToken, 'access');
}
return next.handle(request).pipe(
catchError((error: HttpErrorResponse) => {
const e = error.error.errors[0];
if (e.message === 'expired token') {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.newAccessTokenSubject.next(null);
const refreshToken = this.authService.getRefreshToken();
return this.authService.refreshAccessToken(refreshToken).pipe(
switchMap(res => {
this.isRefreshing = false;
this.newAccessTokenSubject.next(res.accessToken);
const clonedRequest = this.setRequest(request, res?.accessToken, 'refresh');
console.log(clonedRequest);
return next.handle(clonedRequest).pipe();
}),
catchError(refreshError => {
this.isRefreshing = false;
this.authService.removeTokens();
this.router.navigate(['login']);
throw new Error(refreshError);
})
);
} else {
return this.newAccessTokenSubject.pipe(
filter(token => token !== null),
take(1),
switchMap(subject => {
console.log(4, subject);
const cloneRequest2 = this.setRequest(request, subject.accessToken, 'access');
return next.handle(cloneRequest2);
})
);
}
}
throw new Error(error as any);
})
);
}
private setRequest(request: HttpRequest<any>, token: string, tokenType: TokenType): HttpRequest<any> {
return request.clone({
setHeaders: {
Accept: 'charset=utf-8',
Authorization: `Bearer ${token}`,
tokenType: tokenType,
},
});
}
}
@umutyerebakmaz
Copy link
Author

@aliosmanyuksel Hello, I tested and the result did not change. By default, the interceptor goes as access token and tokenType = 'access' in the header, and if this request gives an error as expired token from the server, it should treat the refreshToken endpoint as refresh token and tokenType = 'refresh'. In the current situation, the mutable is behaving correctly or there is something wrong with my setup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment