Most of the application we build require some kind of Authentication and the simplest and fastest way to get started with that is by using the Firestore. Firestore is a flexible, scalable database for mobile, web and server development.
In this article, you will learn to develop a fully functioning authentication system in Angular using Firestore. We will be using the official tool for Angular and Firebase integration – AngularFire. AngularFire allows you to work with Cloud Firestore, the new flagship database for mobile app development. It improves on the successes of Real-time Database with a new, more intuitive data model. Cloud Firestore also features richer, faster queries and scales better than Realtime Database.
In order to follow along with this tutorial please ensure you have downloaded and installed the Angular IDE. Ensure that the latest version of Angular CLI is installed on your computer. You also need a Google account to be able to sign in to Firebase Console, where you will be creating the app which we will work with, in this tutorial.
We’ll be using the latest version of all the tech libraries and stacks as at the time of this writing. Navigate to File -> New -> Angular Project. Then choose to Create a New Project with the following, versions of software as is in the screenshot below.
Create a New Angular Project from Angular IDE
After setting up the project to use the versions and giving it a Project name of AngularAuth click finish to create and install, this will ideally take some time, depending on how fast your internet is, so be patient.
Create a New Angular Project from Angular IDE
Once the project is created, the next thing to do is create an app in Firebase, so navigate to the Firebase Console and then click on Add Project to create a new project. Give it a name, I’ll call mine AngularAuth, then click on Create Project afterward.
Now after the project has been created, you will be redirected to the project’s overview page, there you are meant to choose the option – **_Add Firebase to your web app. _**On clicking that, you will get a pop up with all the info such as API key that you need to be able to interact with your newly created Firebase app from the Angular application that we created in Angular IDE. That’s it for now with Firebase, let’s go back to the Angular IDE to create some components.
We need a Homepage, Login page, and Sign Up page to showcase how our Authentication is working. So we need to create an Angular component for each of these pages. We will use one of the features that make Angular IDE so awesome, the Create Component shortcut, Navigate to File -> New -> **Component**to create a new component.
Give the first component a name – homepage as in the screenshot below and uncheck the Create Component with Unit Test flag, because Unit Testing is beyond the scope of this tutorial,but we can leave the Generate Component using the prefix location flag, which is the default from Angular. The prefix is simply the word that goes before the selector of every component you generate with the CLI. If you want to know more about it or change the prefix, read more about it on this StackOverflow question here.
Click Finish when you are done. This will automatically run the command **_ng g component homepage –spec false _**in Angular IDE’s terminal.
Now let us run our app to confirm everything is working. Go into the Angular IDE and type the command ng serve
On running ng serve I got the following error
~/Workspaces/Dunebook/AngularAuth $ ng serve You seem to not be depending on "@angular/core". This is an error.
If you got that same error, run npm install to install the npm packages required to get your app up and running. Check out this page to install yarn, if you don’t have it yet. After running npm install successfully, the ng serve command will now run successfully. Visit this link to see your app working.
Now, let’s go ahead and remove the default content that came with the new application. Navigate to src/app/app.component.html to see the code. Select all content of this file and delete it. When you hit save and check your browser now, the page should be blank. The app.component.html file now becomes the new base/host for our homepage. Go ahead and add the selector of the homepage component there. To do that, type the following code (for some unknown reason I could not paste the code so I’ll attach the screenshot). Save it now and your site should reload to show the content of homepage.component.html.
The app-homepage is the selector for the homepage component we created earlier.
Next, we will create the other two components needed to run the app and then install AngularFire2 and Firebase. Run the following commands to do that.
ng g c login --spec false && ng g c signup --spec false && npm install firebase angularfire2
The above command will create a LoginComponent, SignupComponent and then install firebase and angularfire2 npm packages.
Now, with the installed npm packages we need configure our Firebase application to enable it to be able to communicate with your Angular application.
Firebase Config set up for Angular Authentication
First, we will import the AngularFire modules to the app.module.ts file. My app.module.ts file looks like this after the new config is added. The lines in bold need to be added to your app.module.ts
When you click on **Add Firebase to your web app **you should get a pop up similar to the image below.
Firebase Auth Config for Authentication in Angular
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { AngularFireModule } from 'angularfire2'; import { AngularFireAuthModule } from 'angularfire2/auth'; import { AppComponent } from './app.component'; import { HomepageComponent } from './homepage/homepage.component'; import { LoginComponent } from './login/login.component'; import { SignupComponent } from './signup/signup.component'; // Copy the firebaseConfig from your created project on the firebase console. Here, click on the project name and then on the project dashboard, click on Add firebase to your web app. Replace the values below with yours, values below will not work for you because I have removed some characters from it. const firebaseConfig = { apiKey: 'AIzaSyAywNGLBVmlk98jwaeqsFdm1hNMQ', authDomain: 'angularauth-502.firebaseapp.com', databaseURL: 'https://angularauth-502.firebaseio.com', projectId: 'angularauth-502', storageBucket: 'angularauth-502.appspot.com', messagingSenderId: '11240551' }; @NgModule({ declarations: [ AppComponent, HomepageComponent, LoginComponent, SignupComponent ], imports: [ BrowserModule, FormsModule, AngularFireModule.initializeApp(firebaseConfig), AngularFireAuthModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Next, we will set up the Authentication methods, by clicking on the Authentication link described in the screenshot above. Once there, enable Sign-in for Email/Password and Google and then save. To enable for other providers you need an API key and API secret. Which can be easily generated by visiting the developers’ section of each of the providers.
Click on the Database on the sidebar at Firebase and then click on TRY FIRESTORE BETA. Then click ENABLE.
Enabling Firestore Firebase Database
Upon creation of the Database, check the Rules tab and make sure the content is similar to this:
service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write; } } }
As at the time of this writing. There was a bug in the Firebase npm package, the following errors were displayed in the console. And according to this thread on Github, we need to downgrade Firebase to version 4.8.0 and upgrade AngularFire to version 5.0.0-rc.5. Remove the ^ at the beginning of the versions so as to download the exact version that we want. After changing it run yarn install to change the version.
"angularfire2": "5.0.0-rc.5-next", "firebase": "4.8.0",
Take note that if you are using a version of Firebase and AngularFire that is higher, you might not need to make these changes. The versions causing the errors are Firebase version 4.8.1 and AngularFire 5.0.0-rc.4.
With these changes effected correctly, the errors should be gone. Now let’s go ahead and use AngularFire and Firebase in our project. First, we need to create a service file which will serve all the methods that we need to login and logout. Go to the Angular IDE and follow the direction as described in the screenshot below.
Creating a New Service in Angular IDE
Creating a New Service and giving it a name in Angular IDE
Now, let’s go to the auth.service.ts file and add some code to it.
import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { AngularFireAuth } from 'angularfire2/auth'; import * as firebase from 'firebase/app'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/switchMap'; @Injectable() export class AuthService { constructor( private afAuth: AngularFireAuth, private router: Router) {} login(email: string, password: string) { this.afAuth.auth.signInWithEmailAndPassword(email, password) .then(value => { console.log('Nice, it worked!'); this.router.navigateByUrl('/profile'); }) .catch(err => { console.log('Something went wrong: ', err.message); }); } emailSignup(email: string, password: string) { this.afAuth.auth.createUserWithEmailAndPassword(email, password) .then(value => { console.log('Sucess', value); this.router.navigateByUrl('/profile'); }) .catch(error => { console.log('Something went wrong: ', error); }); } googleLogin() { const provider = new firebase.auth.GoogleAuthProvider(); return this.oAuthLogin(provider) .then(value => { console.log('Sucess', value), this.router.navigateByUrl('/profile'); }) .catch(error => { console.log('Something went wrong: ', error); }); } logout() { this.afAuth.auth.signOut().then(() => { this.router.navigate(['/']); }); } private oAuthLogin(provider) { return this.afAuth.auth.signInWithPopup(provider); } }
The first thing we need to do after creating a Service method is to add it to the providers array in the app.module.ts file, then after that we need to create routes for the components we created earlier and also create two more components, the EmailComponent and ProfileComponent. Use the same method we used to create components earlier to create those components. Your app.module.ts file should now look like this (The most significant changes are highlighted in bold):
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { AngularFireModule } from 'angularfire2'; import { AngularFireAuthModule } from 'angularfire2/auth'; import { AppComponent } from './app.component'; import { AuthService } from './auth.service'; import { HomepageComponent } from './homepage/homepage.component'; import { LoginComponent } from './login/login.component'; import { SignupComponent } from './signup/signup.component'; import { ProfileComponent } from './profile/profile.component'; import { AppRoutingModule } from './app-routing.module'; import { EmailComponent } from './email/email.component'; const firebaseConfig = { apiKey: 'AIzaSyAywNGLBVmlk98dkqahOj1hNMQ', authDomain: 'angularauth-502.firebaseapp.com', databaseURL: 'https://angularauth-502.firebaseio.com', projectId: 'angularauth-502', storageBucket: 'angularauth-502.appspot.com', messagingSenderId: '1124055' }; @NgModule({ declarations: [ AppComponent, HomepageComponent, LoginComponent, SignupComponent, ProfileComponent, EmailComponent ], imports: [ BrowserModule, FormsModule, AppRoutingModule, AngularFireModule.initializeApp(firebaseConfig), AngularFireAuthModule ], providers: [ AuthService ], bootstrap: [AppComponent] }) export class AppModule { }
Next, we’ll create the AppRoutingModule where we will create our routes. Create a file app-routing.module.ts in the src/app folder, then fill it up with the following content.
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { LoginComponent } from './login/login.component'; import { ProfileComponent } from './profile/profile.component'; import { SignupComponent } from './signup/signup.component'; import { EmailComponent } from './email/email.component'; const routes: Routes = [ { path: '', redirectTo: 'login', pathMatch: 'full' }, { path: 'login', component: LoginComponent }, { path: 'email-login', component: EmailComponent }, { path: 'signup', component: SignupComponent }, { path: 'profile', component: ProfileComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule {}
Now let’s go ahead and work in our LoginComponent file navigate to the login/login.component.ts, the method we will use there is the googleLogin().
import { Component, OnInit } from '@angular/core'; import { AuthService } from '../auth.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent implements OnInit { constructor(private authService: AuthService) { } ngOnInit() {} loginGoogle() { this.authService.googleLogin(); } }
And fill up the component file, login.component.html like so:
Angular Authentication with Firestore Login Form
Before we go ahead and verify that everything is working, we need to change the content of the app.component.html file:
Replace
<app-homepage></app-homepage> with <code><router-outlet></router-outlet>
We should also add some styling to the form by editing the src/styles.css file, add the following css code to it:
body { background: #E2E4E6; padding-top: 4em; } .form-container { background: white; padding: 3.5em; width: 500px; position: fixed; left: 45%; margin-left: -250px; } button { padding: 0.5em; width: 100%; cursor: pointer; margin-bottom: 15px; font-size: 1.3em; } .google { border: 1px solid #95989A; background: #fff; background-size: 25px; } .email { background: #ECECEC; background-size: 25px; } .create-account-txt { text-align: center; display: block; margin: 15px 0; } .auth-btn { background: #3B8598; color: white; } input.input-txt { background: #fff !important; padding: 0.5em 1em; font-size: 1.3em; border: 1px solid #BBBBBB; width: 90%; margin-bottom: 1em; }
Now the login page looks like this:
Angular Firebase Authentication Email Login Form
Log in with Google Account now works, next, we will implement Logging in with Email and then after that, work on the Signup form. Navigate to the email/email.component.ts file:
import { Component, OnInit } from '@angular/core'; import { AuthService } from '../auth.service'; @Component({ selector: 'app-email', templateUrl: './email.component.html', styleUrls: ['./email.component.css'] }) export class EmailComponent implements OnInit { constructor( private authService: AuthService) { } ngOnInit() {} onSubmit(formData) { if (formData.valid) { console.log(formData.value); this.authService.login( formData.value.email, formData.value.password ); } } }
Next, let’s navigate to the email/email.component.html file and add the following (I’m adding the screenshot of the template because it’s been interpreted incorrectly):
Angular Authentication with Firestore Email Login Form
The login form now looks like this:
Angular Firebase Authentication Email Login Form
Next, let’s work on the Signup form and its component:
import { Component, OnInit } from '@angular/core'; import { AuthService } from '../auth.service'; @Component({ selector: 'app-signup', templateUrl: './signup.component.html', styleUrls: ['./signup.component.css'] }) export class SignupComponent implements OnInit { constructor(public authService: AuthService) { } ngOnInit() {} onSubmit(formData) { if (formData.valid) { console.log(formData.value); this.authService.emailSignup( formData.value.email, formData.value.password ); } } }
And then the template:
Angular Firebase Authentication Email Sign up Form
Lastly, the profile component which is the simplest of all, there we just need to add a Sign Out button that will take the user back to the Login Page.
import { Component, OnInit } from '@angular/core'; import { AuthService } from '../auth.service'; @Component({ selector: 'app-profile', templateUrl: './profile.component.html', styleUrls: ['./profile.component.css'] }) export class ProfileComponent implements OnInit { constructor(public authService: AuthService) { } ngOnInit() {} signOut() { this.authService.logout(); } }
Angular Firebase Authentication Profile Page
There’s still room for improvement, we can check the state of the current user and guard the profile page so that a stranger can’t go to User’s profile without Logging in. If you are reading this, you’ve probably navigated your way through this tutorial successfully.
Originally published on dunebook.com
#angular #firebase