Reputation: 392
The case is when calling a service in the back-end and if I get error code indicates that it’s expired then in front-end First : request a valid jwt token. Second: rerequest the original http request after getting a valid token. The first step is done successfully but it’s not the case in the second one. This is the code in the interceptor
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!request.url.endsWith('login') && !request.url.endsWith('refreshtoken')) {
request = this.addAuthenticationToken(request);
}
return next.handle(request).pipe(catchError(err => {
Log.log("Error Status: " + err.status);
// invalid token or bad request
if (err.status == this.NOT_VALID_TOKEN_OR_BAD_REQUEST_ERROR_CODE) {
this.authenticationService.logOut();
return EMPTY;
}
else if (err.status == this.TOKEN_EXPIRED_ERROR_CODE) { // token is expired
this. doRefreshToken(request, next);
}
}
));
}
doRefreshToken(request, next) {
return this.authenticationService.refreshToken().subscribe((resp: HttpResponse<any>) => {
Log.log("in subscripe refresh token")
Log.log(resp.headers.get(this.AUTH_HEADER));
StorageManagementUtil.setLocaltStorage(resp.headers.get(this.AUTH_HEADER), <PortalRsponseTransaction>resp.body);
},
(error) => { Log.log(error) },
() => {
Log.log("on complete()")
request = this.addAuthenticationToken(request);
return next.handle(request);
});
}
And this is refresh token service
refreshToken() {
let map = new TSMap();
map.set(this.RQUEST_BODY_KEY_SESSION_TOKEN, StorageManagementUtil.readFromLocalStorage(StorageManagementUtil.SESSION_TOKEN));
var requsetBody = JSON.stringify(map.toJSON());
let request = new PortalRequestTransaction(requsetBody);
return this.http.post<PortalRsponseTransaction>(fullURL, request, {
observe: 'response',
responseType: 'json'
});
}
And this is a screenshot from network tap while inspecting
https://i.ibb.co/vqLTLh2/1.png
The question is why recalling the original service is not done after getting refresh token? And why calling service is done twice? (if we ignore the ones of OPTIONS request-type).
I'm beginner in angular so I wish I could provide sufficient information to figure out the problem.
Upvotes: 0
Views: 87
Reputation: 392
This solution is inspired by this answer using switchMap
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!request.url.endsWith('login') && !request.url.endsWith('refreshtoken')) {
request = this.addAuthenticationToken(request);
}
return next.handle(request).pipe(
catchError((err) => {
// invalid token or bad request
if (err.status == this.NOT_VALID_TOKEN_OR_BAD_REQUEST_ERROR_CODE) {
this.authenticationService.logOut();
return EMPTY;
}
else if (err.status == this.TOKEN_EXPIRED_ERROR_CODE) {
return this.handleRefreshToken(request, next);
}
})
);
}
handleRefreshToken(request: HttpRequest<any>, next: HttpHandler) {
return this.authenticationService.refreshToken().pipe(
switchMap((tokenResp) => {
StorageManagementUtil.setLocaltStorage(tokenResp.headers.get(this.AUTH_HEADER), <PortalRsponseTransaction>tokenResp.body);
request = this.addAuthenticationToken(request);
return next.handle(request);
}),
catchError(error => {
if (error.status == this.NOT_VALID_TOKEN_OR_BAD_REQUEST_ERROR_CODE) {
this.authenticationService.logOut();
return EMPTY;
}
})
);
}
Upvotes: 0
Reputation: 106
1) 401 means unauthorized, it seems you are not sending the correct authorization header( Bearer {JWT-Token} ) in the request.
2) For refresh token, better use rxjs-retry , which will help you to handle refresh logic either on error or on expiry
Code follows:
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!request.url.endsWith('login') && !request.url.endsWith('refreshtoken')) {
request = this.addAuthenticationToken(request);
}
return next.handle(request).pipe(
retryWhen(err => {
if (err.status == this.TOKEN_EXPIRED_ERROR_CODE) { // token is expired
return this. doRefreshToken(request, next);
}
}),
catchError(err => {
Log.log("Error Status: " + err.status);
// invalid token or bad request
if (err.status == this.NOT_VALID_TOKEN_OR_BAD_REQUEST_ERROR_CODE) {
this.authenticationService.logOut();
return EMPTY;
}
else if (err.status == this.TOKEN_EXPIRED_ERROR_CODE) { // token is expired
this. doRefreshToken(request, next); // return an observable
}
}
));
}
The above code snippet, will hit retry if there is an error, it will first refresh token, return an observable, then calls again the getAll.
Upvotes: 0