We are going to learn how to integrate authentication in an Ionic 5 app by making use of the Firebase (AngularFire – official library for Firebase & Angular) package from the ground up in this comprehensive and step-by-step Ionic 5 Firebase Authentication tutorial.
Authentication of users is a feature that should be present in virtually any web-based or mobile application. Your important data will be protected by it, and only authorised people will be able to access it. Additionally, it will enable the creation of a more individualised user experience.
Getting Started with the Firebase Project
To establish a Firebase account, first visit the console at console.firebase.google.com, then use one of the techniques outlined further down in this article.
To create a Firebase account, simply follow the instructions described below. Create an account with Firebase, and then initiate the creation of a project via the Firebase dashboard. To initiate the creation of a brand new authentication project in Firebase, merely click the Add project button.
After you have finished creating your project, you will automatically be routed to the Firebase dashboard. You will be prompted to add Firebase to your Ionic app; to do so, select the symbol that is marked in red.
For this project, we will be utilising the Realtime Database, so make sure to select that option and then click the "new database" button.
If you select Authentication from the menu on the left side, you will be brought to the page that deals with authentication. It gives you the ability to manually add users and manage users from a variety of sources without requiring you to set up an environment on the server side.
Firebase gives you the option to design your own custom Templates for SMTP settings, email address verification, password reset, changing email addresses, and email address changes.
Firebase Configuration in Ionic/Angular application
Install ionic cli globally by using the command below.
npm install -g ionic
To initiate the creation of a completely new Ionic project, execute the following command:
ionic start ionic-firebase-authentication --type=angular
The Ionic sidemenu project is what we're going to be using for the Ionic
Firebase authentication example.
cd ionic-firebase-authenticationcd
Installing and Configuring AngularFire in the Ionic Project
To connect your Ionic or Angular app with Firebase, you will need to install the AngularFire library, which is the official Firebase package.
Execute the command that is given below in your terminal.
npm install firebase @angular/fire --save
Include configuration information for Firebase in the src/environment.ts file.
export const environment = {
production: true,
fbaseConfig: {
apiKey: 'YOUR_apiKEY',
authDomain: 'YOUR_authDomain',
databaseURL: 'YOUR_databaseURL',
projectId: 'YOUR_projectId',
storageBucket: 'YOUR_storageBucket',
messagingSenderId: 'YOUR_messagingSenderId',
appId: 'YOUR_appId'
}
};
Insert the following into the AppModule in environments: AngularFireModule, AngularFireAuthModule. AngularFireRestoreModule.
// app.module.ts
import { AngularFireModule }
from '@angular/fire'; // AngularFireModule imports
import { AngularFireAuthModule }
from '@angular/fire/auth'; // AngularFireAuthModule Imports...
import { AngularFirestoreModule }
from '@angular/fire/firestore'; // Angular FirestoreModule Importsimport { AngularFireDatabaseModule }
from '@angular/fire/database'; // AngularFireDatabaseModule Imports
import { environment }
from '../environments/environment'; // Firebase environment file
@NgModule({
declarations: [...],
imports: [
AngularFireDatabaseModule,
AngularFirestoreModule,
AngularFireModule
.initializeApp(environment?.fbaseConfig), // fbaseConfig here
AngularFireAuthModule,
],
providers: [ AngularFirestoreModule ],
bootstrap: [...]
})
export class AppModule {}
Develop an Authentication Service Utilizing Ionic 5 & Firebase.
export interface User {
uid: string;
email: string;
displayName: string;
photoURL: string;
emailVerified: boolean;
}
Make a file called authentication-service.ts and put the following code in it.
import {Injectable, NgZone} from '@angular/core';
import {auth} from 'firebase/app';
import {User} from './user';
import {Router} from '@angular/router';
import {AngularFireAuth} from '@angular/fire/auth';
import {AngularFirestore, AngularFirestoreDocument} from '@angular/fire/firestore';
@Injectable({
providedIn: 'root'
})
export class AuthenticationService {
userData: any = {};
constructor(
private afStore: AngularFirestore,
private ngFireAuth: AngularFireAuth,
private router: Router,
private ngZone: NgZone
) {
this.ngFireAuth.authState.subscribe(currentUser => {
if (currentUser) {
this.userData = currentUser;
const obj = this.userData;
localStorage
.setItem('user', JSON.stringify(obj));
const usr = JSON.
parse(localStorage.getItem('user'));
} else {
localStorage.
setItem('user', null); // clear localStorage
consr myUser = JSON.parse(localStorage.getItem('user'));
}
});
}
onSignIn(email: string, password: string) {
return this.ngFireAuth.auth.signInWithEmailAndPassword(email, password);
}
onRegisterUser(email: string, password: string) {
return this.ngFireAuth.auth.createUserWithEmailAndPassword(email, password);
}
onSendVerificationMail() {
return this.ngFireAuth.auth.currentUser.sendEmailVerification()
.then(() => {
this.router.navigate(['verify-email']); // page redirect
});
}
onPasswordRecover(passwordResetEmail: string) {
return this.ngFireAuth.auth
.sendPasswordResetEmail(passwordResetEmail)
.then((res) => {
console.log('Email sent');
}).catch((error) => { // error case
console.log('error occur: ' + error);
});
}
get isLoggedIn(): boolean {
const user = JSON.parse(localStorage
.getItem('user')); // if will get the detail and parse it
// return true if user exists
return (user !== null && user?.emailVerified !== false) ? true : false;
}
get isEmailVerified(): boolean {
const user = JSON.parse(localStorage.getItem('user'));
// return true if email verified
return (user.emailVerified !== false) ? true : false;
}
onGoogleAuth() {
return this.onAuthLogin(new auth.GoogleAuthProvider());
}
onAuthLogin(provider: auth) {
return this.ngFireAuth.auth.signInWithPopup(provider)
.then((result) => {
this.ngZone.run(() => {
this.router.navigate(['dashboard']); // navigate to dashboard
});
this.onSetUserData(result.user);
}).catch((error) => {
// handle error case
window.alert(error);
});
}
onSetUserData(user: any) {
const userRef: AngularFirestoreDocument<any> =
this.afStore.doc(`users/${user?.uid}`);
const userObj: User = {
displayName: user?.displayName,uid: user?.uid,
photoURL: user?.photoURL,
email: user?.email,
emailVerified: user?.emailVerified
};
return userRef.set(userObj, {
merge: true
});
}
onSignOut() {
return this.ngFireAuth.auth.signOut().then(() => {
localStorage.removeItem('user');
this.router.navigate(['login']); // redirect
});
}
}
We brought in the AngularFireAuth service and injected it into the contructor.
Then we subscribed to this method.
The user object from the Firebase database is returned.
We store the user object in localStorage to keep the logged-in
state of the user.
Using the Firebase API, we made the following methods in the above
service file to do the following things: Register with your username &
password, log in with your username and password, reset your
password, verify your email, and protect your route.
Registration in Ionic/Angular application
Let's use the Firebase API to add user registration to an Ionic 4 app.
In the last step, we made a service that we'll use in this step.
First, use the following command to make a registration component:
ng generate page registration
Find & open app/registration.page.ts and paste the code below into it.
import {Component } from '@angular/core';
import {Router} from '@angular/router';
import { AuthenticationService }
from '../shared/authentication-service'; // Path
@Component({
selector: 'app-registration',
templateUrl: './registration.page.html',
styleUrls: ['./registration.page.scss'],
})
export class RegistrationPage {
constructor(
private authenticationService: AuthenticationService,
private router: Router
) {
}
signUp(email: any, password: any) {
this.authenticationService.onRegisterUser(email['value'], password['value'])
.then((res) => {
// TODO
}).catch((error) => {
console.log(error['message']);
});
}
}
At the top of the "registration.page.ts" file, we need to import the AuthenticationService and the Router service.
Put the AuthenticationService and the Router service into the constructor.
Then, create the signUp(email: any, password: any) method & pass in the
values for email and password. Call authService from inside this function. onRegisterUser(x, y) is the method, and it returns the Promise.
In a little while, we'll define the user email verification method inside then block.
To make a user registration form in an Ionic app,
open the registration.page.html file.
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title> Ionic/Angular Registration User</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<form>
<ion-item lines="full">
<ion-label position="floating">Email</ion-label>
<ion-input type="text" #email required></ion-input>
</ion-item>
<ion-item lines="full">
<ion-label position="floating">Password</ion-label>
<ion-input type="password" #password required></ion-input>
</ion-item>
<ion-row>
<ion-col>
<ion-button type="submit" (click)="signUp(email, password)"
expand="block">Register</ion-button>
</ion-col>
</ion-row>
</form>
</ion-content>
To register a user, we made a form with fields for their email address
and password. In the ion-button directive, we declared the signUp()
method and passed the user's email address and password to it.
Email Confirmation in Ionic/Angular Firebase
Now, we're going to verify the email address by using the Firebase sendEmailVerification() method to send a verification email to the email
address that was used to sign up.We need to make the component,
and when a user registers successfully, he or she will be sent to this
component
ng generate page verify-email
Go to the file verify-email.page.ts, import and inject AuthenticationService
into the verify-email component, and then save the file.
import {Component } from '@angular/core';
import { AuthenticationService }
from '../shared/authentication-service' ; // path
@Component({
selector: 'app-verify-email',
templateUrl: './verify-email.page.html',
styleUrls: ['./verify-email.page.scss'],
})
export class VerifyEmailPage {
constructor(
private authService: AuthenticationService
) {
}
}
In the verify-email.page.html file, add the following code.
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title> Verify Email</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-grid>
<ion-row>
<h2>Ionic/Firebase Verify Email</h2>
<p>
Email sent, Check Your Mailbox
</p>
<ion-button type="submit"
(click)="authService.onSendVerificationMail()"
expand="block">
Resend Verification Email
</ion-button>
</ion-row>
</ion-grid>
</ion-content>
In the Promise part of the signUp() function, we need to call the onSendVerificationMail() method. Go to registration.page.ts and change the signUp() method to the code below
signUp(email: any, password: any){
this.authService.onRegisterUser(email['value'], password['value'])
.then((res) => {
this.authService.onSendVerificationMail()
this.router.navigate(['verify-email']); // redirect
}).catch((error) => {
console.log(error['message'])
})
}
In the main service file, we declared the code below.
When a new user signs up, this code checks their email address.
onSendVerificationMail() {
return this.ngFireAuth.auth.currentUser.onSendEmailVerification()
.then(() => {
this.router.navigate(['verify-email']); // redirect
})
}
Email & Password Auth in Ionic/Angular with Firebase
In this step, we need to add a login page to an Ionic app.
This step will let users who have already signed up log in with their email
address and password. Run the following command to generate a login
component:
ng generate page login
Go to the file login.page.ts & update the code below to it:
import {Component} from '@angular/core';
import {Router} from '@angular/router';
import {AuthenticationService} from '../shared/authentication-service';
@Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage {
constructor(
private authService: AuthenticationService,
private router: Router
) {
}
logIn(email: any, password: any) {
this.authService.onSignIn(email['value'], password['value'])
.then(() => {
if (this.authService.isEmailVerified) {
this.router.navigate(['dashboard']);
} else {
console.log('Not verified');
return false;
}
}).catch((error) => {
console.log(error['message']);
});
}
}
The only difference is that we use the signInWithEmailAndPassword() method
instead of the createUserWithEmailAndPassword() function when we use
the SignIn() method.
When a user's email has been checked, the isEmailVerified() returns "true."
Open the file login.page.html and add the code below:
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title> Welcome Back, Login Now </ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<form>
<ion-item lines="full">
<ion-label
position="floating">Email
</ion-label>
<ion-input
type="text"
#email required>
</ion-input>
</ion-item>
<ion-item lines="full">
<ion-label
position="floating">Password
</ion-label>
<ion-input
type="password"
#password
required>
</ion-input>
</ion-item>
<ion-row>
<ion-col>
<ion-button type="submit"
(click)="logIn(email, password)"
expand="block">Login
</ion-button>
</ion-col>
</ion-row>
</form>
</ion-content>
Firebase Providers "Login With Gmail"
If you want to save your users time and don't want to confuse them with usernames and passwords, use a login name and a password instead. Then we have a way for you to use social sign-in providers to log in.
This saves users time because they don't have to check their email and start the process to reset their password. It's useful in a mobile app, and if you already have a Google app on your phone, Google login will work automatically.
Google Login has many benefits, such as being easy to use and not requiring a password or email verification.
So far, we've learned how to use Firebase's ready-made email authentication. In this step, we'll learn how to use social logins to verify our identities.
Firebase has social login with Facebook, GitHub, Microsoft, Google, Twitter, Apple, Yahoo, Game Center (Beta), Phone number, and Anonymous.
In this tutorial, we will focus on Login with Google. We will soon make tutorials for the rest of the social providers.
Even though we already imported and injected the AuthenticationService in the login template, we need to import it again in the Ionic page.
Next, we just need to make a button and use the auth service API to call the GoogleAuth() method.
Find & Update login.page.ts file.
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title> Google Auth </ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<form>
<ion-row>
<ion-col>
<ion-button
type="submit"
color="danger"
(click)="authService.onGoogleAuth()"
expand="block">
Login with Google
</ion-button>
</ion-col>
</ion-row>
</form>
</ion-content>
The user will be taken to the dashboard page once they have logged in.
Firebase Logout
In this last step, we'll use the Firebase API to add a secure way to log out
of the Ionic 4 app. Update the following code in the dashboard.page.ts file:
import {Component } from '@angular/core';
import {AuthenticationService} from
'../shared/authentication-service';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.page.html',
styleUrls: ['./dashboard.page.scss'],
})
export class DashboardPage {
constructor(
private authService: AuthenticationService
) {
}
}
Next, open the dashboard.page.html file and go to the SignOut() method.
This method calls the auth.signOut() method, which lets the current user
sign out of the Firebase database. It also deletes the current Firebase
user from the localStorage.
<ion-button
type="submit"
(click)="authService.onSignOut()"
expand="block"
> Logout</ion-button>