Authentication is one of the common part of any web and mobile application, in this tutorial will cover how to use Firebase API in Angular2 project for open authentication. It includes Facebook, google, twitter and GitHub. We will use angular CLI for completing this project.
Prerequisite
- Facebook App https://developers.facebook.com/apps
- Twitter App https://apps.twitter.com
- GitHub App https://github.com/settings/applications/new
- Firebase App https://console.firebase.google.com
Application Flow
There will be 2 pages one is for login and another would be home page which has to be login protected, once user authenticate successfully with any of the login provider he will redirect to home page. Where we have to show user's displayName, photo and email address.
Install Angular CLI using below command
:~$ npm install @angular/cli -g
Create a new angular project :~$ ng new AngularAuth
:~$ cd AngularAuth
:~$ ng serve
Application will be up and running on port 4200 http://localhost:4200/
Create Firebase App
You can create Google Firebase App from console Firebase Console
Install required dependencies firebase and angularfire2
For consume firebase API in angular we need to install firebase and angularfire2 lib using npm
:~$ npm install firebase angularfire2 --save
First we need to configure AngularFireModule and AnglarFireAuth as below
app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { AppComponent } from './app.component'; import { AngularFireModule } from 'angularfire2'; import { AngularFireAuth } from 'angularfire2/auth'; export const firebaseConfig = { apiKey: "api-key", authDomain: "auth-domain", databaseURL: "database-url", projectId: "project-id", storageBucket: "storage-bucket", messagingSenderId: "sender-id" }; @NgModule({ declarations: [ AppComponent, ], imports: [ BrowserModule, FormsModule, HttpModule, AngularFireModule.initializeApp(firebaseConfig), ], providers: [AngularFireAuth], bootstrap: [AppComponent] }) export class AppModule
Firebase json configuration you can get it from Firebase console click on “Add Firebase to your web app”
![]() |
Project Overview Page |
Create an Authorization service
In order to use firebase authentication in our application it is good to encapsulate authentication functions in one service, Lets create a service using angular CLI.
:~$ ng generate service providers/auth.service.ts
auth.service.ts
import { Injectable } from '@angular/core'; import { AngularFireAuth } from 'angularfire2/auth'; import * as firebase from 'firebase/app'; @Injectable() export class AuthService { constructor(public afa: AngularFireAuth) { } loginWithGoogle() { return this.afa.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider()); } loginWithFacebook() { return this.afa.auth.signInWithPopup(new firebase.auth.FacebookAuthProvider()); } loginWithTwitter() { return this.afa.auth.signInWithPopup(new firebase.auth.TwitterAuthProvider()); } loginWithGitHub() { return this.afa.auth.signInWithPopup(new firebase.auth.GithubAuthProvider()); } logout() { localStorage.clear(); return this.afa.auth.signOut(); }}
We need to import AngularFireAuth from angularfire2 lib and firebase from firebase lib. Next, AngularFireAuth service is injected into the constructor as public in AuthService. logout() method we are clearing out the localstorage data, will use localStorage to stroe displayname, email, photourl from app.component.ts
The AuthService consist of 5 following methods
loginWithFacebook() loginWithGoogle() loginWithTwitter() loginWithGitHub() logout()
AngularFireAuth provide two methods for OAuth, one is signInWithPopUp(provider) and signInWithRedirect(provider), one opens popup window within the page and another redirect you to auth providers website respectively. Both method requires authentication object as parameter, Authentication object means which auth provider you want to use.
Create LoginPage Component
:~$ ng generate component loginPage
Let’s implement LoginPage Component, This component will wrap the AuthService methods to make available for login-page html template, Inject the AuthService and Router as belowlogin-page.component.ts
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { AuthService } from '../providers/auth.service'; @Component({ selector: 'app-login-page', templateUrl: './login-page.component.html', styleUrls: ['./login-page.component.css'], }) export class LoginPageComponent implements OnInit { constructor(public authService: AuthService, private router: Router) { } ngOnInit() { } loginGoogle() { this.authService.loginWithGoogle().then((data)=> { this.router.navigate(['']); }); } loginFacebook() { this.authService.loginWithFacebook().then((data)=> { this.router.navigate(['']); }); } loginTwitter() { this.authService.loginWithTwitter().then((data)=> { this.router.navigate(['']); }); } loginGitHub() { this.authService.loginWithGitHub().then((data)=> { this.router.navigate(['']); }); } }
Login Page HTML
Let's create login html page, i'm using bootstrap 4 for designing this page and also custom css for social login buttons
login-page.component.html
<div class="container" style="margin-top: 20px"> <div class="row"> <div class="col-md-3"> <button class="loginBtn loginBtn--facebook" type="button" (click)="loginFacebook()">Login with Facebook</button> </div> <div class="col-md-3"> <button class="loginBtn loginBtn--twitter" type="button" (click)="loginTwitter()">Login with Twitter</button> </div> <div class="col-md-3"> <button class="loginBtn loginBtn--google" type="button" (click)="loginGoogle()">Login with Google</button> </div> <div class="col-md-3"> <button class="loginBtn loginBtn--github" type="button" (click)="loginGitHub()">Login with GitHub</button> </div> </div> </div>
Each button attached an onclick event and its calling the exposed method by loginPage component i.e loginWith Facebook, Twitter, Google, GitHub respectively.
Create Home Page Component
:~$ ng generate component homePage
This component is to show user's displayName, email and photo, inject AuthService and Router and implement logout() method which will invalidate users logged-in session.
home-page.component.ts
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { AuthService } from '../providers/auth.service'; @Component({ selector: 'app-home-page', templateUrl: './home-page.component.html', styleUrls: ['./home-page.component.css'] }) export class HomePageComponent implements OnInit { private displayName: string; private photoURL: string; private email: string; constructor(private authService: AuthService, private router: Router) { this.displayName = localStorage.getItem('displayName'); this.photoURL = localStorage.getItem('photoURL'); this.email = localStorage.getItem('email'); } ngOnInit() { } logout() { this.authService.logout(); this.router.navigate(['login']); } }
We are getting the data from local storage which we will storing from app.component.ts
Home Page HTML
Let's create home page html, as we are using bootstrap 4 for desiging the pages. Here i'm using card to display photo, username and email
home-page.component.html
<div class="container"> <div class="card" style="margin-top: 20px; width: 18rem;"> <img class="card-img-top" src={{photoURL}} alt="Card image cap"> <div class="card-body"> <h5 class="card-title">Welcome {{displayName}}</h5> <p class="card-text">{{email}}</p> <a href="#" (click)="logout()" class="btn btn-primary">Logout</a> </div> </div> </div>
Navigation
In this application we have two pages, so definitely will need two routes to navigate to these pages "/ " and "/login" for home page and login page respectively. Lets implement routing.
We are configuring routing in app.module.ts, add the below code snippet.
app.module.ts
import { RouterModule, Routes } from '@angular/router'; const routes: Routes = [ { path: '', component: HomePageComponent }, { path: 'login', component: LoginPageComponent } ]; @NgModule({ declarations: [ AppComponent, HomePageComponent, LoginPageComponent ], imports: [ BrowserModule, FormsModule, HttpModule, AngularFireModule.initializeApp(firebaseConfig), RouterModule.forRoot(routes) ], providers: [AngularFireAuth, AuthService], bootstrap: [AppComponent] })
Auth Gaurd
Finally we have to protect our home page by unauthorized access, Let’s add the code in App component constructor by injecting AngularFireAuth and Router. AngularFireAuth has instance variable authState which returns firebase.User observable, so we can subscribe on and check the auth status.app.component.ts
import { Component } from '@angular/core'; import { Router } from '@angular/router'; import { Observable } from 'rxjs/Observable'; import * as firebase from 'firebase/app'; import { AngularFireAuth } from 'angularfire2/auth'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { private isLoggedIn: boolean; private displayName: string; user: Observable<firebase.User>; constructor(afAuth: AngularFireAuth, private router: Router) { this.user = afAuth.authState; this.user.subscribe((auth) => { if(auth == null) { this.isLoggedIn = false; console.log("auth is null"); this.router.navigate(['login']); } else { this.isLoggedIn = true; this.displayName = auth.displayName; localStorage.setItem('displayName', auth.displayName); localStorage.setItem('email', auth.email); localStorage.setItem('photoURL', auth.photoURL); } }); } }
We have declared 2 instance variable which holds loggedin status and display name and then based on isLoggedIn variable we will show user displayName on common navbar.
Add common navbar in app component template
App component is a root component where we have our router outlet, so whatever we add in this page will display for all components.
app.component.html
<nav class="navbar navbar-dark bg-dark"> <a href="#" class="navbar-brand">NinjaCoders.info</a> <span class="pull-right" *ngIf="isLoggedIn" style="color: yellow"> {{displayName}}</span> <span class="pull-right" *ngIf="!isLoggedIn" style="color: yellow"> Logged Out</span> </nav> <div> <router-outlet></router-outlet> </div>
If user is logged in we are showing displayName else showing status as Logged Out.
That's it.
Next tutorial will learn how to deploy Angular apps to Firebase and GitHub pages.
No comments:
Post a Comment