Firebase Authentication in Angular

Firebase Authentication in Angular

Written by Wael Manai on Nov 28th, 2018 Views Report Post

Firebase provides a very simple way to setup authentication in your apps. Here we’ll explore how to setup a simple email/password signup and authentication workflow for Angular 2+ apps using the AngularFire2 library.

The first step will be to create a new Firebase project and enable the Email/Password sign-in method under the Authentication section of the Firebase console.

Let’s get started by installing the necessary packages using npm. This will add the Firebase SDK, AngularFire2 and a promise-polyfill dependency to your project:

$ npm install firebase angularfire2 --save
$ npm install promise-polyfill --save-exact
Now let’s add our Firebase API and project credentials to the environment variable of our project. You’ll find these values in your Firebase console if you click on Add Firebase to your web app:


src/environments/environment.ts

export const environment = {
  production: false,
  firebase: {
    apiKey: 'XXXXXXXXXXX',
    authDomain: 'XXXXXXXXXXX',
    databaseURL: 'XXXXXXXXXXX',
    projectId: 'XXXXXXXXXXX',
    storageBucket: 'XXXXXXXXXXX',
    messagingSenderId: 'XXXXXXXXXXX'
  }
};
Then we’ll configure our app module with AngularFireModule and AngularFireAuthModule. Notice also that we’re importing and providing an AuthService. We’ll create that service next:


app.module.ts

// ...

import { AngularFireModule } from 'angularfire2';
import { environment } from '../environments/environment';
import { AngularFireAuthModule } from 'angularfire2/auth';

import { AuthService } from './auth.service';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    // ...
    AngularFireModule.initializeApp(environment.firebase),
    AngularFireAuthModule
  ],
  providers: [AuthService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Creating the Auth Service

Our service will be a central place that allows us to login, signup or logout users, so we’ll define methods for these 3 actions. All the authentication logic will be in the service, which will allow us to create components that don’t need to implement any auth logic and will help keep our components simple.

You can create the skeleton for the service using the Angular CLI using this command:

$ ng g s auth
And here’s the implementation of the service, making use of AngularFireAuth:


auth.service.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 {
  user: Observable<firebase.User>;

  constructor(private firebaseAuth: AngularFireAuth) {
    this.user = firebaseAuth.authState;
  }

  signup(email: string, password: string) {
    this.firebaseAuth
      .auth
      .createUserWithEmailAndPassword(email, password)
      .then(value => {
        console.log('Success!', value);
      })
      .catch(err => {
        console.log('Something went wrong:',err.message);
      });    
  }

  login(email: string, password: string) {
    this.firebaseAuth
      .auth
      .signInWithEmailAndPassword(email, password)
      .then(value => {
        console.log('Nice, it worked!');
      })
      .catch(err => {
        console.log('Something went wrong:',err.message);
      });
  }

  logout() {
    this.firebaseAuth
      .auth
      .signOut();
  }

}

You’ll notice that the methods available on AngularFireAuth.auth all return promises so we can use then and catch to deal with the success and error states respectively.

We use createUserWithEmailAndPassword and signInWithEmailAndPassword here since we’re setting up email/password auth, but equivalent methods are available for authentication with Twitter, Facebook or Google.

Component Class and Template

Now that our auth service is in place, it’s really simple to create a component that allows for logging in, signing up or logging out:

app.component.ts

import { Component } from '@angular/core';
import { AuthService } from './auth.service';

@Component({ ... })
export class AppComponent {
  email: string;
  password: string;

  constructor(public authService: AuthService) {}

  signup() {
    this.authService.signup(this.email, this.password);
    this.email = this.password = '';
  }

  login() {
    this.authService.login(this.email, this.password);
    this.email = this.password = '';    
  }

  logout() {
    this.authService.logout();
  }
}

We inject the service in the component’s constructor and then define local methods that call the equivalent methods on the auth service. We inject the service with the public keyword instead of private so that we can access the service properties directly from the template too.

The template is very simple and uses the async pipe on the authService’s user object to determine if there’s a logged-in user or not:


app.component.html

<h1 *ngIf="authService.user | async">Welcome {{ (authService.user | async)?.email }}!</h1>

<div *ngIf="!(authService.user | async)">
  <input type="text" [(ngModel)]="email" placeholder="email">
  <input type="password" [(ngModel)]="password" placeholder="email">

  <button (click)="signup()" [disabled]="!email || !password">
    Signup
  </button>

  <button (click)="login()" [disabled]="!email || !password">
    Login
  </button>
</div>

<button (click)="logout()" *ngIf="authService.user | async">
  Logout
</button>

Our input fields two-way bind to the email and password values in our component class using ngModel and the banana in a box syntax.


Done! It's that simple to add authentication to your apps using Firebase authentication.

Comments (0)