Complete Step-by-Step Firebase Authentication in Angular 2
Firebase Authentication provides back-end services, easy-to-use software development kits (SDK), and ready-made UI libraries to authenticate users to your app. It supports authentication by using passwords, phone numbers, popular federated identity providers (e.g. Google, Facebook, Twitter, GitHub), and more.
Throughout this post, I’ll refer to Angular 2 as simply Angular. Note that Angular 1 is referred to as AngularJS.
In this tutorial, I’ll take you through how to easily handle authentication in your Angular application by using the following sign-in methods:
- Regular Email/Password
- GitHub
- Gmail
Let's Get Started
Generally speaking (oh sorry, coding), you can follow these steps to create your new Angular app. We’ll be using Angular CLI. Alternatively, you can skip this step and clone the starter version of the app in my GitHub repository.
$ ng new angular2-authentication-firebase
$ cd angular2-authentication-firebase
$ ng serve
$ npm install --save font-awesome angular2-fontawesome
In the above code, we've created a new Angular app using Angular CLI. We moved into the directory and served the application using the ng serve
command. We also pulled in the Font Awesome library so we can take advantage of its icons.
If your browser doesn't automatically open, visit http://localhost:4200.
Include Bootstrap and Font Awesome in your app by adding the following lines to your src/styles.css
file:
@import "~bootstrap/dist/css/bootstrap.min.css";
@import "~font-awesome/css/font-awesome.css";
Clone the Starter Repository
I've created a starter Angular 2 application already — clone it here. These are all pre-installed:
- A login component and a dashboard component with their HTML and CSS written.
- Bootstrap’s HTML and CSS.`
- Font Awesome — for the social icons
The final version can be found here.
Now, run the command:
npm install
It will look like this:
Let's Add Authentication
Create a Firebase app. Visit firebase.google.com and click Sign In. Then click Go to Console.
Click Add A Project and you’ll see the image below. Fill it out like so:
Once you're in your dashboard, click Add Firebase to your web app and copy the configuration settings as highlighted in the image below:
Run the command below in your terminal to pull in angularfire2
for your authentication:
$ npm install angularfire2 firebase --save
Go to src/environments/environments.ts
and paste the configuration like this:
// src/environments/environments.ts
export const environment = {
production: false,
firebase: {
apiKey: "<Your_API_KEY_HERE>",
authDomain: "AUTH-DOMAIN-HERE",
databaseURL: "DATABASE-URL-HERE",
projectId: "PROJECT-ID-HERE",
storageBucket: "STORAGE-BUCKET-HERE",
messagingSenderId: "MESSAGING-SENDER-ID-HERE"
};
};
Go to app.module.ts
and import the AngularFireModule
, AngularFireDatabaseModule
, and AngularFireAuth
modules. Also, import the environment configuration. Add these to 'imports' under 'NgModule Decorator' like so:
// src/app/app.modules.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutes } from "./app.routes";
import { AppComponent } from './app.component';
import { LoginComponent } from './views/login/login.component';
import { DashboardComponent } from './views/dashboard/dashboard.component';
**import { environment } from '../environments/environment';
import { AngularFireModule } from 'angularfire2';
import { AngularFireDatabaseModule } from 'angularfire2/database';
import { AngularFireAuthModule } from 'angularfire2/auth';**
@NgModule({
declarations: [
AppComponent,
LoginComponent,
DashboardComponent
],
imports: [
BrowserModule,
AppRoutes,
** AngularFireModule.initializeApp(environment.firebase, 'angular-auth-firebase'),
AngularFireDatabaseModule,
AngularFireAuthModule**
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Let's create an auth service to implement the authentication. We'll create services so that it can be accessible and used by all of our components whenever and wherever they're located. We can do this using Angular CLI:
$ ng generate service services/auth
This creates auth.service.ts
inside the src/app/services folder. Import it in your modules. Then we'll add it to providers in our app.module.ts
.
// src/app/services/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutes } from "./app.routes";
import { AppComponent } from './app.component';
import { LoginComponent } from './views/login/login.component';
import { DashboardComponent } from './views/dashboard/dashboard.component';
import { environment } from '../environments/environment';
import { AngularFireModule } from 'angularfire2';
import { AngularFireDatabaseModule } from 'angularfire2/database';
import { AngularFireAuthModule } from 'angularfire2/auth';
**import { AuthService } from './services/auth.service';**
@NgModule({
declarations: [
AppComponent,
LoginComponent,
DashboardComponent
],
imports: [
BrowserModule,
AppRoutes,
AngularFireModule.initializeApp(environment.firebase, 'angular-auth-firebase'),
AngularFireDatabaseModule,
AngularFireAuthModule
],
providers: [**AuthService**],
bootstrap: [AppComponent]
})
export class AppModule { }
In the auth.service.ts
file, import AngularFireAuth, Firebase, and Observable. Create an Observable user variable, inject Firebase Auth in the constructor, and create sign in methods. Your auth.service.ts
becomes:
// src/app/services/auth.service.ts
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';
@Injectable()
export class AuthService {
private user: Observable<firebase.User>;
constructor(private _firebaseAuth: AngularFireAuth, private router: Router) {
this.user = _firebaseAuth.authState;
}
}
Sign In With Twitter
Go to the Firebase Console. Click Authentication menu item on the right. Click Sign-In Method and choose Twitter. Enable it.
Go to dev.twitter.com/apps and create an app. Fill in the information, including a valid URL where your application will be hosted.
Click on the Keys and Access Token tab. Copy the Consumer Key (API Key) and Consumer Secret (API Secret), then paste them in your Firebase console. Click save.
When you hit Save, it generates a link for you. Copy the link from your Firebase console. Go to the Settings tab on your Twitter Developer dashboard and paste the link in the Callback URL Field. This is very important. See images below.
Add the signInWithTwitter()
function in your auth service, like so:
// ...auth.service.ts
...
signInWithTwitter() {
return this._firebaseAuth.auth.signInWithPopup(
new firebase.auth.TwitterAuthProvider()
)
}
...
In your app/views/login.ts
, import the AuthService, inject it in the constructor, and implement Twitter login.
// src/app/views/login/login.component.ts
import { Injectable } from '@angular/core';
import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AuthService {
private user: Observable<firebase.User>;
constructor(private _firebaseAuth: AngularFireAuth) {
this.user = _firebaseAuth.authState;
}
signInWithTwitter() {
return this._firebaseAuth.auth.signInWithPopup(
new firebase.auth.TwitterAuthProvider()
)
}
}
Add the click function in your login HTML file. Open the login.component.html
and add the click function. See snippet below:
<button type="button" class="btn btn-block" **(click)="signInWithTwitter()**">
<i class="fa fa-twitter" aria-hidden="true"></i>
Login with Twitter
</button>
Go to your app on the web and click the Login with Twitter button. It will ask you to authorize the app or log in with your Twitter credentials, then it'll take you to the dashboard page.
Sign In With Facebook
For authentication using Facebook, visit developer.facebook.com and log in with your Facebook credentials. Create/Add a new app. Type in the Display Name and Create App ID.
Click Settings on the side menu. Copy the app ID, click to show the app secret, and copy that as well. Go to your Firebase console, and under sign-in methods, enable Facebook then paste the app ID and app secret.
Now, let's add the signInWithFacebook()
function to our login component and login HTML.
// login.component.ts
...
signInWithFacebook() {
this.authService.signInWithFacebook()
.then((res) => {
this.router.navigate(['dashboard'])
})
.catch((err) => console.log(err));
}
...
In our login HTML file, let's add all the logins once and for all. Our HTML becomes:
// login.component.html
...
<div class="form-group">
<button type="buton" class="btn btn-block" (click)="signInWithFacebook()">
<i class="fa fa-facebook" aria-hidden="true"></i>
Login with Facebook
</button>
<button type="button" class="btn btn-block" (click)="signInWithTwitter()">
<i class="fa fa-twitter" aria-hidden="true"></i>
Login with Twitter
</button>
<button type="button" class="btn btn-block" (click)="signInWithGithub()">
<i class="fa fa-github" aria-hidden="true"></i>
Login with Github
</button>
<button type="button" class="btn btn-block" (click)="signInWithGoogle()">
<i class="fa fa-google" aria-hidden="true"></i>
Login with Google
</button>
</div>
...
Sign In With Google
For Google account sign-in, enable Google authentication in your Firebase console and click Save.
// src/app/services/auth.service.ts
...
signInWithGoogle() {
return this._firebaseAuth.auth.signInWithPopup(
new firebase.auth.GoogleAuthProvider()
)
}
...
It's important to add the following functions: isLoggedIn()
and Logout()
. isLoggedIn()
will return a Boolean type if the user is logged in. This will ensure that certain pages and displays are only available to authorized users.
logout() function
, when called, logs the current user out. It is also essential to protect the application once the user is finished using it.
A complete auth.service
file looks like this:
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';
@Injectable()
export class AuthService {
private user: Observable<firebase.User>;
private userDetails: firebase.User = null;
constructor(private _firebaseAuth: AngularFireAuth, private router: Router) {
this.user = _firebaseAuth.authState;
this.user.subscribe(
(user) => {
if (user) {
this.userDetails = user;
console.log(this.userDetails);
}
else {
this.userDetails = null;
}
}
);
}
signInWithTwitter() {
return this._firebaseAuth.auth.signInWithPopup(
new firebase.auth.TwitterAuthProvider()
)
}
signInWithFacebook() {
return this._firebaseAuth.auth.signInWithPopup(
new firebase.auth.FacebookAuthProvider()
)
}
signInWithGoogle() {
return this._firebaseAuth.auth.signInWithPopup(
new firebase.auth.GoogleAuthProvider()
)
}
isLoggedIn() {
if (this.userDetails == null ) {
return false;
} else {
return true;
}
}
**logout() {
this._firebaseAuth.auth.signOut()
.then((res) => this.router.navigate(['/']));
}
}
logout() {
this._firebaseAuth.auth.signOut()
.then((res) => this.router.navigate(['/']));
}
}**
Thank you for taking the time to read this post — hopefully it's been helpful to you. I'll be publishing Part Two, which will entail:
- GitHub authentication
- Regular signup/signin
- Safeguarding the dashboard page
Thanks! Kindly share, like, and comment. Also, you can follow me on Twitter @ hellotunmbi!
This post is originally published by the author here. This version has been edited for clarity and may appear different from the original post.
Hi. Is this outdated already? I can not get to work. Ng serve is returning an error.
Where is part 2, please? I’m not seeing a link.
Here it is: https://medium.com/@hellotunmbi/part-2-complete-step-by-step-firebase-authentication-in-angular-2-25d284102632
Thanks for the post! It is very useful. Regarding authenticating with a username and password, I am trying to create a page where the ‘admin’ can create multiple users at one go. How can we do this? I am told to use cloud functions but how do we do that? Any suggestion would be great.
This is authentication where the user inputs his details to gain access. However, for your case, you can make us of cloud functions, which would be the perfect solution to create users and authenticate them by yourself(from the admin).
I might just be writing an article on it soonest.
Please do write on cloud functions. I would love to learn more on that.
In this case, I was able to solve it by initializing a second instance of the app. By doing this the reauthentication problem stopped.
But please do write on cloud functions. I would like to understand them.
Alrighty Eashwar, I’ll write up on that pretty soon. Do watch out for it
And cool, you were able to figure a way around it.