Ionic3 Login Authentication With Google Firebase

In this post I will walk through, step-by-step, how to use Google Firebase to authenticate users in an Ionic 3 application. The scope of this tutorial is to only cover basic email and password authentication, but using this method you will be able to integrate additional authentication providers such as Facebook, Twitter, GitHub and Google.

In addition, I am a man of simplicity and do not like dependencies. That is why I will use the Firebase API for Web library from Google and not the likes of AngularFire2. Though some may argue this limits the features available, I think the Firebase API for Web library offers everything you need out of the box – and creating your own wrappers will enable you to integrate your code and debug issues with less friction.

Finally, my example code will be based on an Ionic 3.9.2 project using the tabs starter layout. For those using the sidemenu or any other layout, you will need to replace all mentions to TabsPage to HomePage or equivalent.

How to use Google Firebase authentication with an Ionic 3 application

Step 1: If you haven’t already, open your Ionic app or create a new blank application with the command:


ionic start myApp tabs

Step 2: Install the Google Firebase Web library for JavaScript via npm with the following command:


npm install firebase --save

Step 3: Now create a login page and authentication provider/service with the following commands:


ionic generate provider authentication
ionic generate page login

Step 4: Initialise Firebase from within the app.component.ts file by adding the following code in the ngOnInit function:


firebase.initializeApp({
    apiKey: "YOUR_API_KEY",
    authDomain: "YOUR_AUTH_DOMAIN",
    databaseURL: "YOUR_DATABASE_URL",
    projectId: "YOUR_PROJECT_ID",
    storageBucket: "YOUR_STORAGE_BUCKET",
    messagingSenderId: "YOUR_SENDER_ID"
});

You will also need to add an import statement to the top of the app.component.ts file:


import firebase from 'firebase';

Your credentials can be found in the Firebase Console Dashboard.

Step 5: Set the root page for your application to the LoginPage. This means every time the app is fired up, the LoginPage is displayed first.

Do this by settings the rootPage class variable in app.component.ts to LoginPage.

Step 6: Let’s pad out our AuthenticationProvider with some code. We’ll need to import the firebase definitions to stop Typescript from complaining:


import firebase from 'firebase';

And then add the following functions in the body of the AuthenticationProvider class:


register(credentials): Promise {
    return firebase.auth().createUserWithEmailAndPassword(credentials.email, credentials.password);
}

login(credentials): Promise {
    return firebase.auth().signInWithEmailAndPassword(credentials.email, credentials.password);
}

loginAsGuest(): Promise {
    return firebase.auth().signInAnonymously();
}

logout(): Promise {
    return firebase.auth().signOut();
}

All of these functions wrap the Firebase services. A promise is returned for them all because it will allow us to appropriately handle errors and chain .then()s within the controller (more later). The Google Firebase API docs do a very good job explaining the createUserWithEmailAndPassword(), signInWithEmailAndPassword, signInAnonymously() and signOut() functions.

Step 7: We can now create a form on the LoginPage and all add the logic for the login and register buttons. In this example, I will be using a ReactiveForm because I think they’re cool. It works just as well with template-based forms using ngModel instead of FormControlName. To use ReactiveForms you’ll need to import FormsModule and ReactiveFormsModule from @angular/forms in to your AppModule.

Your login.component.ts file will now contain the following:


export class LoginPage implements OnInit {
    loginForm: FormGroup;

    constructor(private auth: AuthenticationProvider, private formBuilder: FormBuilder, private navCtrl: NavController, private navParams: NavParams) {}

    ngOnInit() {
        this.initLoginForm();
    }

    initLoginForm() {
        this.loginForm = this.formBuilder.group({
            email: ['', [Validators.required, Validators.email]],
            password: ['', [Validators.required]]
        });
    }

    register() {
        this.auth.register(this.loginForm.value)
        .then(response => {
            this.navCtrl.setRoot(TabsPage);
        })
        .catch(error => {
            // handle error by showing alert
        })
    }

    login() {
        this.auth.login(this.loginForm.value)
        .then(response => {
            this.navCtrl.setRoot(TabsPage);
        })
        .catch(error => {
            // handle error by showing alert
        })
    }
}

In the constructor we inject the AuthenticationProvider and a FormBuilder for reactive forms. We also declare the variable loginForm which will contain the reactive form.

We then initialise the reactive form using the FormBuilder which provides validation. You can read more about reactive forms in the Angular documentation here.

The login() and register() functions essentially wrap the functions we created in AuthenticationProvider earlier, and add logic for when the Promise resolves or is rejected. In the case of logging in, if the call is successful the user token will automatically be stored in the firebase.auth() object. We just set the rootPage from LoginPage (set in app.component.ts) to the TabsPage. If you are using the sidemenu template this would be HomePage instead. This navigates the user to the main page of our application and since it is setting the root and not pushing to the NavController the user will not be able to accidentally swipe back to the Login page. You can read more about pushing to and popping from the Ionic NavController here.

In both functions, we are passing the user input email and password which is stored in the loginForm reactive form.

Step 8: Somewhere in your app, you will want to offer your user the option to log out. The implementation for this function is similar to login():


logout() {
    this.auth.logout()
    .then(response => {
        this.navCtrl.setRoot(LoginPage);
    });
}

We set the root page back to LoginPage with no navigation history so the user has to log in before they can use the application.

Subscribe to Email Updates