Search code examples
angularauthenticationtokenaccess-tokenangular2-guards

angular2 refresh token via service


In my project the backend exposed refresh token api. When you log in you get valid token and refresh token. When the token expires you need to make a refresh call, authorized with the old expired token and parameter refresh token. The response returns new valid token and new refresh token. At the moment i am trying to implement it inside my authorization guard. This is the code:

 import { Injectable } from '@angular/core';
 import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot }     from '@angular/router';
 import { Observable } from 'rxjs/Rx';

 import { SessionService } from '../services/session.service';

@Injectable()
export class AuthorizationGuard implements CanActivate {

constructor(private sessionService: SessionService, private router: Router) { }

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean> {
    if (this.sessionService.isAuthenticated() ) {
        console.log('guard has cookies');
        return true;
    } else {
        if(this.sessionService.checkStorageSession() == null) {
            this.router.navigate(['/']);
        } else {
            console.log('guard will refresh token via refresh token call  ');
            this.sessionService.refreshToken()
                .subscribe(
                    data => {
                        console.log('guard  refresh success');
                        this.sessionService.destroySessionCookie();
                        this.sessionService.rememberUser(data.accessToken);
                        this.sessionService.rememberRefreshTocken(data.refreshToken);
                        this.sessionService.setSessionCookie(data.accessToken);
                        this.sessionService.setRefreshTocken(data.refreshToken);
                        return true;
                    },
                    error => {
                        console.log('session refresh fail: ' + error);
                        this.router.navigate(['/']);
                        return false;
                    }
            );
        }
    }
}

}

But the problem is canActivate invokes, the call starts, refreshes token but i get 403 unauthorized from other calls that are on the activated page before the success response from the refresh. Also i cant figure out how to refresh token when i am standing on a page with save button, the token expires, i press save and update call is made, but with the expired token. Please suggest approaches :s


Solution

  • I used this approach, in AuthorizationGuard you have check of:

    if(!this.sessionService.isUserAuthenticated){
      this.router.navigate(['/']);
    }
    

    Where isAuthenticated=true means that user has valid refreshToken. And I overrided http service to have refresh token logic:

    var authenticatedCall: Observable<any>;
          if (needToken) {
              if (this.sessionService.isUserAuthenticated) {
                   authenticatedCall = this.sessionService.acquireToken()
                   .flatMap((token: string) => {
                             if (options1.headers == null) {
                               options1.headers = new Headers();
                             }
                                options1.headers.append('Authorization', 'Bearer ' + token);
                                return this.http.request(url, options1);
                         });
                    }
                    else {
                        authenticatedCall = Observable.throw(new Error("User Not Authenticated."));
                    }
            }
            else {            
                authenticatedCall = this.http.request(url, options).map(this.extractData);
     }
    

    As example I used this: https://github.com/sureshchahal/angular2-adal/blob/master/src/services/authHttp.service.ts