
ionic2: how to automatically redirect to the login page
I got a point where it was important to implement an automatic redirection to the login page when the user tries to access a page that should be accessed from logged users only.
I needed something easy to add on every “reserved” page.
The first attempt was to create a service, I immediately faced with a problem:
The NavController (needed for the page change) can’t work form inside a service.
This is the error I got:
No provider for NavController
https://github.com/driftyco/ionic/issues/9581
I decided for a component.
The working principle is easy:
- When the app starts deletes the storage obj “user”
- Immediately after it tries to get a new obj from an api call by using the access token stored in the storage obj “session”
- If the call succeeds it saves the new storage obj “user”
- Every page that needs to be “protected” includes the component <login-redirect>
- <login-redirect> checks if the storage obj “user” exists, if it does not, it redirects to the login page passing a parameter used from the login component to redirect to a page(or back) if the login succeeds
- When the login succeeds, the login component calls the api again to fetch and set the storage obj “user”
- The login page redirects to the right page (passed as parameter on the point 5)
Let’s see some code:
1 |
$ionic g component login-redirect |
I don’t need to modify the template or the scss file.
controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import { Component,Input } from '@angular/core'; import { Storage } from '@ionic/storage'; import { NavController, NavParams } from 'ionic-angular'; @Component({ selector: 'login-redirect', templateUrl: 'login-redirect.html' }) export class LoginRedirectComponent { @Input() public redirect: string; constructor(public storage:Storage, public navCtrl:NavController) { storage.get('user').then((user) => { if (!user) { if (this.redirect) this.navCtrl.setRoot('LoginPage',{opt:{dismiss:false,redirect:this.redirect}}); }; }); } } |
The @Input() is used to read from the tag’s attribute “redirect” the page to pass to the login component (we’ll see it later)
The login component has some logic like this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
............... // to read the paramaters this.loginOpts = navParams.get('opt'); ........................... //login let result = await this.api.call('post','login',obj); if (result.code == 200) { //I am logged in await this.storage.set('session', result.data); //I save the auth token let user_me = await this.api.call('get','users/me/'); //I fetch the user data associated to the auth token if ( user_me.code == 200 ) { await this.storage.set('user', user_me.data); //I set the user data in the storage obj "user" if (typeof _.get(this.loginOpts,'redirect') == 'string') this.navCtrl.setRoot(this.loginOpts.redirect); //I Redirect the user to the page passed in input ................... |
In every page I want to reserve for logged users, I add this line in the template
1 |
<login-redirect [redirect]="'PAGE I WANT TO GO AFTER THE LOGIN'"></login-redirect> |
This method works fine, anyway I don’t know yet if this is the best method to achieve the result, for example a little side effect is that the page we want to protect appears for a short time before the redirection.
As soon as I discover a better method I’ll share it.
Any suggestion?