In this article, let me show you how to create an Ionic application with E-mail Authentication in Firebase. Before moving to the configuration part. Just take a look at what is Ionic and Firebase?

What is Ionic?

Ionic Framework is an open-source UI toolkit that allows high-quality mobile and desktop applications to be developed using web technologies. Ionic Architecture is based on the application’s interface or user experience. It is easy to learn, easy to integrate, or can be used standalone without a front frame using a simple script including other libraries or frameworks, such as Angle. Ionic Framework currently has official Angular and React integrations and support for Vue is in the pipeline.

What is Firebase?

Firebase is a Backend-as-a-Service (Baas). It provides developers with a variety of tools and services to help them develop quality apps, grow their user base, and earn a profit. It is built on Google’s infrastructure. Firebase is categorized as a NoSQL database program, which stores data in JSON like documents.

Prerequisites

* Google Account

Before Starting make sure that you have gmail account. If not, you can simply obtain a google account here.

* Latest version of Ionic

Make sure that you have latest version of @ionic/cli installed. You can update it by running below code.

1
npm install -g @ionic/cli
To check your Ionic version by simply runnig below code.

1
ionic -v

Create new Ionic App

Now we should create a new ionic application using Angular framework. To specify the intergration you can use
--type=angular. In here use we use blank template for our application. You can create blank Ionic app by inserting blank keyword. Just simply running below command in your terminal you can create new Ionic application.

1
ionic start ionic-email-authentication blank --type=angular
Then move to your project directory

1
cd ionic-email-authentication
To open your project in Visual Studio Code,type

1
code .

Install Firebase in Ionic Application

When it comes to Firebase official package for Angular is called as angualrfire. This package allow Angular project to use all Firebase service. To use Firebase services we should install @angular/fire and firebase packages by running below command.

1
npm install firebase @angular/fire --save

Create Firebase project

Next we need to create Firebase App using our Firebase Console . Login to your Firebase console and crate new project using Add project section

alt text After filling out all the required parts, you will redirect in to a page like below.

alt text Then you should click "Web App" icon to get configuration text, which we will add in to our Ionic Application to communicate with Firebase. After that you have to fill out all the required details related your web app and register it with Firebase.

alt text After you registered your web app with Firebase, they provide the SDK.

alt text Now we have to enable the Email Authentication from our Firebase console. To enable it, click the the Authentication tab in the left menu and it will redirect you in to a page like below.

alt text Then select Email/Password from sign-in-providers section and Enable the E-mail Authentication. alt text Now we have all done with our Firebase console. Now we can moving to our programming part.

Add Firebase configuration to Ionic App

To add Firebase configuration to our Ionic application, you should update the "src/environments/environment.ts" by adding cofiguration text we got in previous section.

1
2
3
4
5
6
7
8
9
10
11
12
export const environment = {
production: false,

firebase: {
apiKey: "AIzXXXXXXXXXXXXXXXWZMPN90HFrp4",
authDomain: "test-projeXXXXXXX.firebaseapp.com",
databaseURL: "https://test-projeXXXXXXX.firebaseio.com",
projectId: "test-projeXXXXXXX7",
storageBucket: "test-projeXXXXXXXX.appspot.com",
messagingSenderId: "446XXXXXX105"
}
};
Note: You should replace above values with your project credentials. Now you should delete your home page in your project directory because we are creating new three new pages according to our project requirments.

Create new pages using CLI

In this project we need three pages. They are Login, Register and Dashboard page. To Create this pages easily you can use below commands.

1
2
3
ionic generate page login
ionic generate page register
ionic generate page dashboard
Now we should create a new service to communicate with the Firebase Authentication methods and keep login, register and logout logic separate. you can generate service using below command.

1
ionic g service services/authentication
In this Authenticateservice, we keep the methods for login, register, get user details and logout. To register a new member, we call createUserWithEmailAndPassword() function with email and password which is provided by users from register page. signInWithEmailAndPassword() use to manage the login of Users. We have userDetails() function to return the details of logged in user. At finally we have signOut() method to remove user session from Firebase Authentication Service.

Paste below code in your authentication.service.ts file.

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
36
37
38
39
40
41
42
43
44
45
46
47
import { Injectable } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';

@Injectable({
providedIn: 'root'
})
export class AuthenticateService {
constructor(
private afAuth: AngularFireAuth
) { }

registerUser(value) {
return new Promise<any>((resolve, reject) => {
this.afAuth.createUserWithEmailAndPassword(value.email, value.password)
.then(
res => resolve(res),
err => reject(err));
});
}

loginUser(value) {
return new Promise<any>((resolve, reject) => {
this.afAuth.signInWithEmailAndPassword(value.email, value.password)
.then(
res => resolve(res),
err => reject(err));
});
}

logoutUser() {
return new Promise((resolve, reject) => {
if (this.afAuth.currentUser) {
this.afAuth.signOut()
.then(() => {
console.log('Log Out');
resolve();
}).catch((error) => {
reject();
});
}
});
}

userDetails() {
return this.afAuth.user;
}
}

