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 codeimport { 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 belowimport { 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 Routesimport { 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.
Category: Angular
Leave a Reply