简体   繁体   中英

Jwt token expiration in angular 6

I am making an angular app that uses jwt to authenticate db calls.However the issue
is that when the token expires at the server,the app starts giving blank pages instead of data as the expired token is still in the local storage.After some research I found out that jwt2 library can be used to track token expiry.However even after using that I have to refresh the page to redirect to the login page.I am still able to move within the components. I want that as soon as the token is expired the login page comes or the token is refreshed and even when moving between components,if the token is expired the user should be redirected to login page or the token should be refreshed.I don't know what else I need to do.Please help.Thanks in advance.

Here is my auth guard:

Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

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

  canActivate(

    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    if (!(this.authService.isTokenExpired()) ){
      // logged in so return true
      console.log("Logged IN");
      return true;
    }

    // not logged in so redirect to login page with the return url
    this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
    return true;
  }
}

Here is my auth Service:

 const helper = new JwtHelperService();

    @Injectable({
      providedIn: 'root'
    })
    export class AuthService {

      constructor(private http: HttpClient) { }

    /*  public login<T>(username: string, password: string): Observable<HttpResponse<T>> {
        let headers = new HttpHeaders();
 const clientId = 'rosClient';
    const secret = 'secret';
        headers = headers.append("Authorization", "Basic " + btoa(`${username}:${password}`));
        headers = headers.append("Content-Type", "application/x-www-form-urlencoded");
        return this.http.get<T>('/auth/login', {
          headers: headers,
          observe: 'response'
        });
      }*/


      public login<T>(username: string, password: string): Observable<HttpResponse<T>> {
        let headers = new HttpHeaders();
        const clientId = 'clientid';
        const secret = 'secret';
        headers = headers.append('Authorization', 'Basic ' + btoa(`${clientId}:${secret}`));
        headers = headers.append('Content-Type', 'application/x-www-form-urlencoded');
        const params = new HttpParams().set('username', username).set('password', password).set('grant_type', 'password').set('scope', 'read');
        return this.http.post<T>('/oauth/token', params.toString(), {
          headers,
          observe: 'response'
        });
      }

      public logout<T>() {
        this.http.post('/oauth/revoke_token', '', {}).subscribe();
      }

      getToken(): string {
        return localStorage.getItem(TOKEN_NAME);
      }



      isTokenExpired(token?: string): boolean {
        if(!token) token = this.getToken();
        if(!token) return true;

        const date = helper.getTokenExpirationDate(token);
        console.log(date);
        if(date === undefined) return false;
        return !(date.valueOf() > new Date().valueOf());
      }
    }

Below is my error interceptor:

@Injectable()
export class H401Interceptor implements HttpInterceptor {

    constructor(private authService: AuthService) { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(request).pipe(catchError(err => {
            if (err.status === 401) {
                // auto logout if 401 response returned from api
                // this.authService.logout();
                // location.reload(true);
                localStorage.removeItem('currentUser');
            }

            const error = err.error.message || err.statusText;
            return throwError(error);
        }));
    }
}

You can use HttpInterceptor, when the backend answers with '401 Unauthorized', you delete the token and navigate to the sign in page. Here's a working code:

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone({
      setHeaders: {
        Authorization: `Bearer ${this.storageService.retrieve(tokenKey)}`,
        'Content-Type': 'application/json'
      }
    });
    return next.handle(request).pipe(
      catchError(
        (err, caught) => {
          if (err.status === 401){
            this.handleAuthError();
            return of(err);
          }
          throw err;
        }
      )
    );
  }
  private handleAuthError() {
    this.storageService.delete(tokenKey);
    this.router.navigateByUrl('signIn');
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM