Subscribe for more content from me

In this post, we are going to cover the following:

In Firebase Auth, we will customize: Password Reset Email Content/Message

Add a Custom Domain for use by email address

And Password Reset/Email Verification URL In Angular: Send Password Reset Request Emails

Confirm Password Reset Code and Set New Password

Confirm Email Address

Prerequisite

Firebase Auth

Enable Email/Password Verification

First, we are going to enable email password authentication.

In your Firebase project home page, go to Authentication, on the side nav under Develop menu item. And then, select the sign-in method tab.

And then, under sign-in providers, under the Email/Password provider, hover to reveal the edit icon.

And finally, click toggle enable switch and save the changes.

Customize Email Address Domain

Next, let’s customize the email domain Firebase uses to send password reset requests and send user email verification requests to our users.

Under authentication, select the Templates tab.

Then, under Email address Verification , click on the edit icon next to the from email address.

And then, click on the customize domain link.

After that, you will be prompted for the domain name, enter the name and click next.

Here, you will be prompted to verify your domain name. This is done by adding the DNS records provided by firebase on the verification window to your domains DNS records. This process varies for different domain registrars but it’s also straightforward.

Once you have added the DNS records, click on the verify button. This can take time to verify the records – up to 48 hours on rare occasions – so don’t panic. Once the verification is done, all email sent by Firebase auth will use your domain name.

Customize the Password Reset Action URL

Next, let’s customize the password reset URL. By default, Firebase provides a preset URL with a generic UI that handles password resets. We are going to change this so that we can point it to our angular app which will handle confirmation and setting of the new password. This will be configured under the Templates Tab in Firebase Authentication.

On the sidebar, select Password Reset and scroll to the bottom.

Click on the Customize Action URL link, below the Action URL Text Field and Just Above the Save Button.

A modal window titled Action URL will pop up, prompting you to enter a Custom Action URL. Enter a Custom Action URL of your choice – something like http://localhost:4200/auth/email/action and save.

NB: Keep in mind that both Password Reset, Email address change and Verification will share the same Action URL. A query parameter mode , alongside the oobCode parameter is appended to the action URL. The mode parameter holds the action type the user is performing i.e. password reset etc.

Customize Password Reset Message

This is not entirely necessary, but you might want to have a custom message for your app’s users. From the same page as above, you should see the message field, you can customize that by using HTML. Use the following placeholder strings, to inject dynamic data into the template.

%DISPLAY_NAME% - The recipient’s display name.

%APP_NAME% - The name of your app. You can set this value by editing the Public-facing name field on the Settings page.

%LINK% - The URL that the recipient must visit to complete the account management task. See Customize the action link URL.

%EMAIL% - The recipient’s email address.

%NEW_EMAIL% - The new email address to set as the recipient’s primary address. Used only in the Email Address Change template.

NB: You can also customize the Subject of the email too on the same page.

Angular Application

Assuming you already have created an Angular App and installed @angular/fire – check the prerequisite section above if you haven’t – let’s dive into sending a password reset request.

Sending Password Resets Requests Component

This component will collect user email addresses and request Firebase to send a password request if the email exists. Firebase authentication servers are going to determine is an Email exists or not.

We are going to start by creating a Reactive Form, with one FormControl . First, we are going to inject both FormBuilder and AngularFireAuth services into our component.

constructor ( private afAuth : AngularFireAuth , private fb : FormBuilder ) {}

And then, we are going to declare frmResetPassword property of type FormGroup , then set it to a new instance of FormGroup , with one form field named email . The form control is going to have validators for both required and obviously email.

frmPasswordReset : FormGroup = this . fb . group ({ email : [ null , [ Validators . required , Validators . email ]] });

Next, let’s add a method to be called on from submit, which is going to send a request to Firebase to Send A Password Reset Request to the provided email if it exists.

