I use HttpClient and I create this interceptor to add the jwt token. Everyting work perfect but I have a bad practise. I use Http inside the HttpClient Interceptor. If I change
private http: Http,
to
private http: HttpClient
I get this cycle error
Cannot instantiate cyclic dependency! InjectionToken_HTTP_INTERCEPTORS ("[ERROR ->]")
any ideas how can I make it work?
import {Injectable} from "@angular/core";
import {HttpEvent, HttpHandler, HttpInterceptor} from "@angular/common/http";
import {HttpRequest} from "@angular/common/http";
import {Observable} from "rxjs/Observable";
import {Http} from "@angular/http";
import {SiteService} from "../services/site.service";
import {Router} from "@angular/router";
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(
private http: Http,
private router: Router,
private siteService: SiteService
) {}
refreshToken() {
return this.http.get(this.siteService.apiDomain() + '/api/token?token=' + localStorage.getItem('JWToken'), {})
.map((response: any) => {
let data = response.json();
return {
token: data.token,
permissions: data.permissions,
user: data.user,
};
})
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const clonedRequest = req.clone({
headers: req.headers.set('Authorization', 'Bearer ' + localStorage.getItem('JWToken'))
});
return next.handle(clonedRequest).catch((res) => {
if (res.status === 401 || res.status === 403) {
return this.refreshToken().flatMap((data) => {
if (data.token !== '') {
localStorage.setItem('currentUser', JSON.stringify(data.user));
localStorage.setItem('currentUserPermissions', JSON.stringify(data.permissions));
localStorage.setItem('JWToken', data.token);
} else {
localStorage.removeItem('currentUser');
localStorage.removeItem('currentUserPermissions');
localStorage.removeItem('JWToken');
this.router.navigate(['./auth/login']);
return Observable.throw(res);
}
const clonedRequestRepeat = req.clone({
headers: req.headers.set('Authorization', 'Bearer ' + localStorage.getItem('JWToken'))
});
return next.handle(clonedRequestRepeat);
})
} else {
return Observable.throw(res);
}
});
}
}
Another important thing for those who will use this interceptor for their project but irrelevant to the current problem is to set headers to the refresh token response at least some seconds.
->header('Cache-Control', 'public, max-age=45')
->header('Expires', date('D, d M Y H:i:s ', time() + 45).'GMT');
I resolved simply not setting authService in constructor but getting in the intercept function.
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Get the auth header from the service.
const auth = this.inj.get(AuthenticationService);
const authToken = auth.getAuthorizationToken();
...
}
Hou have to add Injector to your constructor first
constructor(
...
private inj: Injector
) {}
You may also try a little hack to instatiate the service, like:
constructor(private injector: Injector) {
setTimeout(() => {
this.loginService = this.injector.get(LoginService);
})
}
This way you won't get the max call stack exceeded error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With