0

I have 2 tokens. token_a lasts a very long time and is used to generate token_b. token_b expires every 15 minutes.

A user can navigate to a module however before they can do this i have a guard which checks whether the token_b is expired or not.However, they could already be within the module and making api calls that do not require a page change. My understanding is that guards are mainly used to protect routes.

How do i solve this problem of checking if a token is expired before making a http request.

api.service.ts

import { Injectable } from '@angular/core';
import { environment } from './../../../../environments/environment';
import { HttpHeaders, HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class ApiService {
    constructor(
        private http: HttpClient,
    ) { }

    private setHeaders(): HttpHeaders {
        const headersConfig = {
            'Content-Type': 'application/json',
            // 'Accept': 'application/json plain/text'
        };
        const token = localStorage.getItem('profile_token');

        if (token) {
            headersConfig['Authorization'] = 'Bearer ' + token;
        }
        return new HttpHeaders(headersConfig);
    }

    private formatErrors(error: any) {
        console.log(error);
        return Observable.throw(error);
    }

    get(path: string, httpParams: HttpParams = new HttpParams()): Observable<any> {
        return this.http.get(`${environment.api_url}${path}`, { headers: this.setHeaders(), params: httpParams })
            .catch(this.formatErrors)
            .map((res) => res);
    }

    put(path: string, body: Object = {}): Observable<any> {
        return this.http.put(
            `${environment.api_url}${path}`,
            JSON.stringify(body),
            { headers: this.setHeaders() }
        )
            .catch(this.formatErrors)
            .map((res) => res);
    }

    post(path: string, body: Object = {}): Observable<any> {
        return this.http.post(
            `${environment.api_url}${path}`,
            body,
            { headers: this.setHeaders() }
        )
            .catch(this.formatErrors)
            .map((res) => res);
    }

    delete(path): Observable<any> {
        return this.http.delete(
            `${environment.api_url}${path}`,
            { headers: this.setHeaders() }
        )
            .catch(this.formatErrors)
            .map((res) => res);
    }
}
Kay
  • 17,906
  • 63
  • 162
  • 270
  • You can use an `Httpinterceptor` to veryfy the token and then make the request. Or you can make the request, and if the server's response is that the token is invalid, get a new token and make the request again – David Apr 16 '18 at 09:16
  • Have a look here https://stackoverflow.com/questions/45202208/angular-4-interceptor-retry-requests-after-token-refresh – David Apr 16 '18 at 09:41
  • @David this seems to be the best answer, however my interceptor is not loading in a lazy loaded feature module any ideas? – Kay Apr 16 '18 at 10:08
  • Make sure the `HttpClientModule` is not imported multiple times in your app – David Apr 16 '18 at 13:01
  • @David its not, i have created a new question for this. – Kay Apr 16 '18 at 15:03

2 Answers2

0

As far I understand, You should save the token_b generation time in localstorage and every time you have to use token_b, check if 15 minutes elapsed. If 15 minutes elapsed then regenerate token_b and save the new generation time in localstorage.

0

You can check if the tooken is valid then only make request otherwise throw error. You can refer following code:

import { Injectable } from '@angular/core';
import { environment } from './../../../../environments/environment';
import { HttpHeaders, HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class ApiService {
    constructor(
        private http: HttpClient,
    ) { }
    ...
    get(path: string, httpParams: HttpParams = new HttpParams()): Observable<any> {
        if(this.isTokenValid()) {
            return this.http.get(`${environment.api_url}${path}`, { headers: this.setHeaders(), params: httpParams })
                .catch(this.formatErrors)
                .map((res) => res); 
        } else {
            return this.throwError();
        }

    }
    ...

    throwError() {
        return Observable.throw({message: 'Not authenticated'}});
    }

    isTokenValid() {
        // logic to check token expiry return true false accordingly;
    }
}
Anshuman Jaiswal
  • 5,352
  • 1
  • 29
  • 46