How to implement Firebase Email Link (Passwordless) login in Ionic 4 for Android

Vivek Gawande
6 min readJun 5, 2019

--

I recently had a client ask me to implement email link authentication for an app using Ionic 4. I knew that this was a feature provided by Firebase, but when I started searching for tutorials online, to my surprise — I didn’t find any. That’s why I’m writing this tutorial for any other developer who may be in a similar situation.

Step 1: Create Firebase Project

This step is pretty straight forward. Go to https://console.firebase.google.com and create a new Firebase Project

Step 2: Create Ionic 4 Project

This step is easy as well. Just create a blank starter project using the command:

ionic start firebase-email-link blank

Step 3: Give it a package name

Go to your config.xml file (in the folder that you just created) and edit the following line and give it a custom package name:

<widget id="com.starter.ionic" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">

Change it to this (Give it a different name):

<widget id="com.firebaseemail.linkauth" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">

Step 4: Add Android App to Firebase

Adding your app to the Firebase console

Go to your Firebase console and click on Project Settings (gear in the sidebar). Then click on add an android app and follow the steps. Use the package name that you gave in the previous step. Make sure to download the google-services.json file in this step. Move that file to the android directory of your project. In this example, it’s path should be firebase-email-link/platforms/android/google-services.json

Step 5: Enable Email Link Authentication

In the Firebase console, go to Authentication > Sign in Method, and enable email/password sign in. When you do this, also enable email link sign in

Enabling Email link authentication

Step 6: Setup Firebase Hosting

Why do we need hosting? It is not for our app. It is used to represent the URL which will be opened in our app. Have you ever opened a facebook post link on your phone and it magically opens in your Facebook app instead of your browser? That’s what we’re trying to achieve. It’s called Dynamic Links.

So to set this up, first install firebase-tools

npm install -g firebase-tools
firebase login

Then create a folder to host our web app and initialize Firebase hosting:

mkdir email-link-webapp
cd email-link-webapp
firebase init hosting
firebase deploy

In this step, Link your web app to the same Firebase project when it asks for your input. If you want, you can edit the public/index.html file to say whatever you want your website to say when the user opens it via Chrome. It will only be visible for 1–2 sec and the user will be redirected to the app.

Simple Html page that is hosted using Firebase Hosting

Step 7: Enable Firebase Dynamic Links

Go to your Firebase Console > Dynamic Links in the sidebar. Click on get started and select a domain name. For this tutorial, I’m going to use a free domain provided by Google. Just type in the name you want and it will give you a choice of a page.link domain name. Click on that dropdown choice to select it.

Configuring Dynamic Links on the Firebase Console

If you choose this option, you won’t have to do steps 2 and 3. But if you choose a custom domain, then you have to configure your domain accordingly. Follow the steps in this link if you want to use a custom domain.

Step 8: It’s coding time

Finally after all this setup, you have to write some code to send the email link to the user and to intercept whenever the user clicks on the link and log him in the app. Make sure that you’ve setup Firebase and AngularFire in your app. Follow this link to set up AngularFire.

Setup the Firebase Dynamic Links Plugin as follows:

$ cordova plugin add cordova-plugin-firebase-dynamiclinks --variable APP_DOMAIN="yourprojectname.firebaseapp.com" --variable PAGE_LINK_DOMAIN="yourdomain.page.link"

Be sure to replace the APP_DOMAIN and PAGE_LINK_DOMAIN links to what you did in the previous steps.

Next, follow the steps here to setup the Ionic Native plugin for firebase dynamic links. Specifically, you’ve to do the following two steps:

  1. Add The following snippet to your config.xml file. You’ll get the GoogleIOSClientId and GoogleAndroidClientId from the GoogleService-Info.plist and google-services.json file. You have already downloaded the google-services.json file in Step 4.
<platform name="ios">
<preference name="GoogleIOSClientId" value="..." />
</platform>
<platform name="android">
<preference name="GoogleAndroidClientId" value="..." />
</platform>

2. Install the Ionic Native plugin:

npm install @ionic-native/firebase-dynamic-links

Setup a basic page to take the user email as input:

<ion-header>
<ion-toolbar>
<ion-title>
Login using Email
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-item>
<ion-label position="floating">Email</ion-label>
<ion-input [(ngModel)]="email"></ion-input>
</ion-item>
<ion-button
expand="block"
[disabled]="emailSent"
(click)="sendEmailLink(email)"
>Login</ion-button
>
</ion-content>

Here’s the code to send the email:

async sendEmailLink() {
var actionCodeSettings = {
// URL you want to redirect back to. Enter the Firebase hosting url here.
url: "https://yourprojectname.firebaseapp.com/",
handleCodeInApp: true,
iOS: {
bundleId: "com.firebaseemail.linkauth"
},
android: {
packageName: "com.firebaseemail.linkauth"
}
};
try {
await this.afAuth.auth.sendSignInLinkToEmail(
this.email,
actionCodeSettings
);
this.presentAlert("Mail Sent", "Check your email for login link");
this.emailSent = true;
} catch (err) {
console.error(err);
this.presentAlert("Error", "There was an error in sending mail");
this.errorMessage = err.message;
}
}

And here’s the code to intercept the link:

this.platform.ready().then(() => {
this.firebaseDynamicLinks.onDynamicLink().subscribe(
(res: any) => {
console.log(res);
afAuth.auth
.signInWithEmailLink(this.email, res["deepLink"])
.then(() => {
this.presentAlert("Success", "Logged in successfully");
// Navigate the user to whereever you want
this.navCtrl.navigateRoot("dashboard");
})
.catch(err => {
console.error(err);
this.presentAlert(
"Error",
"There was an error while logging in. Please try again later"
);
});
console.log("Link intercepted");
},
(error: any) => {
console.error(error);
this.presentAlert(
"Error",
"There was an error in intercepting the link"
);
}
);
});

Step 9: Test the app

Try running the app on your device and check if everything works as expected. Here’s the full code for home.page.ts:

import { Component } from "@angular/core";
import { AngularFireAuth } from "@angular/fire/auth";
import { FirebaseDynamicLinks } from "@ionic-native/firebase-dynamic-links/ngx";
import { Platform, AlertController, NavController } from "@ionic/angular";
@Component({
selector: "app-home",
templateUrl: "home.page.html",
styleUrls: ["home.page.scss"]
})
export class HomePage {
email;
emailSent = false;
errorMessage;
user;
constructor(
private firebaseDynamicLinks: FirebaseDynamicLinks,
private afAuth: AngularFireAuth,
private platform: Platform,
private alertController: AlertController,
private navCtrl: NavController
) {
this.platform.ready().then(() => {
this.firebaseDynamicLinks.onDynamicLink().subscribe(
(res: any) => {
console.log(res);
afAuth.auth
.signInWithEmailLink(this.email, res["deepLink"])
.then(() => {
this.presentAlert("Success", "Logged in successfully");
this.navCtrl.navigateRoot("dashboard");
})
.catch(err => {
console.error(err);
this.presentAlert(
"Error",
"There was an error while logging in. Please try again later"
);
});
console.log("Link intercepted");
},
(error: any) => {
console.error(error);
this.presentAlert(
"Error",
"There was an error in intercepting the link"
);
}
);
});
}
async sendEmailLink() {
var actionCodeSettings = {
// URL you want to redirect back to. Enter the Firebase hosting url here.
url: "https://yourprojectname.firebaseapp.com/",
handleCodeInApp: true,
iOS: {
bundleId: "com.firebaseemail.linkauth"
},
android: {
packageName: "com.firebaseemail.linkauth"
}
};
try {
await this.afAuth.auth.sendSignInLinkToEmail(
this.email,
actionCodeSettings
);
this.presentAlert("Mail Sent", "Check your email for login link");
this.emailSent = true;
} catch (err) {
console.error(err);
this.presentAlert("Error", "There was an error in sending mail");
this.errorMessage = err.message;
}
}
async presentAlert(title, message) {
const alert = await this.alertController.create({
header: title,
message: message,
buttons: ["OK"]
});
await alert.present();
}
}

I have already shared the home.page.html code above.

That’s it for this tutorial. Let me know if you guys are stuck anywhere and I’ll be happy to help. If this tutorial helps even a single developer — It’d have served its purpose. If you appreciate this type of tutorial and want more, let me know and buy me a coffee maybe!

--

--