I have written the below interceptor which is working mostly as expected, apart from once my refresh token has expired, it gets stuck in a loop or re-requesting an updated access token with the expired refresh token and I can't figure out why?
My interceptor to Http requests looks like this
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private inject: Injector){}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let userService = this.inject.get(UserService)
let authReq = request;
authReq = this.AddTokenHeader(request, userService.getToken())
return next.handle(authReq).pipe(
catchError(errordata => {
if(errordata.status === 401){
//401 status error, the access token needs refreshing.
return this.handleRefreshToken(request, next)
}
return throwError(() => errordata)
})
)
}
AddTokenHeader(request: HttpRequest<any>, token: any){
return request.clone({headers: request.headers.set('Authorization', 'Bearer ' token)})
}
handleRefreshToken(request: HttpRequest<any>, next: HttpHandler){
let userService = this.inject.get(UserService)
return userService.GenerateRefreshToken().pipe(
switchMap((data:any) => {
userService.updateAccessToken(data)
return next.handle(this.AddTokenHeader(request, localStorage.getItem('accessToken')))
}),
catchError(errordata => {
userService.logout()
return throwError(() => errordata)
})
)
}
}
And the UserService contains this among other functions, but I think this is the only one really relevant.
public GenerateRefreshToken(){
return this.http.post(this.djangoPath '/api/token/refresh/', JSON.stringify({"refresh": localStorage.getItem('refreshToken')}), this.httpOptions)
}
I thought the catchError in the handleRefreshToken function would deal with the refresh token being expired and then result to logging out the user to force religion to generate a new refresh token, but clearly I am wrong. I am just getting repeated 401 responses from the refresh call as the token is expired. It works fine while the refresh token is valid.
Can anyone shed any light on what I am doing wrong? The backend is Django/DRF/SimpleJWT.
Finally, Merry Christmas to anybody who chooses to celebrate it.
CodePudding user response:
(You didn't mention what updateAccessToken
method does, but I believe it's saving the token to the localStorage
)
I believe the problem is that - userService.GenerateRefreshToken()
method is also intercepted by this interceptor, so any time you get to catchError
you call this function which goes into this interceptor again and calls this function - and here is the loop...
what you can do is exclude this route from being intercepted - wrap your code with this condition:
if(req.url.includes('/api/token/refresh/')) {
// only for this route skip interceptor logic
return next();
}
good luck :)