Murlidhar Fichadia
Murlidhar Fichadia

Reputation: 2609

get Access Token before sending GET or POST request

I am trying to access the token in the constructor, like below in utils.service.ts file:

utils.service.ts > constructor

storage.get('token').then((val) => {
  this.token = val;
  console.log("token: ", val);
});

I have all my api get and post requests which need the token. When I make a call like below:

utils.service.ts

getDashboard() {
    if (this.dashboard) {
      return Promise.resolve(this.dashboard);
    }
    return new Promise(resolve => {
      this.http
        .get(globals.base_prod_api_url + "dashboard", {
          headers: {
            "Content-Type": globals.content_type,
            Authorization: "Bearer " + this.token
          }
        })
        .subscribe(
          data => {
            this.dashboard = data;
            resolve(this.dashboard);
          },
          error => {
            console.log(error);
            this.dashboard = error;
            return this.dashboard;
          }
        );
    });
  }

dashboard.page.ts

this.utilService.getDashboard().then(data => {
  this.dashboard_data = data;
});

Get request is executed even before the token value is retrieved from Storage. How can I get token first only then make a get request to server?

Upvotes: 0

Views: 1736

Answers (3)

lovis91
lovis91

Reputation: 2171

i think you should use interceptors to do that.

First you have to add it to your app.module.ts providers :

  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HttpTokenInterceptor,
      multi: true
    },
    ...
  ],

Then intercept the request and add your token to the headers :

import { Injectable, Inject } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http';
import { JwtService } from '../services/jwt.service';

@Injectable({
 providedIn: 'root'
})
export class HttpInterceptorService implements HttpInterceptor {
  constructor(
    private jwtService: JwtService,
  ) {}

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

  const headersConfig = {
    'Accept': 'application/json',
  };

  storage.get('token').then((token) => {
      headersConfig['Authorization'] = `Bearer ${token}`;
      return next.handle(request.clone({
         setHeaders: headersConfig
      }));
  });
}

To go further, you can use the interceptors to catch errors : (401 for example to handle the refresh token)

return next
.handle(request.clone({
    setHeaders: headersConfig
}))
.pipe(
    catchError(err => {

        if (err.status === 401) {
            // token is no longer available, refresh it
        }

        return throwError(err);
    })
);

Upvotes: 1

Timothy
Timothy

Reputation: 3593

If I were you I'd use Observables rather then Promises. Something like for RXJS 6

import { from } from 'rxjs';

get authToken(): Observable<string> {
  return from(storage.get('token')))
}

sendRequest():Observable<ReturnedObject> {
  this.authToken.pipe(switchMap(token => {
    return this.http
      .get(globals.base_prod_api_url + "dashboard", {
        headers: {
          "Content-Type": globals.content_type,
          Authorization: "Bearer " + token
        }
      })
  }))
}

Alternatively ES6 Promises decorators: Async, Await will radically simplify your code. Just don't remember to catch rejected promises via try/catch blocks

Upvotes: 2

rowadz
rowadz

Reputation: 361

You might create a private async method in the utils.service.ts which gits the token if the value of the token is undefined and return it. for example :

  async getToken(): Promise<string> {
    if(!this.token){
      this.token = await storage.get('token');
    }
    return this.token;
  }

and mark the other methods as async and 'await' for the token in the headers object.

for example

async getData(){
   ....
      headers: {
            "Content-Type": '...',
            Authorization: "Bearer " + await this.getToken()
      }
   ....
}

Upvotes: 1

Related Questions