Check token alive in Ionic 2
If you are involve in hybrid applications, you may know that Ionic Framework is one of the best solutions to do it. Why is that? Because it brings you a lot of re-useful visual and native components, like Camera, Contacts, Geolocation and more.
Ionic 2 is the evolution of Ionic Framework which use Angular 2 like core code, but this is old news for you. What do you really know is that are not too much documentation and how to do something in the new way.
One of my impediments was checking the token alive. All examples were using cloud solutions like Firebase or Auth0, but I already has my own server with my API developed. So I wanted to do the entire solution and check up on my app, but how?
This was my Use Case:
- Open the app and login in the form.
- Send to the server the user and password.
- The server response successful and return the JWT token with an expiration time.
- Navigate through the pages and check if the token is alive in any try.
- If token is not alive, redirect to the login page.
To do It, you will notice the Lifecycle events related to the NavController, which gives you hooks when you are entering or leaving pages. With this, you can check before rendering a new page, if the token is alive and redirect or do something else if it is not. One of them is the IonViewCanEnter function. It must to return a Boolean or a Promise and it is false, . I made a heritable component class to do the goToPage function and the token check:
import { NavController} from 'ionic-angular';
import { LoginPage } from '../pages/login/login';
import { LoginService } from '../providers/login-service';
export class SuperComponent {
constructor(public loginService: LoginService, public navCtrl: NavController) { }
protected goToPage(componentClass: any) {
this.navCtrl.push(componentClass).catch(() => {
//The push has failed
this.navCtrl.setRoot(LoginPage);
});
}
ionViewCanEnter() {
return this.loginService.isAlive();
}
}
We assumed that this.loginService.isAlive() is a method which gets the token in local storage, decodes it and check the expiration date. Then it returns a resolve or rejected promise.
When you push a Page into NavController and it fails, you could catch this and set LoginPage like root. The fail is executed when the ionViewCanEnter of the pushed Page returns false or a rejected Promise.
Then you have to extend the SuperComponent Class in the pages that you want to control this, injecting the LoginService and the NavController:
import { Component } from '@angular/core';
import { NavController} from 'ionic-angular';
import { SuperComponent } from '../../shared/supercomponent';
import { ContactPage } from '../contact/contact';
import { LoginService } from '../../providers/login-service';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage extends SuperComponent{
constructor(public navCtrl: NavController, public loginService: LoginService) {
//Injecting to the Supercomponent
super(loginService, navCtrl);
}
goToContactPage(){
this.goToPage(ContactPage);
}
}
When the link fires the goToContactPage method, it use the heritable goToPage method. The ContactPage must to extends the SuperComponent too, to hook the ionViewCanEnter.
Another complete options to mobile apps are storing the credentials in a Secure Storage and try to login automatically when the token has expired or use a refresh token like OAuth2. This is because mobile apps should be logged once and not each time. But, don’t use a unique and not expirable token, this is a bad and hackable idea.