Ionic 3 Skip Login if User Logged in Updated FREE
Ionic 3 Skip Login if User Logged in
Near apps require a certain kind of boilerplate lawmaking, with login, introduction folio, routing and security – and that's what we volition create in this tutorial.
We will start with a tabs template from Ionic and use Capacitor to store some data. Additionally nosotros will secure the routing in our app and use a dummy JWT from the reqres.in API.
At the end you lot'll take a complete understanding about routing, securing your app, using guards and reactive forms and all the nuts to start your next Ionic app!
If you need help with average more often, too bank check out my tool KickoffIonic.
Starting our Ionic v App Navigation
As promised, we start with a tabs template today so nosotros tin can save a bit of fourth dimension. We generate a service that will keep our hallmark logic, additional pages for the introduction and login screen, and guards to add some cool functionality to our app:
1 2 iii 4 5 6 7 viii nine x 11 12 13 14 xv xvi 17 18 xix 20 21 | ionic start devdacticApp tabs -- type = angular -- capacitor cd . / devdacticApp # Manage your authentication state (and API calls) ionic g service services / authentication # Additional Pages ionic one thousand page pages / intro ionic g folio pages / login # Secure inside area ionic g baby-sit guards / auth -- implements CanLoad # Prove intro automatically once ionic g baby-sit guards / intro -- implements CanLoad # Automatically log in users ionic k guard guards / autoLogin -- implements CanLoad # Install Capacitor Storage for v3 npm install @ capacitor / storage |
We tin actually tell the CLI already which interface within the baby-sit should be implemented, which will come up in very handy later on.
Because we will do a piddling dummy HTTP request, besides add together the according module to the src/app/app.module.ts:
1 2 3 4 5 half-dozen 7 8 ix 10 11 12 13 xiv xv sixteen 17 xviii nineteen 20 21 22 23 24 25 26 27 28 29 xxx | import { NgModule } from '@angular/core' ; import { BrowserModule } from '@angular/platform-browser' ; import { RouteReuseStrategy } from '@angular/router' ; import { IonicModule , IonicRouteStrategy } from '@ionic/athwart' ; import { SplashScreen } from '@ionic-native/splash-screen/ngx' ; import { StatusBar } from '@ionic-native/status-bar/ngx' ; import { AppRoutingModule } from './app-routing.module' ; import { AppComponent } from './app.component' ; import { HttpClientModule } from '@angular/common/http' ; @ NgModule ( { declarations : [ AppComponent ] , entryComponents : [ ] , imports : [ BrowserModule , IonicModule . forRoot ( ) , AppRoutingModule , HttpClientModule ] , providers : [ StatusBar , SplashScreen , { provide : RouteReuseStrategy , useClass : IonicRouteStrategy } , ] , bootstrap : [ AppComponent ] , } ) consign course AppModule { } |
Nosotros will use the Capacitor Storage plugin so we don't need any additional Cordova plugin or other library.
Routing Setup
Our routing file is a bit messed upwards from the generation of additional pages, and we also want to add together a few guards to our pages. Nosotros have the post-obit guards for specific reasons:
- IntroGuard: Check if the user has already seen the intro and show the page if not
- AutoLoginGuard: Automatically log in a user on app startup if already authenticated earlier
- AuthGuard: Secure the internal pages of your app
We can use multiple guards for a page, and we utilise canLoad
instead of canActivate
since this will protect the whole lazy loaded module and not fifty-fifty load the file if the user is not immune to admission a path!
By securing the /tabs path at the top level, we likewise automatically secure every other path and page that you might afterward add to your tabs routing, since the guard will always exist applied in that case.
Become ahead now and change the src/app/app-routing.module.ts to:
1 ii 3 4 v 6 7 viii ix ten 11 12 13 14 15 16 17 xviii 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | import { AuthGuard } from './guards/auth.baby-sit' ; import { NgModule } from '@angular/core' ; import { PreloadAllModules , RouterModule , Routes } from '@athwart/router' ; import { IntroGuard } from './guards/intro.guard' ; import { AutoLoginGuard } from './guards/automobile-login.guard' ; const routes : Routes = [ { path : 'login' , loadChildren : ( ) = > import ( './pages/login/login.module' ) . so ( m = > m . LoginPageModule ) , canLoad : [ IntroGuard , AutoLoginGuard ] // Bank check if we should prove the introduction or forward to within } , { path : 'intro' , loadChildren : ( ) = > import ( './pages/intro/intro.module' ) . so ( g = > m . IntroPageModule ) } , { path : 'tabs' , loadChildren : ( ) = > import ( './tabs/tabs.module' ) . then ( grand = > m . TabsPageModule ) , canLoad : [ AuthGuard ] // Secure all child pages } , { path : '' , redirectTo : '/login' , pathMatch : 'total' } ] ; @ NgModule ( { imports : [ RouterModule . forRoot ( routes , { preloadingStrategy : PreloadAllModules } ) ] , exports : [ RouterModule ] } ) export class AppRoutingModule { } |
Since we renamed the paths a chip nosotros at present come to the tabs routing file with only an empty path, beacuse the "tabs" part of the URL will already exist resolved. Check out my Athwart routing tutorial for more information about routing as well.
Therefore, we remove the parent path and slightly modify the redirect logic within the src/app/tabs/tabs-routing.module.ts now too:
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 28 29 30 31 32 33 34 35 | import { NgModule } from '@athwart/core' ; import { RouterModule , Routes } from '@athwart/router' ; import { TabsPage } from './tabs.page' ; const routes : Routes = [ { path : '' , component : TabsPage , children : [ { path : 'tab1' , loadChildren : ( ) = > import ( '../tab1/tab1.module' ) . and then ( m = > one thousand . Tab1PageModule ) } , { path : 'tab2' , loadChildren : ( ) = > import ( '../tab2/tab2.module' ) . then ( 1000 = > one thousand . Tab2PageModule ) } , { path : 'tab3' , loadChildren : ( ) = > import ( '../tab3/tab3.module' ) . then ( m = > m . Tab3PageModule ) } , { path : '' , redirectTo : '/tabs/tab1' , pathMatch : 'full' } ] } ] ; @ NgModule ( { imports : [ RouterModule . forChild ( routes ) ] , exports : [ RouterModule ] } ) export class TabsPageRoutingModule { } |
We'll see how each of the unlike guards work along the tutorial, for now we get-go with the introduction logic.
Creating the Introduction Page
Of grade we could also make the tutorial folio only the first page, but usually you don't want to bore your users more frequently than necessary with this page.
Therefore the thought is to use a guard that checks if we've already seen the tutorial and shows it if not. Otherwise, the guard volition return true
and the page the user wanted to access will exist shown as usual.
Within our routing nosotros accept only added this baby-sit to the login page, but of course it could be added to other pages as well. But since the login is the very get-go page that would exist shown when the app is opened on a device, this is the place where it really makes sense.
The guard will make use of the Capacitor Storage plugin to check for a sure central, which is really a cord and non a boolean. This API merely allows to store capricious strings, just that'southward fine for united states of america.
Go ahead at present and alter the src/app/guards/intro.baby-sit.ts to:
ane ii 3 4 five half dozen 7 8 nine 10 xi 12 13 14 15 16 17 18 19 20 21 22 23 24 | import { Injectable } from '@athwart/cadre' ; import { CanLoad , Router } from '@angular/router' ; import { Storage } from '@capacitor/storage' ; consign const INTRO_KEY = 'intro-seen' ; @ Injectable ( { providedIn : 'root' } ) export grade IntroGuard implements CanLoad { constructor ( private router : Router ) { } async canLoad ( ) : Promise < boolean > { const hasSeenIntro = await Storage . get ( { key : INTRO_KEY } ) ; if ( hasSeenIntro && ( hasSeenIntro . value === 'true' ) ) { return true ; } else { this . router . navigateByUrl ( '/intro' , { replaceUrl : true } ) ; render simulated ; } } } |
And so if needed, we directly transition to the introduction without even showing the login page. That means, no flash of a folio you lot don't want to present!
Inside the introduction nosotros volition add some slides, which are very common to present your apps features. Y'all can even access the slides chemical element from lawmaking every bit a ViewChild
to interact directly with them to eastward.g. coil to the next/previous slide.
In one case the users finishes the introduction, nosotros will write the according key to our storage and move on to our login page. From that point on, the user won't meet that page again!
Open up the src/app/pages/intro/intro.page.ts and change it to:
1 2 3 iv 5 6 7 8 9 10 11 12 13 xiv 15 xvi 17 18 xix xx 21 22 23 24 25 26 27 28 29 | import { Component , OnInit , ViewChild } from '@angular/core' ; import { IonSlides } from '@ionic/angular' ; import { INTRO _KEY } from 'src/app/guards/intro.guard' ; import { Router } from '@angular/router' ; import { Storage } from '@capacitor/storage' ; @ Component ( { selector : 'app-intro' , templateUrl : './intro.page.html' , styleUrls : [ './intro.page.scss' ] , } ) export class IntroPage implements OnInit { @ ViewChild ( IonSlides ) slides : IonSlides ; constructor ( private router : Router ) { } ngOnInit ( ) { } adjacent ( ) { this . slides . slideNext ( ) ; } async kickoff ( ) { await Storage . set ( { key : INTRO_KEY , value : 'truthful' } ) ; this . router . navigateByUrl ( '/login' , { replaceUrl : true } ) ; } } |
Now we merely need a cool UI for the introduction, and we will make the slides cover the whole screen and besides use a groundwork epitome. Simply from HTML, the only thing we demand are the nuts and the buttons to trigger our deportment, and so change the src/app/pages/intro/intro.page.html to:
1 two 3 4 5 six 7 8 9 ten 11 12 13 14 xv sixteen 17 xviii 19 20 21 22 23 24 25 | < ion - content > < ion - slides pager = "true" > < ! -- Slide i -- > < ion - slide > < ion - text color = "light" > < img src = "https://i1.wp.com/ionicacademy.com/wp-content/uploads/2019/10/async-lawmaking-course.png" > < h1 > Hey at that place ! < / h1 > < p > This is an epic app because . . . < / p > < ion - button ( click ) = "side by side()" fill = "outline" colour = "light" > Next < / ion - push > < / ion - text > < / ion - slide > < ! -- Slide two -- > < ion - slide > < ion - text color = "light" > < img src = "https://i1.wp.com/ionicacademy.com/wp-content/uploads/2020/06/ionic-everywhere-course.png" > < h1 > It's Ionic ! < / h1 > < p > . . . it shows all the nuts you need ! < / p > < ion - push ( click ) = "commencement()" fill up = "outline" color = "light" > Beginning < / ion - push button > < / ion - text > < / ion - slide > < / ion - slides > < / ion - content > |
Now this won't look that skilful out of the box, only with a few lines of CSS inside the src/app/pages/intro/intro.page.scss everything becomes a lot better:
ion - content { -- background : #0081ca; } ion - slides { top : 100 % ; -- bullet - background - active : #fff; -- bullet - background : #000; } |
At present you can server your app and the first thing yous should meet is the introduction, which at the end guides you to the login.
If you reload the app at that betoken, the introduction won't be shown again since the guard evaluates that we've already seen the intro.
Creating the Authentication Logic
Now on to the login, which volition use a dummy implementation for retrieving a token. Usually you would plug in your own API, but by doing it similar this we can actually replicate a real world scenario pretty accurate.
If yous are edifice a real app check out Practical Ionic, my book to assistance you build more circuitous apps!
Our service will also concord a BehaviorSubject
, which we initialise with null in the beginning for a reason: Our baby-sit will later catch this very commencement value, which doesn't indicate a lot near the authentication state of a user. Therefore, nosotros can later easily filter out this value in the baby-sit so users can directly access pages of our app if they were previously authenticated.
When nosotros request a token after login, we volition store it locally (with a chip of RxJS fun since Storage returns a Hope and nosotros demand an Appreciable) and also set the new value to our behaviour subject.
After that, everyone calling the discipline would get the latest value, which is true
subsequently a login and set dorsum to false in the case of a logout.
Continue with the src/app/services/hallmark.service.ts and change it to:
1 2 iii 4 5 six 7 8 9 ten xi 12 13 14 fifteen sixteen 17 18 19 20 21 22 23 24 25 26 27 28 29 xxx 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | import { Injectable } from '@athwart/core' ; import { HttpClient } from '@angular/common/http' ; import { map , tap , switchMap } from 'rxjs/operators' ; import { BehaviorSubject , from , Observable , Subject } from 'rxjs' ; import { Storage } from '@capacitor/storage' ; const TOKEN_KEY = 'my-token' ; @ Injectable ( { providedIn : 'root' } ) consign class AuthenticationService { // Init with cypher to filter out the kickoff value in a guard! isAuthenticated : BehaviorSubject < boolean > = new BehaviorSubject < boolean > ( zilch ) ; token = '' ; constructor ( private http : HttpClient ) { this . loadToken ( ) ; } async loadToken ( ) { const token = await Storage . get ( { key : TOKEN _KEY } ) ; if ( token && token . value ) { console . log ( 'fix token: ' , token . value ) ; this . token = token . value ; this . isAuthenticated . next ( true ) ; } else { this . isAuthenticated . adjacent ( false ) ; } } login ( credentials : { e-mail , password } ) : Observable < any > { return this . http . post ( ` https : //reqres.in/api/login`, credentials).pipe( map ( ( data : whatever ) = > information . token ) , switchMap ( token = > { render from ( Storage . fix ( { cardinal : TOKEN_KEY , value : token } ) ) ; } ) , tap ( _ = > { this . isAuthenticated . adjacent ( true ) ; } ) ) } logout ( ) : Promise < void > { this . isAuthenticated . side by side ( false ) ; render Storage . remove ( { key : TOKEN_KEY } ) ; } } |
Now nosotros got all the logic in place in the background so we can build the login and later secure the pages of our app.
Edifice a User Login Page
Since we want to build a cool login procedure with decent error messages, we are going to apply a reactive form. And the kickoff step to utilise it is to add information technology to the module of the page, in our case that's the src/app/pages/login/login.module.ts:
1 ii 3 iv 5 6 7 eight nine 10 11 12 13 14 fifteen 16 17 18 19 20 21 | import { NgModule } from '@angular/core' ; import { CommonModule } from '@angular/common' ; import { FormsModule , ReactiveFormsModule } from '@athwart/forms' ; import { IonicModule } from '@ionic/angular' ; import { LoginPageRoutingModule } from './login-routing.module' ; import { LoginPage } from './login.folio' ; @ NgModule ( { imports : [ CommonModule , FormsModule , IonicModule , LoginPageRoutingModule , ReactiveFormsModule ] , declarations : [ LoginPage ] } ) export grade LoginPageModule { } |
At present we will utilize a but form with a few validators, that we will access from the template also. In gild to get the form elements more hands afterwards we also define two getter functions for them at the bottom of the class.
Within the actual login we volition utilise our service from before and handle the outcome: Either navigate forward or brandish an alert.
Notice how we set the replaceUrl
cardinal as an extra for the navigation! This prevents the case where users tin merely navigate back in the history of your application on Android, and nosotros'll apply it in a few places where it fits.
Information technology'southward basically the aforementioned equally calling a setRoot()
on the Ionic navigation controller, which as well simply proxies the Angular router.
Therefore continue with the src/app/pages/login/login.page.ts at present:
1 2 3 4 5 half dozen vii 8 nine 10 11 12 xiii 14 xv 16 17 eighteen nineteen twenty 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | import { AuthenticationService } from './../../services/authentication.service' ; import { Component , OnInit } from '@athwart/cadre' ; import { FormBuilder , FormGroup , Validators } from '@angular/forms' ; import { AlertController , LoadingController } from '@ionic/angular' ; import { Router } from '@athwart/router' ; @ Component ( { selector : 'app-login' , templateUrl : './login.page.html' , styleUrls : [ './login.folio.scss' ] , } ) export class LoginPage implements OnInit { credentials : FormGroup ; constructor ( private fb : FormBuilder , private authService : AuthenticationService , private alertController : AlertController , individual router : Router , private loadingController : LoadingController ) { } ngOnInit ( ) { this . credentials = this . fb . grouping ( { email : [ 'eve.holt@reqres.in' , [ Validators . required , Validators . email ] ] , password : [ 'cityslicka' , [ Validators . required , Validators . minLength ( 6 ) ] ] , } ) ; } async login ( ) { const loading = look this . loadingController . create ( ) ; wait loading . nowadays ( ) ; this . authService . login ( this . credentials . value ) . subscribe ( async ( res ) = > { await loading . dismiss ( ) ; this . router . navigateByUrl ( '/tabs' , { replaceUrl : truthful } ) ; } , async ( res ) = > { expect loading . dismiss ( ) ; const alert = await this . alertController . create ( { header : 'Login failed' , message : res . fault . mistake , buttons : [ 'OK' ] , } ) ; await alert . present ( ) ; } ) ; } // Easy access for form fields get email ( ) { return this . credentials . get ( 'email' ) ; } get password ( ) { render this . credentials . get ( 'password' ) ; } } |
I've added some default values, which are the combination for a successful login request – change them and the request will fail (you hear that Galadriel phonation?)!
We have prepared the form code, at present we but need an co-ordinate view effectually information technology. The form elements itself are non very special, simply for each field nosotros can check if it was touched or dirty, which basically means the user has interacted with the field.
You don't want to show all possible errors to your users before any interaction happened!
It's possible to check for specific errors of a field, and that's what we check inside those blocks to show specific error messages for dissimilar errors, which occur because we added the validators to these class elements in the pace before.
Additionally I added several buttons without functionality, but always make certain to use the blazon=button
on buttons inside a form that shouldn't trigger the submit – that type is only used on the push that should really trigger the submit activity.
With that information, become ahead and modify the src/app/pages/login/login.page.html:
1 2 3 iv 5 6 7 8 9 ten 11 12 13 14 fifteen 16 17 18 19 20 21 22 23 24 25 26 27 28 29 xxx 31 32 33 34 35 36 37 38 39 40 | < ion - header > < ion - toolbar color = "primary" > < ion - title > Devdactic App < / ion - championship > < / ion - toolbar > < / ion - header > < ion - content > < form ( ngSubmit ) = "login()" [ formGroup ] = "credentials" > < div class = "input-group" > < ion - item > < ion - input type = "email" placeholder = "Electronic mail" formControlName = "email" > < / ion - input > < / ion - item > < div * ngIf = "(electronic mail.dirty || email.touched) && email.errors" course = "errors" > < span * ngIf = "email.errors?.required" > Email is required < / bridge > < span * ngIf = "electronic mail.errors?.e-mail" > Email is invalid < / span > < / div > < ion - item > < ion - input type = "countersign" placeholder = "Countersign" formControlName = "password" > < / ion - input > < / ion - detail > < div * ngIf = "(password.dirty || password.touched) && countersign.errors" grade = "errors" > < bridge * ngIf = "countersign.errors?.required" > Password is required < / bridge > < bridge * ngIf = "countersign.errors?.minlength" > Password needs to be 6 characters < / bridge > < / div > < / div > < ion - button type = "submit" expand = "block" [ disabled ] = "!credentials.valid" > Log in < / ion - button > < ion - push type = "button" expand = "block" colour = "light" fill = "clear" > Not however a fellow member ? Sign up ! < / ion - push button > < ion - button type = "push" expand = "block" color = "tertiary" > < ion - icon name = "logo-google" slot = "commencement" > < / ion - icon > Sign in with Google < / ion - button > < ion - button type = "push" expand = "cake" color = "tertiary" > < ion - icon name = "logo-apple" slot = "start" > < / ion - icon > Sign in with Apple < / ion - button > < / form > < / ion - content > |
This doesn't look very special nonetheless, but yous can spice upwardly basically every view in almost minutes with some additional CSS. For example, we could define a background prototype, utilize some rounded borders and colors for stardom like this inside the src/app/pages/login/login.page.scss:
1 2 3 4 5 half dozen vii 8 9 10 11 12 13 14 fifteen 16 17 18 xix 20 21 22 | ion - content { -- padding - top : twoscore % ; -- padding - get-go : 10 % ; -- padding - end : 10 % ; -- background : url ( 'https://images.unsplash.com/photograph-1536431311719-398b6704d4cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1234&q=lxxx' ) 0 0 / 100 % 100 % no - echo ; } . input - grouping { groundwork : #fff; border - radius : 10px ; overflow : hidden ; margin - lesser : 15px ; } . errors { font - size : small ; color : #fff; background : var ( -- ion - color - danger ) ; padding - left : 15px ; padding - elevation : 5px ; padding - bottom : 5px ; } |
At present we've got a lovely login screen that should bring the states to the inside area upon successful login!
I've left out the signup screen, but I'm quite sure yous are capable of calculation the folio and building it almost like the login with this data.
Adding the Logout
This office is actually quite wearisome simply necessary to exam out our further security features. We've already created a logout inside the services previously, and so permit'due south now just add a function ton the first page of the within expanse, which is the src/app/tab1/tab1.page.ts:
1 2 3 4 v vi 7 8 ix 10 xi 12 xiii fourteen 15 xvi 17 xviii | import { AuthenticationService } from './../services/hallmark.service' ; import { Component } from '@athwart/core' ; import { Router } from '@athwart/router' ; @ Component ( { selector : 'app-tab1' , templateUrl : 'tab1.page.html' , styleUrls : [ 'tab1.page.scss' ] } ) export form Tab1Page { constructor ( private authService : AuthenticationService , private router : Router ) { } async logout ( ) { await this . authService . logout ( ) ; this . router . navigateByUrl ( '/' , { replaceUrl : truthful } ) ; } } |
To call that, permit's simply add a push button to the src/app/tab1/tab1.folio.html and nosotros are skilful to become:
< ion - header > < ion - toolbar > < ion - title > Tab one < / ion - title > < / ion - toolbar > < / ion - header > < ion - content > < ion - push expand = "full" ( click ) = "logout()" > Logout < / ion - button > < / ion - content > |
The logout will bring you back to the login, but what you notice is that you can e.chiliad. directly navigate to the URL http://localhost:8100/tabs/tab1/ although you lot are non authenticated.
That's actually no surprise because we haven't added the code for our baby-sit that should protect our within are.
Protecting Pages with the Auth Baby-sit
In the beginning we used a guard to perform a quick check if we've seen the tutorial already, at present we want to cheque if a user is allowed to enter a certain page.
That ways, within the guard we need to check the hallmark state from our service, and because that would be way too easy, there's a bit more complexity in here:
The initial value of the behaviour subject within the service is cipher
. If we would simply recollect that value inside the guard, whatsoever direct access of a folio (like within a web awarding) would be forbidden since the baby-sit assumes an unauthenticated user.
Information technology's not a huge bargain for a mobile application, but if you are using it on the web, or later on direct links to open pages of your mobile app, this is a very annoying behaviour.
Therefore, nosotros filter out the zip value inside the guard and only so check the authentication state.
Go ahead and alter the src/app/guards/auth.guard.ts to:
ane 2 3 4 5 6 7 8 9 10 11 12 13 fourteen fifteen xvi 17 eighteen xix xx 21 22 23 24 25 26 27 | import { AuthenticationService } from './../services/authentication.service' ; import { Injectable } from '@angular/core' ; import { CanLoad , Router } from '@athwart/router' ; import { Appreciable } from 'rxjs' ; import { filter , map , accept } from 'rxjs/operators' ; @ Injectable ( { providedIn : 'root' } ) export class AuthGuard implements CanLoad { constructor ( private authService : AuthenticationService , private router : Router ) { } canLoad ( ) : Observable < boolean > { return this . authService . isAuthenticated . pipe ( filter ( val = > val !== null ) , // Filter out initial Behaviour subject area value have ( 1 ) , // Otherwise the Observable doesn't consummate! map ( isAuthenticated = > { if ( isAuthenticated ) { render true ; } else { this . router . navigateByUrl ( '/login' ) return false ; } } ) ) ; } } |
At that place are also cases when your baby-sit evaluates to true, but the app simply doesn't modify: In these cases, the trouble is usually that the Observable is not complete.
Basically, the guard is still listening and doesn't end, only we have fixed this by using take(1)
, which will have only one event and then consummate the Observable!
Now you lot tin can log in, directly access any of the tabs pages with a URL like http://localhost:8100/tabs/tab1, and afterwards a logout, those pages aren't attainable anymore and you lot would be redirected to the login.
Very uncomplicated machinery, simply powerful to protect the inside area of your application.
Automatic Login
If the user was previously authenticated and so closes the app, the user would yet showtime on the login folio once again right now. Just we can actually automatically forward authenticated users to the inside area with a footling trick!
We will use our third guard as a check if the current user is authenticated using basically the same logic like the previous authentication guard.
Just this time, nosotros will handle the result a fleck differently and forward authenticated users to the inside area.
Go ahead and modify our final pipe inside the src/app/guards/auto-login.baby-sit.ts to:
1 2 3 four 5 6 vii eight 9 10 eleven 12 xiii 14 fifteen xvi 17 18 19 20 21 22 23 24 25 26 27 28 29 | import { Injectable } from '@angular/core' ; import { CanLoad , Router } from '@angular/router' ; import { Observable } from 'rxjs' ; import { AuthenticationService } from '../services/hallmark.service' ; import { filter , map , take } from 'rxjs/operators' ; @ Injectable ( { providedIn : 'root' } ) export class AutoLoginGuard implements CanLoad { constructor ( private authService : AuthenticationService , private router : Router ) { } canLoad ( ) : Appreciable < boolean > { return this . authService . isAuthenticated . piping ( filter ( val = > val !== null ) , // Filter out initial Behaviour subject value take ( ane ) , // Otherwise the Observable doesn't complete! map ( isAuthenticated = > { console . log ( 'Plant previous token, automatic login' ) ; if ( isAuthenticated ) { // Directly open inside expanse this . router . navigateByUrl ( '/tabs' , { replaceUrl : true } ) ; } else { // Simply allow access to the login return truthful ; } } ) ) ; } } |
This baby-sit was only added to our login page in the outset, just could (like the other guards) exist used in different places also.
Just now, every authenticated users will exist logged in straight!
Conclusion
This tutorial was a basic example for a very common use example, an introduction with login screen before tabs navigation.
With a simple routing setup and helpful guards, yous accept past at present already a powerful template for the remainder of your application!
You can also check out a video version of this tutorial below.
Ionic 3 Skip Login if User Logged in
DOWNLOAD HERE
Source: https://devdactic.com/ionic-5-navigation-with-login/
Posted by: smithmuspee.blogspot.com