Angular 4 Firebase Auth – Send Reset Password Email with AngularFire2 v4

In previous post, we had know way to build an Angular 4 App that allows user sign up and login (with form validation). This tutorial shows you how to implement function that can send Reset Password Email using AngularFire2 v4.

Related Posts:
Angular 4 Firebase Auth – Anonymous Authentication with AngularFire2 v4
Angular 4 Firebase Auth – Email/Password Authentication with AngularFire2 v4

I. Technology

– Angular 4
– AngularFire2 4.0

II. Overview

Basing on code from previous post, we will continue to add send Reset Password function:
angular-4-firebase-auth-reset-password-overview

II. How to do

1. Set up the Firebase Project & Install AngularFire2

Please visit this post to know step by step.

angular-4-firebase-integration-copy-firebase-project-config

2. Enable Firebase Auth for Email/Password

Go to your Project on Firebase Console -> Authentication tab -> SIGN-IN METHOD -> enable Email/Password:
angular-4-firebase-auth-email-password-enable-console

3. Build Angular 4 App that supports Email/Password Authentication

For details, take a look at the post below:
Angular 4 Firebase Auth – Email/Password Authentication with AngularFire2 v4

4. Auth Service
import {AngularFireAuth} from 'angularfire2/auth';

@Injectable()
export class AuthService {

  authState: any = null;

  constructor(private afAuth: AngularFireAuth, private router: Router) {
    this.afAuth.authState.subscribe((auth) => {
      this.authState = auth
    });
  }
  
  resetPassword(email: string) {
    return this.afAuth.auth.sendPasswordResetEmail(email)
      .then(() => console.log('sent Password Reset Email!'))
      .catch((error) => console.log(error))
  }
}

– We subscribe to the AngularFire auth observable that returns a FirebaseAuthState object. This object is null when logging out, and contains useful User Information (UID, Display Name, Photo URL…) when logging in.
– We use AngularFireAuth.auth.sendPasswordResetEmail() to send reset password email.

5. App Module
// ...
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';

import {AngularFireModule} from 'angularfire2';
import {AngularFireAuthModule} from 'angularfire2/auth';

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

@NgModule({
  // ...
  imports: [
    BrowserModule,
    FormsModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFireAuthModule
  ],
  providers: [AuthService],
  // ...
})
6. Use Service – Login Component
import {AuthService} from '../auth.service';

@Component({
  selector: 'user-login',
  templateUrl: './user-login.component.html',
  styleUrls: ['./user-login.component.css']
})
export class UserLoginComponent implements OnInit {

  resetPassword = false;
  
  constructor(public authService: AuthService) {}
  
  isValidMailFormat(email: string) {
    const EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;

    if ((email.length === 0) && (!EMAIL_REGEXP.test(email))) {
      return false;
    }

    return true;
  }

  sendResetEmail() {
    this.authService.resetPassword(this.email)
      .then(() => this.resetPassword = true)
      .catch(_error => {
        this.error = _error
      })
  }
}

isValidMailFormat(email) function checks if user has entered right email format or not.
Once that format is right, link for resetting password will appear.
And after resetPassword() is done, resetPassword flag will be changed to true for displaying notification.
If there is an error, we can catch it and display as notification.
Template:

{{error.message}}

Reset Password for {{email}}

Check your email to reset password!

III. Practice

1. Project structure

angular-4-firebase-auth-anonymous-structure

2. App Module
import {environment} from '../environments/environment';
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {AppRoutingModule} from './app-routing.module';

import {AngularFireModule} from 'angularfire2';
import {AngularFireAuthModule} from 'angularfire2/auth';

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

import {AppComponent} from './app.component';
import {UserLoginComponent} from './auth/user-login/user-login.component';
import {UserInfoComponent} from './auth/user-info/user-info.component';

@NgModule({
  declarations: [
    AppComponent,
    UserLoginComponent,
    UserInfoComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFireAuthModule
  ],
  providers: [AuthService],
  bootstrap: [AppComponent]
})
export class AppModule {}
3. Auth Service
import {Injectable} from '@angular/core';
import {Router} from '@angular/router';
import {AngularFireAuth} from 'angularfire2/auth';

@Injectable()
export class AuthService {

  authState: any = null;

  constructor(private afAuth: AngularFireAuth, private router: Router) {
    this.afAuth.authState.subscribe((auth) => {
      this.authState = auth
    });
  }

  get isUserAnonymousLoggedIn(): boolean {
    return (this.authState !== null) ? this.authState.isAnonymous : false
  }

  get currentUserId(): string {
    return (this.authState !== null) ? this.authState.uid : ''
  }

  get currentUserName(): string {
    return this.authState['email']
  }

  get currentUser(): any {
    return (this.authState !== null) ? this.authState : null;
  }

  get isUserEmailLoggedIn(): boolean {
    if ((this.authState !== null) && (!this.isUserAnonymousLoggedIn)) {
      return true
    } else {
      return false
    }
  }

  signUpWithEmail(email: string, password: string) {
    return this.afAuth.auth.createUserWithEmailAndPassword(email, password)
      .then((user) => {
        this.authState = user
      })
      .catch(error => {
        console.log(error)
        throw error
      });
  }

  loginWithEmail(email: string, password: string) {
    return this.afAuth.auth.signInWithEmailAndPassword(email, password)
      .then((user) => {
        this.authState = user
      })
      .catch(error => {
        console.log(error)
        throw error
      });
  }

  signOut(): void {
    this.afAuth.auth.signOut();
    this.router.navigate(['/'])
  }

  resetPassword(email: string) {
    return this.afAuth.auth.sendPasswordResetEmail(email)
      .then(() => console.log('sent Password Reset Email!'))
      .catch((error) => console.log(error))
  }
}
4. Components
4.1 User Login Component

user-login.component.ts

import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {AuthService} from '../auth.service';

@Component({
  selector: 'user-login',
  templateUrl: './user-login.component.html',
  styleUrls: ['./user-login.component.css']
})
export class UserLoginComponent implements OnInit {

  isNewUser = true;
  email = '';
  password = '';
  errorMessage = '';
  error: {name: string, message: string} = {name: '', message: ''};

  resetPassword = false;

  constructor(public authService: AuthService, private router: Router) {}

  ngOnInit() {
  }

  clearErrorMessage() {
    this.errorMessage = '';
    this.error = {name: '', message: ''};
  }

  changeForm() {
    this.isNewUser = !this.isNewUser
  }

  onSignUp(): void {
    this.clearErrorMessage()

    if (this.validateForm(this.email, this.password)) {
      this.authService.signUpWithEmail(this.email, this.password)
        .then(() => {
          this.router.navigate(['/user'])
        }).catch(_error => {
          this.error = _error
          this.router.navigate(['/'])
        })
    }
  }

  onLoginEmail(): void {
    this.clearErrorMessage()

    if (this.validateForm(this.email, this.password)) {
      this.authService.loginWithEmail(this.email, this.password)
        .then(() => this.router.navigate(['/user']))
        .catch(_error => {
          this.error = _error
          this.router.navigate(['/'])
        })
    }
  }

  validateForm(email: string, password: string): boolean {
    if (email.length === 0) {
      this.errorMessage = 'Please enter Email!'
      return false
    }

    if (password.length === 0) {
      this.errorMessage = 'Please enter Password!'
      return false
    }

    if (password.length < 6) {
      this.errorMessage = 'Password should be at least 6 characters!'
      return false
    }

    this.errorMessage = ''

    return true
  }

  isValidMailFormat(email: string) {
    const EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;

    if ((email.length === 0) && (!EMAIL_REGEXP.test(email))) {
      return false;
    }

    return true;
  }

  sendResetEmail() {
    this.clearErrorMessage()

    this.authService.resetPassword(this.email)
      .then(() => this.resetPassword = true)
      .catch(_error => {
        this.error = _error
      })
  }
}

user-login.component.html

{{errorMessage}}

{{error.message}}

Already have an Account? >> Log In

{{errorMessage}}

{{error.message}}

Not have any Account yet? >> Register

Reset Password for {{email}}

Check your email to reset password!

4.2 User Info Component

user-info.component.ts

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

@Component({
  selector: 'user-info',
  templateUrl: './user-info.component.html',
  styleUrls: ['./user-info.component.css']
})
export class UserInfoComponent implements OnInit {

  constructor(public authService: AuthService) {}

  ngOnInit() {
  }

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

user-info.component.html

User Information

UID: {{ authService.currentUserId }}

Email: {{ authService.currentUserName }}

5. App Routing Module

app-routing.module.ts

import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';

import {UserLoginComponent} from './auth/user-login/user-login.component';
import {UserInfoComponent} from './auth/user-info/user-info.component';

const routes: Routes = [
  {path: '', redirectTo: 'login', pathMatch: 'full'},
  {path: 'login', component: UserLoginComponent},
  {path: 'user', component: UserInfoComponent},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})

export class AppRoutingModule {}
6. App Component

app.component.ts

import {Component} from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'JavaSampleApproach';
  description = 'Angular4-Firebase Demo';
}

app.component.html

{{title}}

{{description}}

7. Check Result

Run the App, go to http://localhost:4200/.

Check error case (email was not registered before):
angular-4-firebase-auth-reset-password-result-error

Send reset password:
angular-4-firebase-auth-reset-password-result-ok

Check email:
angular-4-firebase-auth-reset-password-result-check-mail

Click the link inside the email, new browser window will opened with pop-up for resetting our password:
angular-4-firebase-auth-reset-password-result-pop-up-reset-password

Now we can login with new password.

IV. Source Code

Angular4Firebase-Auth-Email-Reset-Password



By grokonez | September 14, 2017.

Last updated on November 29, 2018.



Related Posts


1 thought on “Angular 4 Firebase Auth – Send Reset Password Email with AngularFire2 v4”

Got Something To Say:

Your email address will not be published. Required fields are marked *

*