Angular sending token with get (and other) requests

Mike Warren picture Mike Warren · Dec 29, 2017 · Viewed 16.6k times · Source

For some reason, the internet is devoid of examples on how to do this in Angular 4 (which uses TypeScript, which doesn't let you skip including option properties like the JavaScript it transpiles into does).

I'm trying to hit my team's RESTful API, which requires an authentication token, with GET request, like, for example :

return this.http.get(this.BASE_URL + '/api/posts/unseen/all', {
            headers : {
                "Authorization": 'Token token="' + TokenService.getToken() + '"'
            }   
        })

where TokenService is business service class I wrote to return token for use in the app. Upon typing it up, I get greeted with this error instead:

enter image description here

My dependencies in the service file this appears in are:

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';

import { Post } from '../models/post'; // business class 
import 'rxjs/';
import { User } from '../models/user'; // business class
import { HttpService } from './http.service'; // service for connecting us to the base location of the endpoints. provides BASE_URL to any service that extends it
import { TokenService } from './token.service'; // token provider

NOTE: I tried copying and pasting that error, but Visual Studio Code would not cooperate with me doing that.

Answer

edkeveked picture edkeveked · Dec 29, 2017

Using the new httpClient makes it easier to send token. First you will have to define an interceptor

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

@Injectable()
export class TokenInterceptor implements HttpInterceptor {

  constructor(public auth: AuthService) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    request = request.clone({
      setHeaders: {
        Authorization: `Bearer ${this.auth.getToken()}`
      }
    });

    return next.handle(request);
  }
}

You have to add the interceptor to your provider:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { TokenInterceptor } from 'token.interceptor';

@NgModule({
  bootstrap: [AppComponent],
  imports: [...],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: TokenInterceptor,
      multi: true
    }
  ]
})
export class AppModule {}

Now when you make any request, the token will be present automatically in the headers.

import { HttpClient } from '@angular/common/http';
// ...
export class AppComponent {

  constructor(public http: HttpClient) {}

  public connectServer() {
    this.http.get('url')
      .subscribe(
        data => console.log(data),
        err => console.log(err)
      );
  }

}

In the interceptor I use a service to check if the token is valid. It is not compulsory as you can define your own authenticationService. But here is one you can use:

import { Injectable } from '@angular/core';
import decode from 'jwt-decode';

@Injectable()
export class AuthService {

  public getToken(): string {
    return localStorage.getItem('token');
  }

  public isAuthenticated(): boolean {
    // get the token
    const token = this.getToken();
    // return a boolean indicating whether or not the token is expired
    return tokenNotExpired(token);
  }

}