I am in the process of building a new app that requires authorization headers. Typically I use something very similar to the approach found in this scotch.io article. But it has come to my attention that HTTP Interceptors are now fully supported within the Angular 4 ecosystem via the new HttpClientModule and I am trying to find some documentation on how exactly to use them.
If I am incorrect in (as of 4.3) this being the best practice for injecting authorization headers, I'd also be open to suggestions. My thinking was that it was a feature added recently which means there is probably good reason to migrate to an "Angular Approved" method.
Create the InterceptorImport all the essential modules required by the application, such as the observable, injectable, HTTP requests, HTTP handler, HTTP events, etc. Now, create a class implementing the HTTP interceptor in angular interface. Later, you need to create one interceptor method with two arguments.
By intercepting the HTTP request, we can modify or change the value of the request. Interceptors is a unique type of Angular service that allow us to intercept incoming or outgoing HTTP request using HttpClient.
To create an Interceptor, we need to implement the HttpInterceptor interface from @angular/common/http package. Every time our application makes an HTTP request using the HttpClient service, the Interceptor calls the intercept() method.
Interceptors are used in conjunction with Java EE managed classes to allow developers to invoke interceptor methods on an associated target class, in conjunction with method invocations or lifecycle events. Common uses of interceptors are logging, auditing, and profiling.
This answer is borrowing from the official documentation linked to by CodeWarrior.
Angular allows you to create an HttpInterceptor:
import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
@Injectable()
export class NoopInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req);
}
}
which you can then integrate into your app like so:
import {NgModule} from '@angular/core';
import {HTTP_INTERCEPTORS} from '@angular/common/http';
@NgModule({
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: NoopInterceptor,
multi: true,
}],
})
export class AppModule {}
To add an authorization header, you can clone the request with the changed headers:
import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private auth: AuthService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Get the auth header from the service.
const authHeader = this.auth.getAuthorizationHeader();
// Clone the request to add the new header.
const authReq = req.clone({headers: req.headers.set('Authorization', authHeader)});
// Pass on the cloned request instead of the original request.
return next.handle(authReq);
}
}
Note that the interceptors act like a chain, so you can set up multiple interceptors to perform different tasks.
Injecting AuthService to the Interceptor's constructor was giving me this error:
Uncaught Error: Provider parse errors: Cannot instantiate cyclic dependency! InjectionToken_HTTP_INTERCEPTORS ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1
So instead of injecting it to the constructor, I used Injector
of @angular/core
and it worked fine. I am storing the token in localStorage
and using basic auth. I need to set
Authorization: 'Bearer token_string'
Here is how I have implemented:
token.interceptor.ts
import {Injectable, Injector} from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import {AuthService} from './auth.service';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private injector: Injector) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const auth = this.injector.get(AuthService);
if (auth.getToken()) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${auth.getToken()}`
}
});
}
return next.handle(request);
}
}
getToken function in AuthService
Here you can implement the whole logic to get the header or only the token. Here in my case, I am only calling this to get the JWT token string.
/**
* Get jwt token
* @returns {string}
*/
getToken(): string {
return localStorage.getItem('token');
}
app.module.ts
Import the TokenInterceptor
import {TokenInterceptor} from './pathToTheFile/token.interceptor';
add the following under @NgModule
in providers:
array.
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
}
//, other providers
]
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