2

I have successfully developed an angular2 interceptor utilizing refresh tokens (refreshing the token and then retrying the http request) in which the access_token and refresh_token are both stored in the localStorage.

The following is the code for refreshing the token in my "AuthService":

refreshToken():Observable<Response>
{
  let refToken: string = localStorage.getItem("bdRefreshToken");
  let username: string = localStorage.getItem("bdUsername");
  let body = "grant_type=refresh_token"
            +"&client_id=" + Settings.loginInfo.client_id
            +"&client_secret=" + Settings.loginInfo.client_secret
            +"&scope=" + Settings.loginInfo.scope
            +"&username="+username
            +"&refresh_token="+refToken;
  let header = new Headers({
      'Content-Type': 'application/x-www-form-urlencoded'
  });
  let ro:RequestOptions = new RequestOptions({
      headers: header
  });
  return this._http.post(Settings.tokenEndpoint, body, ro)
      //.map(res => res.json())
      .map(data => {
            let d = data.json();
            localStorage.setItem('bdAccessToken', d.access_token);
            localStorage.setItem('bdRefreshToken', d.refresh_token);
            this.saveRoles(d.access_token);
            return data;
        }
   )
   .catch(error => {
        this.logout();
        return Observable.throw(error)
   });
}

And the following is part of my inherited http class which serves as an interceptor:

get(url:string, options?:RequestOptions):Observable<Response>
  {    
       return super.get(url, this.getAuthorizedOptions())
       .catch(err => {
          if (err && err.status === 401){
              return this._authService.refreshToken()
                .flatMap(r =>
                    super.get(url, this.getAuthorizedOptions())
                )
                .catch(err2 => {
                    this.redirect();
                    return Observable.throw(err2);
                });
          }
          else {
              return Observable.throw(err);
          }
      });      
  }

private getAuthorizedOptions():RequestOptions
  {
      let token = localStorage.get('bdAccessToken');
      let header = new Headers({
        'Authorization': 'Bearer '+ token
      });
      let ro = new RequestOptions({
        headers: header
      });
      let options = new RequestOptions();
      if (options.headers) options.headers.delete("Authorization");
      options.headers = header;
      return options;
  }

Now, I have been trying to develop the same thing in Ionic, however, I have not been able to make it work because of the asynchronous nature of the Ionic Storage. Retrieving a value from the storage is not as simple as localStorage.get(item), and you have to do something like: storage.get(item).then(v => do stuff...).

I am looking to create an AuthService and an inherited Http class that works as an interceptor; which does the following standard procedure:

  1. Reads the access token from the storage, builds up the requestOptions based off it and tries the request.
  2. If it results a 401, it reads the refresh token from the storage, and gets a new access token using it and stores it in the storage.
  3. Tries the original http request using the new access token
  4. If it still fails, redirects the user to the login page.
halfer
  • 19,824
  • 17
  • 99
  • 186
Behrooz
  • 1,895
  • 4
  • 31
  • 47

0 Answers0