Changes in App module and Routing module

Now we need to make changes in out app.module.ts and app.routing.module.ts. In our app.module.ts, we need to import AngularFireModule and AngularFireAuthModule modules.And also we need to import to our environment file which contains configuration for Firebase.Paste below code in your app.module.ts

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
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 { AngularFireModule } from '@angular/fire';
import { AngularFireAuthModule } from '@angular/fire/auth';
import { environment } from '../environments/environment';

@NgModule({
declarations: [AppComponent],
entryComponents: [],

imports: [
BrowserModule,
IonicModule.forRoot(),
AppRoutingModule,
AngularFireAuthModule,
AngularFireModule.initializeApp(environment.firebase)
],

providers: [
StatusBar,
SplashScreen,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],

bootstrap: [AppComponent]
})

export class AppModule { }
Paste below code in your app.routing.module.ts

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
import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';

const routes: Routes = [
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
},
{
path: 'login',
loadChildren: () => import('./login/login.module').then(m => m.LoginPageModule)
},
{
path: 'register',
loadChildren: () => import('./register/register.module').then(m => m.RegisterPageModule)
},
{
path: 'dashboard',
loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardPageModule)
},
];

@NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
],
exports: [RouterModule]
})

export class AppRoutingModule { }

Import ReactiveFormsModule

To validate forms in Login and Register, we use React approach. So, we need to import ReactiveFormsModule in our import array in login.ts and register.ts.

1
2
3
4
5
6
7
8
9
10
11
12
@NgModule({

imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
IonicModule,
...

],
declarations: [LoginPage]
})

Login Page

Replace following component code in login.page.ts

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
import { NavController } from '@ionic/angular';
import { AuthenticateService } from '../services/authentication.service';

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

export class LoginPage implements OnInit {
validations_form: FormGroup;
errorMessage: string = '';
constructor(
private navCtrl: NavController,
private authService: AuthenticateService,
private formBuilder: FormBuilder
) { }

ngOnInit() {
this.validations_form = this.formBuilder.group({
email: new FormControl('', Validators.compose([
Validators.required,
Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
])),
password: new FormControl('', Validators.compose([
Validators.minLength(5),
Validators.required
])),
});
}

validation_messages = {
'email': [
{ type: 'required', message: 'Email is required.' },
{ type: 'pattern', message: 'Please enter a valid email.' }
],
'password': [
{ type: 'required', message: 'Password is required.' },
{ type: 'minlength', message: 'Password must be at least 5 characters long.' }
]
};

loginUser(value) {
this.authService.loginUser(value)
.then(res => {
console.log(res);
this.errorMessage = "";
this.navCtrl.navigateForward('/dashboard');
}, err => {
this.errorMessage = err.message;
})
}

goToRegisterPage() {
this.navCtrl.navigateForward('/register');
}
}
Replace following HTML code in login.page.html

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
36
37
38
39
<ion-header>
<ion-toolbar color="primary">
<ion-title>Login</ion-title>
</ion-toolbar>
</ion-header>

<ion-content class="ion-padding">
<form class="form" [formGroup]="validations_form" (ngSubmit)="loginUser(validations_form.value)">
<ion-item>
<ion-label position="floating" color="primary">Email</ion-label>
<ion-input type="text" formControlName="email"></ion-input>
</ion-item>
<div class="validation-errors">
<ng-container *ngFor="let validation of validation_messages.email">
<div class="error-message"
*ngIf="validations_form.get('email').hasError(validation.type) && (validations_form.get('email').dirty || validations_form.get('email').touched)">
{{ validation.message }}
</div>
</ng-container>
</div>
<ion-item>
<ion-label position="floating" color="primary">Password</ion-label>
<ion-input type="password" formControlName="password" class="form-controll" required></ion-input>
</ion-item>
<div class="validation-errors">
<ng-container *ngFor="let validation of validation_messages.password">
<div class="error-message"
*ngIf="validations_form.get('password').hasError(validation.type) && (validations_form.get('password').dirty || validations_form.get('password').touched)">
{{ validation.message }}
</div>
</ng-container>
</div>
<ion-button class="submit-btn" type="submit" [disabled]="!validations_form.valid">Log In</ion-button>
<label class="error-message">{{errorMessage}}</label>
</form>
<p class="go-to-register">
No account yet? <a (click)="goToRegisterPage()">Create an account.</a>
</p>
</ion-content>

Register Page

Replace following component code in register.page.ts

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
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
61
62
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
import { AuthenticateService } from '../services/authentication.service';
import { NavController } from '@ionic/angular';