const email = this . frmPasswordReset . controls [ 'email' ]. value ; this . afAuth . auth . sendPasswordResetEmail ( email ). then ( () => { // success, show some message }, err => { // handle errors } );

When the above process completes successfully, an email address is sent to the user with the password reset link.

To handle errors, please check for a code property in the returned error. You can find a list of error codes for Firebase Auth here. I have attached a simple Firebase error parser at the bottom of this post.

And finally, here is the template for this component:

< form [ formGroup ]=" frmPasswordReset " ( submit )=" sendPasswordResetRequest ()" > < div class = "field has-text-left" > < label class = "label" >Email Address: </ label > < div class = "control has-icons-left" > < input formControlName = "email" class = "input is-focused" type = "email" > < span class = "icon is-small is-left" > < fa-icon [ icon ]=" faEnvelope " ></ fa-icon > </ span > </ div > < div class = "has-text-danger" > Email is required! </ div > < div class = "has-text-danger" > A valid email is required! </ div > </ div > < div class = "field" > < button [ disabled ]=" frmPasswordReset . invalid " class = "button is-block is-primary has-text-white is-fullwidth " > < fa-icon [ icon ]=" faSigninIcon " ></ fa-icon > Send Request </ button > </ div > </ form >

Confirming Email and Setting a New Password for the User

The password reset link and email confirmation/verification link are the same, with the only variants being oobCode and mode . The mode will determine whether a user is resetting a password or confirming their email address. It can either be resetPassword or verifyEmail .

This means that these two actions are going to be redirected to the same route in our Angular Application. As such, we are going to need 3 components – One for switching between the modes, one for resetting password and another for confirming/verifying email addresses.

Switching Between Reset Password and Verify Email Address

Let’s start with the Component for switching between Reset Password and Confirm Email Address. We will start by injecting ActivatedRoute service into our Component.

constructor ( private activatedActivated : ActivatedRoute ) {}

And then, let’s declare a property named mode and assign it the value of Query Parameter mode from the URL.

mode = this . activatedActivated . snapshot . queryParams [ 'mode' ];

And finally, in our template, we can use the value of the mode property to either display the Reset Password Component or the Verify Email Address Component using ng-switch .

< ng-container [ ngSwitch ]=" action " > <!-- password reset --> < ng-container * ngSwitchCase = "'resetPassword'" > < app-confirm-password-reset ></ app-confirm-password-reset > </ ng-container > <!-- verify email address --> < ng-container * ngSwitchCase = "'verifyEmail'" > < app-confirm-email-address ></ app-confirm-email-address > </ ng-container > <!-- default action --> < ng-container * ngSwitchDefault > <!—show an error message --> </ ng-container > </ ng-container >

Confirm Password Reset Code Component

In this component, we will do two things, first is to request the user to provide enter a new password. And then we will use this password and oobCode to save the new password. If the oobCode is valid, the password will be updated successfully, otherwise, it will fail.

We will start by injecting FormBuilder , ActivatedRoute , Router and AngularFireAuth services into our Component.

constructor ( private afAuth : AngularFireAuth , private fb : FormBuilder , private route : ActivatedRoute , private router : Router ) {}

And then we will declare a FormGroup property named frmSetNewPassword , with new and confirm password form fields:

frmSetNewPassword = this . fb . group ({ password : [ null , [ Validators . required ]], confirmPassword : [ null , [ Validators . required ]] });

And finally, inside our submit method, we will check if the two passwords match:

const password = this . frmSetNewPassword . controls [ 'password' ]. value ; const confirmPassword = this . frmSetNewPassword . controls [ 'confirmPassword' ]. value ; if ( password !== confirmPassword ) { // react to error return ; }

And then get the oobCode from the URL, using the ActivateRoute service.

const code = this . route . snapshot . queryParams [ 'oobCode' ];

And then finally send call the confirmPasswordReset , passing both the code and new password to update the users password.

this . afAuth . auth . confirmPasswordReset ( code , password ) . then (() => this . router . navigate ([ 'signin' ])) . catch ( err => { const errorMessage = FirebaseErrors . Parse ( err . code ); // check this helper class at the bottom });

If successful, we will redirect the user to the sign-in page where they can sign in with their new password, otherwise we will show the error.

And here is the template for the above form:

< form [ formGroup ]=" frmSetNewPassword " ( ngSubmit )=" setPassword ()" > < h3 class = "title is-5 has-text-black" > Set a new password </ h3 > < h4 class = "subtitle is-6 has-text-grey" >Please enter and confirm your new password</ h4 > < div class = "field" > < label class = "label" >Password: </ label > < div class = "control" > < input class = "input " type = "password" name = "password" formControlName = "password" > </ div > </ div > < div class = "field" > < label class = "label" >Confirm Password: </ label > < div class = "control" > < input class = "input " type = "password" name = "confirmPassword" formControlName = "confirmPassword" > < div class = "has-text-danger" > Confirm password is required! </ div > </ div > </ div > < div class = "field" > < div class = "control" > < button class = "button is-fullwidth is-primary" type = "submit" [ disabled ]="! frmSetNewPassword . valid " > < span class = "icon" > < fa-icon [ icon ]=" saveIcon " ></ fa-icon > </ span > < span >Reset</ span > </ button > </ div > </ div > </ form >

Verify Email Address

Verifying email addresses is out of the scope for this post, so I won’t go into details. Here is the code snippet to verify user email address:

const code = this . activateRoute . snapshot . queryParams [ 'oobCode' ]; this . afAuth . auth . applyActionCode ( code ) . then (() => { // do something after successful verification }) . catch ( err => { // show error message });

Remember to inject both AngularFireAuth and ActivatedRoute services:

constructor ( private afAuth : AngularFireAuth , private activateRoute : ActivatedRoute ) {}

NB: If you don’t require any user action, you can run the above code OnInit and show a loading animation.

Configure Router

And finally, all that is remaining is to configure our Angular Router:

const routes : Routes = [ { path : 'auth' , children : [ { //... Auth Guards For UnAuthenticated Users Here children : [ // ... { path : 'forgot-password' , component : PasswordResetRequestComponent , data : { title : 'Forgot Password' } } ] }, { path : 'email/action' , component : EmailConfirmationComponent , data : { title : 'Confirm Email Address' } } ] } ];

Bonus - Firebase Auth Errors Parser

Here is a simple helper method for checking errors returned by Firebase Auth: