loading...
Cover image for Angular adding a token to each API request

Angular adding a token to each API request

dailydevtips1 profile image Chris Bongers Originally published at daily-dev-tips.com ・3 min read

Alright, so normally, when we are making API requests, we will need some kind of token to validate our request.

In our case, we just learned how to Log in as a user and ensure the routes are secured.

So from here, how can we manipulate API calls always to include the token we stored in our user object?

We don't want to be adding a header to every object call, like this.

const headers = new Headers({
  'Content-Type': 'application/json',
  'Authorization': `Bearer ${auth_token}`
})
return this.http.get(apiUrl, { headers: headers })
Enter fullscreen mode Exit fullscreen mode

Don't get me wrong. This will work, but it's repeating ourselves, so let's create an interceptor that will do just this for us!

Creating our interceptor

As usual let's open the terminal and find our project folder.
Now execute the following command to generate our token interceptor.

ng generate service interceptors/TokenInterceptor
Enter fullscreen mode Exit fullscreen mode

This will create a token-interceptor.service.ts file in our interceptors folder.

import { Injectable } from '@angular/core';
import { catchError } from 'rxjs/operators';
import { Observable, throwError } from 'rxjs';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { AuthService } from 'src/app/services/auth.service';

@Injectable({
  providedIn: 'root',
})
export class TokenInterceptorService implements HttpInterceptor {
  constructor(private authService: AuthService) {}
  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    const { token } = this.authService.userValue;
    if (token) {
      request = request.clone({
        setHeaders: {
          Authorization: `Bearer ${token}`,
        },
      });
    }
    return next.handle(request).pipe(
      catchError((err) => {
        if (err.status === 401) {
          this.authService.logout();
        }
        const error = err.error.message || err.statusText;
        return throwError(error);
      })
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

So, we register the authService as a provider in our service.
Then we implement the HttpInterceptor from which we will be extending the intercept function.

This intercept function has a request and a next object.

What we do is get the token from our user object.
If this is set, we clone the request that is being made and add a header.

In this case, we add a Bearer token with the actual token attached to it (yes, I know this is not an oAuth token)

Then we return the request and catch if we get a 401 (unauthorized) back.

If that is the case, we log out the current user since our token is expired and throw an error back.

Implementing the interceptor

So we now have to make sure all our calls are being logged with this interceptor.

Open up your app.module.ts, and in the providers section add the following.

providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: TokenInterceptorService,
      multi: true,
    },
],
Enter fullscreen mode Exit fullscreen mode

This tells Angular that we made our own HTTP_INTERCEPTOR and which service it should load this from.

Trying out our interceptor

Let's make a quick demo to see if it works.

Open the home.component.ts and make it look as such:

export class HomeComponent implements OnInit{
  currentUser: User;
  constructor(private authenticationService: AuthService, private http: HttpClient
) {
  this.authenticationService.user.subscribe(user => this.currentUser = user);
 }
 ngOnInit() {
   this.getUsers().subscribe(result => {
     console.log(result);
   })
 }
 getUsers() {
  return this.http.get<any>(`${environment.apiUrl}api/users`);
 }
}
Enter fullscreen mode Exit fullscreen mode

We are just doing a simple in component API call with the sole purpose of checking if our interceptor is working.

Now, if you open your console network tab, you should see the following request!

Angular Custom header

There you go, we now added our own custom header, and it will be added to every single one of our calls.

You can also find this code on GitHub.

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Discussion

pic
Editor guide
Collapse
mohsen2014 profile image
Mohsen Emami

Thanks, @dailydevtips1
I have an issue with the inspector in angular. I use angular-aws-amplify to fetch the token.
angular-aws-amplify has a method that returns an observable. but I don't know how can use an observable method in the inspector. do you know?

Collapse
dailydevtips1 profile image
Chris Bongers Author

Hey Mohsen,

What do you mean with inspector in angular, like a visual studio plugin or chrome plugin?

Normally you should be able to subscribe to an observable anyway.

Like amplify.subscribe(res => { console.log(res) });

Collapse
banzyme2 profile image
EN_DEE_SA

Where is the token stored? Localstorage or in memory as part of the currentUser object?

Collapse
dailydevtips1 profile image
Chris Bongers Author

Actually both, so in this example, it's stored in local storage, but the service is mostly based on memory itself to get the user object.
It will however get it initially from localStorage if it exists.