,

Ionic 5|4 Login & Registration Form using Guard Working UI Example Application

Ionic 4/5 is using Angular Routing, so it becomes very easy to add authentication in an Ionic application using Auth Guards. In this post, we will create a simple login application to quickly demonstrate how we can implement Angular Guards in Ionic to prevent access to pages if the user is not logged in. This…

By.

min read

Ionic 4/5 is using Angular Routing, so it becomes very easy to add authentication in an Ionic application using Auth Guards.

In this post, we will create a simple login application to quickly demonstrate how we can implement Angular Guards in Ionic to prevent access to pages if the user is not logged in. This is very common and required by most of the real-world application where we don’t want some pages to be accessed without proper authentication.

Version Check

@ionic/cli 

   _             _
  (_) ___  _ __ (_) ___
  | |/ _ \| '_ \| |/ __|
  | | (_) | | | | | (__
  |_|\___/|_| |_|_|\___| CLI 6.4.1


#Update to the latest version of Ionic CLI by running following NPM command:

$ npm install -g @ionic/cli

Create a new Ionic Application

We will create an Ionic application using latest Ionic CLI. Make sure you have the latest version of NPM and Ionic CLI installed

$ npm install -g @ionic/cli</pre>
 

Create a new Angular Ionic blank application using below CMD command given below.
<pre class="wp-block-prismatic-blocks"><code class="language-javascript">$ ionic start IonicAuthGaurds blank --type=angular
$ ionic IonicAuthGaurds</pre>
 
<h4>Add Storage Module in Ionic App</h4>
Here we will on store values in browser storage for the dummy login process, in real-world applications as well we use web storages but login authentication happens on the server-side.

Install storage package using following npm command
<pre class="wp-block-prismatic-blocks"><code class="language-javascript">$ npm install --save @ionic/storage</pre>
 

As we have an Ionic application, we will create Login & Dashboard pages, two new services Authentication, and Auth Guard by running following commands
<pre class="wp-block-prismatic-blocks"><code class="language-javascript">$ ionic g page login
$ ionic g page dashboard
$ ionic g service services/authentication
$ ionic g service services/authGuard</pre>
 

Next import services and Storage module in the <strong>app.module.ts</strong> file as shown below
<pre class="lang:js mark:12,13,29,30 decode:true">import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { IonicStorageModule } from '@ionic/storage';
import { AuthGuard } from './services/AuthGuard.service';
import { AuthenticationService } from './services/Authentication.service';

@NgModule({
  declarations: [
    AppComponent
  ],
  entryComponents: [],
  imports: [
    BrowserModule, 
    IonicModule.forRoot(), 
    AppRoutingModule,
    IonicStorageModule.forRoot()
  ],
  providers: [
    StatusBar,
    SplashScreen,
    AuthGuard,
    AuthenticationService,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
</pre>
In <code><strong>AuthenticationService</strong> add some basic methods like <strong>login()</strong>, <strong>logout()</strong>, <strong>isLoggedIn()</strong> and <strong>isAuthenticated()</strong>

In "~services/Authentication.service.ts" add the following code
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Storage } from '@ionic/storage';
import { ToastController, Platform } from '@ionic/angular';
import { BehaviorSubject } from 'rxjs';


@Injectable()
export class AuthenticationService {

  authState = new BehaviorSubject(false);

  constructor(
    private router: Router,
    private storage: Storage,
    private platform: Platform,
    public toastController: ToastController
  ) {
    this.platform.ready().then(() => {
      this.ifLoggedIn();
    });
  }

  ifLoggedIn() {
    this.storage.get('USER_INFO').then((response) => {
      if (response) {
        this.authState.next(true);
      }
    });
  }


  login() {
    var dummy_response = {
      user_id: '007',
      user_name: 'test'
    };
    this.storage.set('USER_INFO', dummy_response).then((response) => {
      this.router.navigate(['dashboard']);
      this.authState.next(true);
    });
  }

  logout() {
    this.storage.remove('USER_INFO').then(() => {
      this.router.navigate(['login']);
      this.authState.next(false);
    });
  }

  isAuthenticated() {
    return this.authState.value;
  }



}</pre>
<h4>Add Angular Guard CanActive to Prevent Unauthorized Access</h4>
Angular provides Guards to prevent navigation and loading of routes. To implement Guards we add <code>canActivate parameter attribute on Routes in the app-routing.module.ts file as shown below
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AuthGuard } from './services/AuthGuard.service';

const routes: Routes = [
  { path: '', redirectTo: 'login', pathMatch: 'full' },
  { path: 'login', loadChildren: './login/login.module#LoginPageModule' },
  {
    path: 'dashboard',
    loadChildren: './dashboard/dashboard.module#DashboardPageModule',
    canActivate: [AuthGuard]
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

In another service <strong>AuthGuard</strong>, we will implement <strong>CanActivate</strong> to convert this service into and an Angular Guard. Add the following code in "~services/AuthGuard.service.ts" file to be used in <strong>canActivate</strong> parameter in Routes

import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { AuthenticationService } from './Authentication.service';


@Injectable()
export class AuthGuard implements CanActivate {
    constructor(
      public authenticationService: AuthenticationService
        ) {}

    canActivate(): boolean {
      return this.authenticationService.isAuthenticated();
    }

}

Check User Authentication on App Load

To check if the user is logged in on app load, we will call <strong>isAuthenticated()</strong> method from app.component.ts in the platform ready()

import { Component } from '@angular/core';

import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { Router } from '@angular/router';
import { AuthenticationService } from './services/Authentication.service';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html'
})
export class AppComponent {
  constructor(        
    private router: Router,
    private platform: Platform,
    private splashScreen: SplashScreen,
    private statusBar: StatusBar,
    private authenticationService: AuthenticationService
  ) {
    this.initializeApp();
  }

  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();


      this.authenticationService.authState.subscribe(state => {
        if (state) {
          this.router.navigate(['dashboard']);
        } else {
          this.router.navigate(['login']);
        }
      });

    });
  }
}

Update Login and Dashboard Components

On the login page, we will have a Login button which will add dummy user values in Session. There is also a "Go to dashboard" link to demonstrate <strong>CanActive</strong> Guard usage. On this link, we are simply redirecting to dashboard page, but a user is not authenticated yet by clicking on Login so it will alert the user by an alert. On the Dashboard, we will have a logout button to clear authentication state and move back to login.

Login HTML and Component code

login.page.html

  <ion-button (click)="loginUser()">
    login
  </ion-button>

  <a [routerLink]="['/dashboard']">Go to dashboard</a>

login.page.ts

import { Component, OnInit } from '@angular/core';
import { AuthenticationService } from '../services/Authentication.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.page.html',
  styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {

  constructor(
    private authService: AuthenticationService
     ) { }

  ngOnInit() {
  }

  loginUser(){
    this.authService.login()
  }

}

Similarly, on the Dashboard page in HTML template, we have a logout button ad in a component we will call logout() method from AuthenticationService

dashboard.page.html

<ion-content padding>
    <ion-button (click)="logoutUser()">
        Logout
      </ion-button>
</ion-content>

dashboard.page.ts

import { Component, OnInit } from '@angular/core';
import { AuthenticationService } from '../services/Authentication.service';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.page.html',
  styleUrls: ['./dashboard.page.scss'],
})
export class DashboardPage implements OnInit {

  constructor(
    private authService: AuthenticationService
    ) { }

  ngOnInit() {
  }

  logoutUser(){
    this.authService.logout();
  }

}

That's it now you can run the application to check Login flow using Angular Guard on dashboard link.

 

11 responses to “Ionic 5|4 Login & Registration Form using Guard Working UI Example Application”

  1. DigCrt Avatar
    DigCrt

    All great thanks!!!

  2. Federico Avatar
    Federico

    The big issue with this approach (that is the same that i saw in many others tutorials, btw) is that authguard check BEFORE that autentication service even be created, so if you refresh the page the first thing you say is app root (whatever it is, in my case login page) and only AFTER will subscribe for changing in authState (that will be fired in constructor service itself). Basically, login page appears for 1 sec or so. And i don’t like it.

    1. ckl Avatar

      Hi, how to solve the 1 sec display? What alternative approach you suggest?

    2. Uday Ghulaxe Avatar

      How Did you solve this issue? Any other way to fix loading of login page for a 1-2 seconds

  3. Kamlesh Avatar

    Thank you for nice article. This example working fine.

    But, How I can handle hardware back button on login page after user logged in, both in sidebar and tabs page application. In device after login success tabs page comes than after press back button than login page show again 🙁

    I tried to add a new authGaurd for login page, but blank page comes for few sec.

    How can handle this? Please post a example.

    Thanks,
    Kamlesh

    1. Mauro Avatar
      Mauro

      instead of

      this.router.navigate([‘dashboard’]);

      use

      this.navCtrl.navigateRoot(‘dashboard’)

      to do this you have to import NavController first:

      import { NavController } from ‘@ionic/angular’;

      and in your constructor:

      constructor(private navCtrl: NavController)

  4. juhee Avatar
    juhee

    Thank you. But there’s an error. Why is that? I did the same thing.
    Error: StaticInjectorError(AppModule)[AuthGuardService -> AuthenticationService]:
    StaticInjectorError(Platform: core)[AuthGuardService -> AuthenticationService]:
    NullInjectorError: No provider for AuthenticationService!

  5. Mary User Avatar
    Mary User

    Thanks, nice simple explanation.
    How would you handle different access Levels? e.g. in WordPress you have Admin, Authors etc.

    Say I have Level 1, Level 2, Level 3 users how would I save, and use their access level using this technique?

    1. Athishay Avatar
      Athishay

      I guess you need to take care of that in your backend API’s.

Leave a Reply

Your email address will not be published. Required fields are marked *