简体   繁体   中英

How to logout when token expires in ionic3?

When user logs in then next day it keeps caches and shows destroyed app. How can we redirect the user to the login page once his/her token is expired? We are using JWT with ionic 3 based on Angular 6. Here is the code:

Token service (provider)

import { Injectable } from '@angular/core';
import { Storage } from '@ionic/storage';

@Injectable()
export class TokenProvider {
  constructor(private storage: Storage) { }

  SetToken(token) {
    return this.storage.set('auth-token', token);
  }

  async GetToken() {
    return await this.storage.get('auth-token');
  }

  DeleteToken() {
    this.storage.remove('auth-token');
  }

  async GetPayload() {
    const token = await this.storage.get('auth-token');
    let payload;
    if (token) {
      payload = token.split('.')[1];
      payload = JSON.parse(window.atob(payload));
    }

    return payload.data;
  }
}

Interceptor

import { switchMap } from 'rxjs/operators';
import { TokenProvider } from './token/token';
import { Observable } from 'rxjs/Observable';
import { fromPromise } from 'rxjs/observable/fromPromise';
import { Injectable } from '@angular/core';
import {
  HttpInterceptor,
  HttpRequest,
  HttpHandler,
  HttpEvent
} from '@angular/common/http';

@Injectable()
export class TokenInterceptor implements HttpInterceptor {
  constructor(private tokenProvider: TokenProvider) {}

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    return fromPromise(this.tokenProvider.GetToken()).pipe(
      switchMap(token => {
        const headersConfig = {
          'Content-Type': 'application/json',
          Accept: 'application/json'
        };
        if (token) {
          headersConfig['Authorization'] = `beader ${token}`;
        }
        const _req = req.clone({ setHeaders: headersConfig });
        return next.handle(_req);
      })
    );
  }
}

app component:

 this.storage.get('auth-token').then(token => {
        if (token) {
          this.tokenProvider.GetPayload().then(data => {
            const params = {
              room: 'global',
              user: data.username
            };
            this.socket.emit('online', params);
          });
          this.nav.setRoot('TabsPage');
        } else {
          this.nav.setRoot('LoginPage');
        }
      });
    });
  }

But it seems still not working. When the token expires it still keeps the page active without any data looks like a destroyed app. How can we fix this issue and redirect user to the Login page?

Two ways you can handle the Token expiration,

  1. In Interceptor, You can get error codes in error block.

import { switchMap } from 'rxjs/operators';
import { TokenProvider } from './token/token';
import { Observable } from 'rxjs/Observable';
import { fromPromise } from 'rxjs/observable/fromPromise';
import { Injectable } from '@angular/core';
import {
  HttpInterceptor,
  HttpRequest,
  HttpHandler,
  HttpEvent
} from '@angular/common/http';

@Injectable()
export class TokenInterceptor implements HttpInterceptor {
  constructor(private tokenProvider: TokenProvider) {}

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    return fromPromise(this.tokenProvider.GetToken()).pipe(
      switchMap(token => {
        const headersConfig = {
          'Content-Type': 'application/json',
          Accept: 'application/json'
        };
        if (token) {
          headersConfig['Authorization'] = `beader ${token}`;
        }
        const _req = req.clone({ setHeaders: headersConfig });
        return next.handle(_req).do((event: HttpEvent<any>) => {
      if (event instanceof HttpResponse) {
        // do stuff with response if you want
      }
    }, (err: any) => {
      if (err instanceof HttpErrorResponse) {
        if (err.status === 401) {
          // redirect to the login route
          // or show a modal
        }
      }
    });
      })
    );
  }
}
  1. You can add AuthGuard, CanActivate in route to check token authentication.
import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuardService implements CanActivate {
  constructor(public auth: AuthService, public router: Router) {}
  canActivate(): boolean {
    if (!this.auth.isAuthenticated()) {
      this.router.navigate(['login']);
      return false;
    }
    return true;
  }
}

Use event in this case. Publish event when login request get error as token expired or invalid credential and subscribe it on app.component.ts where you can set login page as root page.

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