Ionic 2 - Get token from Storage value and set Header before HTTP Request
Asked Answered
A

2

3

I am using the ionic/storage package to store the api_token for users after they logged in so I can use the unique token to interact with an API.

The problem I am facing is that I need to get the value via storage.get which returns a promise and results in the headers I want to set not being set in time.

I need to return an instance of RequestOptions but can't figure out how to add the header I retrieve when it comes from a promise. Adding a header synchronous with localStorage is working fine when testing so the issue must be the asynch execution.

createAuthorizationHeader(headers: Headers) {
    // this does add the header in time
    localStorage.setItem('api_token', 'some token');
    headers.append('Authorization', 'Bearer ' + localStorage.getItem('api_token'));

    // this does not add the header in time
    return this.storage.get('api_token').then((value) => {
        headers.append('Authorization', 'Bearer ' + value);
    });
}

getHeaders(path): RequestOptions {
    let headers = new Headers({
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    });

    if(!this.isGuestRoute(path)) {
        this.createAuthorizationHeader(headers);
    }

    return new RequestOptions({ headers: headers });
}

get(path: string) {
    return this._http.get(this.actionUrl + path, this.getHeaders(path))
        .map(res => res.json())
        .catch(this.handleError);
}

Edit: Working code now looks like this

getApiToken(): Observable<Headers> {
    return Observable.fromPromise(this.storage.get('api_token'));
}

getHeaders(): Headers {
    return new Headers({
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    });
}

get(path: string) {
    let headers: Headers = this.getHeaders();

    if(!this.isGuestRoute(path)) {
        return this.getApiToken().flatMap(data => {
            headers.append('Authorization', 'Bearer' + data);

            return this._http.get(this.actionUrl + path, { headers : headers })
                .map(res =>  res.json())
                .catch(this.handleError);
        });
    }

    return this._http.get(this.actionUrl + path, { headers : headers })
        .map(res => res.json())
        .catch(this.handleError);
}
Abulia answered 8/12, 2016 at 8:49 Comment(0)
C
9

Check out my similar problem Angular2 - Use value of Observable returning method in another Observable

If you convert the Promise to a Observable you will be able to use the rxjs flatMap function.

Let me show you what your would somewhat look like then

getApiToken(): Observable<Headers> {
    return Observable.fromPromise(this.storage.get('api_token'));
   //OR return Observalbe.of(this.storage.get('api_token'));
}

getHeaders(): Headers { 
     //create all headers here except the 'api_token'
     .....
}


get(path: string): Observable<any> {
    let headers: Headers = this.getHeaders();
    return this.getApiToken().flatMap(data => {

       headers.append('Authorization', 'Bearer'+data);

       return this.http.get(this.actionUrl + path, headers)
          .map(res =>  res.json()) 
          .catch(this.handleError);
    });
}

OR (Just learned about this so not sure if it will work)

createAuthorizationHeader(headers: Headers) {
    // this does add the header in time
    localStorage.setItem('api_token', 'some token');
    headers.append('Authorization', 'Bearer ' + localStorage.getItem('api_token'));

    // this does not add the header in time
    let api_token = await this.storage.get('api_token');
    headers.append('Authorization', 'Bearer ' + api_token);
}
Chiclayo answered 8/12, 2016 at 9:6 Comment(1)
Thanks, the first one works! The await variant throws an error that it only is supported when targeting ES2015 or higher for some reason.Abulia
O
0

I would suggest looking at Interceptors: https://angular.io/guide/http (serach for the section named "Setting new headers"). I tried using BaseRequestOptions but that still causes an async problem.

Regadring Ivaro18 answer, of setting the headers as the token is received and saved in storage, won't that break when the user returns to an app/page after killing the app/ closing browser? The header are set in memory, so it won't be persistent.

Oliveira answered 23/7, 2017 at 7:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.