@Component({
selector: 'app-register',
templateUrl: './register.page.html',
styleUrls: ['./register.page.scss'],
})

export class RegisterPage implements OnInit {
validations_form: FormGroup;
errorMessage: string = '';
successMessage: string = '';
validation_messages = {
'email': [
{ type: 'required', message: 'Email is required.' },
{ type: 'pattern', message: 'Enter a valid email.' }
],
'password': [
{ type: 'required', message: 'Password is required.' },
{ type: 'minlength', message: 'Password must be at least 5 characters long.' }
]
};

constructor(
private navCtrl: NavController,
private authService: AuthenticateService,
private formBuilder: FormBuilder
) { }

ngOnInit() {
this.validations_form = this.formBuilder.group({
email: new FormControl('', Validators.compose([
Validators.required,
Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
])),
password: new FormControl('', Validators.compose([
Validators.minLength(5),
Validators.required
])),
});
}

tryRegister(value) {
this.authService.registerUser(value)
.then(res => {
console.log(res);
this.errorMessage = "";
this.successMessage = "Your account has been created. Please log in.";
}, err => {
console.log(err);
this.errorMessage = err.message;
this.successMessage = "";
})
}

goLoginPage() {
this.navCtrl.navigateBack('');
}
}
Replace following HTML code in register.page.html

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
36
37
38
<ion-header>
<ion-toolbar color="primary">
<ion-title>Register</ion-title>
</ion-toolbar>
</ion-header>

<ion-content class="ion-padding">
<form class="form" [formGroup]="validations_form" (ngSubmit)="tryRegister(validations_form.value)">
<ion-item>
<ion-label position="floating" color="primary">Email</ion-label>
<ion-input type="text" formControlName="email"></ion-input>
</ion-item>
<div class="validation-errors">
<ng-container *ngFor="let validation of validation_messages.email">
<div class="error-message"
*ngIf="validations_form.get('email').hasError(validation.type) && (validations_form.get('email').dirty || validations_form.get('email').touched)">
{{ validation.message }}
</div>
</ng-container>
</div>
<ion-item>
<ion-label position="floating" color="primary">Password</ion-label>
<ion-input type="password" formControlName="password" class="form-controll" required></ion-input>
</ion-item>
<div class="validation-errors">
<ng-container *ngFor="let validation of validation_messages.password">
<div class="error-message"
*ngIf="validations_form.get('password').hasError(validation.type) && (validations_form.get('password').dirty || validations_form.get('password').touched)">
{{ validation.message }}
</div>
</ng-container>
</div>
<ion-button class="submit-btn" type="submit" [disabled]="!validations_form.valid">Register</ion-button>
<label class="error-message">{{errorMessage}}</label>
<label class="success-message">{{successMessage}}</label>
</form>
<p class="go-to-login">Already have an account? <a (click)="goLoginPage()">Try to Log In.</a></p>
</ion-content>

Dashboard

Replace following component code in dashboard.page.ts

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
36
37
38
39
40
41
42
43
44
import { Component, OnInit } from '@angular/core';
import { NavController } from '@ionic/angular';
import { AuthenticateService } from '../services/authentication.service';

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

export class DashboardPage implements OnInit {

userEmail: string;

constructor(
private navCtrl: NavController,
private authService: AuthenticateService
) { }

ngOnInit() {
this.authService.userDetails().subscribe(res => {
console.log('res', res);
if (res !== null) {
this.userEmail = res.email;
} else {
this.navCtrl.navigateBack('');
}
}, err => {
console.log('err', err);
})

}

logout() {
this.authService.logoutUser()
.then(res => {
console.log(res);
this.navCtrl.navigateBack('');
})
.catch(error => {
console.log(error);
})
}
}
Replace following HTML code in dashboard.page.html

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
<ion-header>
<ion-toolbar>
<ion-title>Dashboard</ion-title>
</ion-toolbar>
</ion-header>

<ion-content class="ion-padding">
<ion-grid>
<ion-row>
<ion-col text-center>
Welcome to Dashboard!
</ion-col>
</ion-row>
<ion-row>
<ion-col text-center>
Your Registered EmailID : {{userEmail}}
</ion-col>
</ion-row>
</ion-grid>
</ion-content>

<ion-footer (click)="logout()">
<ion-toolbar color="secondary">
<ion-title>Log out</ion-title>
</ion-toolbar>
</ion-footer>

Run Application

Now we have finished our coding part. Now it's time to run our application. You can run your application by hitting below command in your terminal.

1
ionic serve --lab
You can get source code from here.

In this post, I showed you how to integrate Google Firebase service in Ionic Application to create login and registration functionality. We can include more Firebase services like Firestore, Messaging, Social login which we will discuss in coming articles.

Happy Coding