Handling Expired Token From Api in Angular 4
Asked Answered
G

2

15

I need help in handling expired token in my angular application. My api has the expired time but my problem is when i forgot to log out of my angular application, after some time, i still can access the homepage but without data. Is there something i can do about this? Are there libraries that can handle this? or are there something i could install? Better, if i nothing will be installed. Here's my authentication code below? Can i add anything that can handle expiration and I won't be able to access the homepage if it expires.

auth.service.ts

 export class AuthService {
  private loggedIn = false;

  constructor(private httpClient: HttpClient) {
  }

  signinUser(email: string, password: string) {  
    const headers = new HttpHeaders() 
    .set('Content-Type', 'application/json');

    return this.httpClient
    .post(
      'http://sample.com/login', 
       JSON.stringify({ email, password }), 
       { headers: headers }
    )
    .map(
        (response: any) => {
          localStorage.setItem('auth_token', response.token);
          this.loggedIn = true;
          return response;
        });
   }

    isLoggedIn() {
      if (localStorage.getItem('auth_token')) {
        return this.loggedIn = true;
      }
    }

   logout() {
     localStorage.removeItem('auth_token');
     this.loggedIn = false;
    }
}

authguard.ts

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private router: Router, private authService: AuthService) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {

    if (this.authService.isLoggedIn()) {
      // logged in so return true
      return true;
    }

    else {
      // not logged in so redirect to login page with the return url
      this.router.navigate(['signin'])
      return false;
      }
  }
}
Godmother answered 11/9, 2017 at 2:4 Comment(6)
You can force app to clear login status when leaving the app.Preventer
@Pengyy. But i think that's not how professional web app works, right? They still can access their account after they close the browser.Godmother
This is depend on your app's authentication strategy. For me, it's strange that app can be still logged in but API is not reachable any more.Preventer
what is happening on logout?Wristband
@Kuncevic. Do you mean when i click the logout button? It logouts the app and i won't be able to access the homepageGodmother
@Kuncevic. This is how my app works. When i forgot to logout and i open the browser again, i still can access the homepage and have data in it. After some time, the token expires but my problem is i'm still on my homepage but have no data in it, i should be redirected to the login pageGodmother
W
8

I think there is two solution you can play with.

The first one you can just call you logout function when browser getting closed like:

  @HostListener('window:unload', ['$event'])
  handleUnload(event) {
    this.auth.logout();
  }

https://developer.mozilla.org/de/docs/Web/Events/unload

OR

 @HostListener('window:beforeunload', ['$event'])
      public handleBeforeUnload(event) {
        this.auth.logout();
      }

https://developer.mozilla.org/de/docs/Web/Events/beforeunload

This way alway when browser getting closed your this.auth.logout(); will be called automatically.

Second you can install library like angular2-jwt it can help you to detect if token has expired

jwtHelper: JwtHelper = new JwtHelper();

useJwtHelper() {
  var token = localStorage.getItem('token');

  console.log(
    this.jwtHelper.decodeToken(token),
    this.jwtHelper.getTokenExpirationDate(token),
    this.jwtHelper.isTokenExpired(token)
  );
}
Wristband answered 11/9, 2017 at 2:41 Comment(9)
What do you recommend, if i close browser, i will call logout? OR When i forgot to logout and i open the browser again, i still can access the homepage and have data in it. After some time, the token expires but my problem is i'm still on my homepage but have no data in it, i should be redirected to the login pageGodmother
I think you better use the library like angular2-jwt this way you can handle your case in proper way it has all functionality you need.Wristband
@Kuncevice. Does it support angular 4? I have an error installing itGodmother
@Godmother Yes it is supports angular 4 I just installed that in the app and no issues. Make sure you are installing angular2-jwt not angular-jwtWristband
what exactly you are having problem with?Wristband
I just want to implement angular2-jwt in my code. If it is ok with you that you can write code on my code :)Godmother
I think you have to check that tutorial first jasonwatmore.com/post/2016/08/16/… and check the docs github.com/auth0/angular2-jwt, then if you have any issues just create another questionWristband
Let us continue this discussion in chat.Wristband
Is there another solution to this problem except the above solutions?Conah
C
9

You can do this using http interceptors.

intercept(req: HttpRequest<any>, next: HttpHandler) {
  if(!localStorage.getItem('token'))
    return next.handle(req);

  // set headers
  req = req.clone({
    setHeaders: {
      'token': localStorage.getItem('token')
    }
  })

  return next.handle(req).do((event: HttpEvent<any>) => {
    if(event instanceof HttpResponse){
      // if the token is valid
    }
  }, (err: any) => {
    // if the token has expired.
    if(err instanceof HttpErrorResponse){
      if(err.status === 401){
        // this is where you can do anything like navigating
        this.router.navigateByUrl('/login');
      }
    }
  });
}

Here's the full solution

Conah answered 14/6, 2018 at 6:23 Comment(0)
W
8

I think there is two solution you can play with.

The first one you can just call you logout function when browser getting closed like:

  @HostListener('window:unload', ['$event'])
  handleUnload(event) {
    this.auth.logout();
  }

https://developer.mozilla.org/de/docs/Web/Events/unload

OR

 @HostListener('window:beforeunload', ['$event'])
      public handleBeforeUnload(event) {
        this.auth.logout();
      }

https://developer.mozilla.org/de/docs/Web/Events/beforeunload

This way alway when browser getting closed your this.auth.logout(); will be called automatically.

Second you can install library like angular2-jwt it can help you to detect if token has expired

jwtHelper: JwtHelper = new JwtHelper();

useJwtHelper() {
  var token = localStorage.getItem('token');

  console.log(
    this.jwtHelper.decodeToken(token),
    this.jwtHelper.getTokenExpirationDate(token),
    this.jwtHelper.isTokenExpired(token)
  );
}
Wristband answered 11/9, 2017 at 2:41 Comment(9)
What do you recommend, if i close browser, i will call logout? OR When i forgot to logout and i open the browser again, i still can access the homepage and have data in it. After some time, the token expires but my problem is i'm still on my homepage but have no data in it, i should be redirected to the login pageGodmother
I think you better use the library like angular2-jwt this way you can handle your case in proper way it has all functionality you need.Wristband
@Kuncevice. Does it support angular 4? I have an error installing itGodmother
@Godmother Yes it is supports angular 4 I just installed that in the app and no issues. Make sure you are installing angular2-jwt not angular-jwtWristband
what exactly you are having problem with?Wristband
I just want to implement angular2-jwt in my code. If it is ok with you that you can write code on my code :)Godmother
I think you have to check that tutorial first jasonwatmore.com/post/2016/08/16/… and check the docs github.com/auth0/angular2-jwt, then if you have any issues just create another questionWristband
Let us continue this discussion in chat.Wristband
Is there another solution to this problem except the above solutions?Conah

© 2022 - 2024 — McMap. All rights reserved.