How to use firebase reset password custom and manage & reset forgotten users passwords - #14

Learn how to use custom firebase reset password and manage & reset forgotten users passwords. Detailed how to implement the custom Firebase Auth Forgot/Reset Password template and send to user on Forgot Password Request. And the reset password URL would contain URL to your site instead of Firebase default URL. And on visit of this URL, how to call verify method of Firebase Auth and Form containing password fields submission in Laravel PHP with little help of JavaScript SDK.

Here, before we start, please read this Email verification chapter https://laravelwithfirebase.blogspot.com/2020/04/chapter-13-implement-custom-firebase-auth-email-verification-template-replace-default-view-using-laravel-php.html
Most of below content would be same.



Now lets begin to customize the URL, you get in your firebase email verification template. It looks like something https://test-cc4d3.firebaseapp.com/__/auth/action?mode=<action>&oobCode=<code>


Here, in above image, you have edit button for the editing the template. Click on that, then you will have "customize action URL" link at the bottom. You know for security rules, you can edit message, if you use firebase domain. But we can if we are using our own customized template. Now click on the button "customize action URL".


Here, we have added our domain url http://localhost/yourproject/yourmethod, so the email template would have this. (Note: This change is action url, will reflect to all your email templates like reset password etc.)

Now Firebase side work is done. Now lets come to Laravel PHP side.
First, we use our smtp to send email, inside of Firebase send mail.This has been covered in previous chapter also


Fetch link for Reset Password

 $link = app('firebase.auth')->getPasswordResetLink('someone@example.com');  

Then use Mail of Laravel, (assuming you are pretty much clear, to have template blade file in views folder and that blade will have your content and a dynamic variables like name, link etc.)

 use Mail;  
 $data['link'] = $link;  
 Mail::send('password-reset', compact('data'),  
           function ($m) {  
         $m->to('someone@example.com', 'John Carry')  
             ->subject('Password Reset');  
       });  
So, when you send your email, it would receive something as below with your domain url


Note: This email template is yours, not firebase, you can design any way you want. So now look at url. it is something like this
http://localhost/yourproject/yourmethod?mode=resetPassword&oobCode=2WGHWEUiMmIqTALRuWTGE4bD1XvzoYgYAO0G21Ve_-IAAAFxsGoqSA&apiKey=AIzaSyAxk3OUAewciGQ5CUXdJ4076dNCytkgicg&lang=en

It has appended its parameter like mode, oobCode and the apiKey. Now as soon as this url is hit. You will have a route for this

 Route::get('yourmethod', 'YourController@yourmethod')->name('yourmethod');  

In your controller, just call a view

 public function yourmethod(Request $request)  
 {  
 return view('yourview');  
 }  


Now in yourview.blade.php, you have to add a script file. From here begins the work of Javascript SDK

 <script src="https://www.gstatic.com/firebasejs/7.13.1/firebase.js"></script>  

Now add some script code

 <script>  
 document.addEventListener('DOMContentLoaded', function() {  
 var mode = fetchParamsbyUrl('mode');  
 var actionCode = fetchParamsbyUrl('oobCode');  
 var continueUrl = fetchParamsbyUrl('continueUrl');  
 var lang = fetchParamsbyUrl('lang') || 'en';  
 var apiKey = fetchParamsbyUrl('apiKey');  
 var config = {  
     'apiKey': apiKey  
   };  
 var app = firebase.initializeApp(config);  
 var auth = app.auth();  
 switch (mode) {  
     case 'resetPassword':  
       // Display reset password handler and UI.  
       handleResetPassword(auth, actionCode, continueUrl, lang);  
       break;  
     case 'recoverEmail':  
       // Display email recovery handler and UI.  
       handleRecoverEmail(auth, actionCode, lang);  
       break;  
     case 'verifyEmail':  
       // Display email verification handler and UI.  
       handleVerifyEmail(auth, actionCode, continueUrl, lang);  
       break;  
     default:  
       // Error: invalid mode.  
   }  
 }, false);  
 function fetchParamsbyUrl(name, url) {  
     if (!url) url = window.location.href;  
     name = name.replace(/[\[\]]/g, '\\$&');  
     var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),  
       results = regex.exec(url);  
     if (!results) return null;  
     if (!results[2]) return '';  
     return decodeURIComponent(results[2].replace(/\+/g, ' '));  
 }  
 function handleResetPassword(auth, actionCode, continueUrl, lang) {  
   var accountEmail;  
   // Verify the password reset code is valid.  
   auth.verifyPasswordResetCode(actionCode).then(function(email) {  
     var accountEmail = email;  
     //SUCCESS: URL VERIFIED  
     // NOW TODO: Show the reset screen with the user's email and ask the user for  
     // the new password.  
   }).catch(function(error) {  
 //ERROR: INVALID CODE OR EXPIRED  
   });  
 }  
 </script>  

Now you can create a form having two fields password and confirm password. Then on submit of this form, you have to add following code

 <script>  
    auth.confirmPasswordReset(actionCode, $("#password").val()).then(function(resp) {  
         // Password reset has been confirmed and new password updated.  
       }).catch(function(error) {  
         // Error occurred during confirmation. The code might have expired or the  
         // password is too weak.  
       });  
 </script>  

$("#password").val() is your code. It can be anything.

Your are done. The password reset flow has been completed. So hope your are clear how to customize the email process of Reset password of Firebase Auth. Please let us know if you have any doubt in above in comment section and also let us know if you require chapter on specific topic. Thanks for reading.


[UPDATED 12-06-2021] On our readers request, we are including a sample blade file for password reset


 <!DOCTYPE html>  
 <html lang="en">  
 <head>  
   <meta charset="UTF-8">  
   <meta http-equiv="X-UA-Compatible" content="IE=edge">  
   <meta name="viewport" content="width=device-width, initial-scale=1.0">  
   <title>Document</title>  
   <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>  
 </head>  
 <body>  
   <form autocomplete="off" method="post" id="form">  
     <label for="password">New Password</label>  
     <input type="password" name="password" id="password">  
     <label for="password_confirmation">Confirm Password</label>  
     <input type="password" name="password_confirmation" id="password_confirmation">  
     <button type="submit" id="submit">Submit</button>  
   </form>  
    <script src="https://www.gstatic.com/firebasejs/7.13.1/firebase.js"></script>   
    <script>   
     document.addEventListener('DOMContentLoaded', function() {   
     var mode = fetchParamsbyUrl('mode');   
     var actionCode = fetchParamsbyUrl('oobCode');   
     var continueUrl = fetchParamsbyUrl('continueUrl');   
     var lang = fetchParamsbyUrl('lang') || 'en';   
     var apiKey = fetchParamsbyUrl('apiKey');   
     var config = {   
       'apiKey': apiKey   
     };   
     var app = firebase.initializeApp(config);   
     var auth = app.auth();   
     switch (mode) {   
       case 'resetPassword':   
       // Display reset password handler and UI.   
       handleResetPassword(auth, actionCode, continueUrl, lang);   
       break;   
       case 'recoverEmail':   
       // Display email recovery handler and UI.   
       handleRecoverEmail(auth, actionCode, lang);   
       break;   
       case 'verifyEmail':   
       // Display email verification handler and UI.   
       handleVerifyEmail(auth, actionCode, continueUrl, lang);   
       break;   
       default:   
       // Error: invalid mode.   
     }   
     }, false);   
     function fetchParamsbyUrl(name, url) {   
       if (!url) url = window.location.href;   
       name = name.replace(/[\[\]]/g, '\\$&');   
       var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),   
       results = regex.exec(url);   
       if (!results) return null;   
       if (!results[2]) return '';   
       return decodeURIComponent(results[2].replace(/\+/g, ' '));   
     }   
     function handleResetPassword(auth, actionCode, continueUrl, lang) {   
     var accountEmail;   
     // Verify the password reset code is valid.   
     auth.verifyPasswordResetCode(actionCode).then(function(email) {   
       var accountEmail = email;   
       //SUCCESS: URL VERIFIED   
       // NOW TODO: Show the reset screen with the user's email and ask the user for   
       // the new password.   
     }).catch(function(error) {   
     //ERROR: INVALID CODE OR EXPIRED   
     });   
     }   
     $("#submit").click(function() {  
       auth.confirmPasswordReset(actionCode, $("#password").val()).then(function(resp) {   
         // Password reset has been confirmed and new password updated.   
       }).catch(function(error) {   
         // Error occurred during confirmation. The code might have expired or the   
         // password is too weak.   
       });   
     });  
     </script>   
 </body>  
 </html>  

Post a Comment

14 Comments

  1. can you please do an article about using models with laravel (Like elequent Orm)
    and a article about the auth middleware too thanks a lot for the efforts

    ReplyDelete
    Replies
    1. Yes, there are many requests for the Laravel models implementation with Firebase. We will surely have a chapter on this, as we build a complete solution on this. And till then you can read this https://laravelwithfirebase.blogspot.com/2020/05/chapter-15-laravel-with-firebase-sign-in-maintain-logged-in-session-using-middleware.html, if it helps you

      Delete
  2. Hello Users, Might your question regarding topic "custom reset password laravel" is solved here. Thanks for reading and keep supporting us by sharing our urls.

    ReplyDelete
  3. Swift_TransportException
    Cannot send message without a sender address

    ReplyDelete
    Replies
    1. The password reset link is generated but cannot send mail. And I didn't understand the blade code should we write the first script and then add 2 form labels , after that how to link the submit button with last script and what should be the action to the form ???

      Thank You !!

      Delete
    2. Ok this process has two separate steps.

      1. Generate link and send email. The error you got is the email is missing in any email send service you are using SmTp or mailgun etc.

      So 1st step. Only generates a link and sends to users.

      Delete
    3. Now

      2. The verify method. This is where user comes on click of the url.

      Here there is no PHP code involved. Everything is javascript. So no form submission.

      If you read doc. You find this line in script tag
      auth.confirmPasswordReset(actionCode

      This functions takes value of input id password and sends and password is updated.

      Hope it helps. Please share our blog.

      Delete
    4. Can't we send the mail from firebase itself

      Delete
    5. Can't we send the mail from firebase itself

      Delete
    6. And for blade code , I don't know more about JavaScript can you please write the blade file code for me ... [ https://stackoverflow.com/questions/67799140/how-to-impalement-javascript-for-the-given-set-of-code ] you are the only one who can answer it ( I just need the code of yourview.blade.php )

      Thank You and again its a wonderfully blog ❤ ❤

      Delete
    7. Yes, you can send directly from Firebase. Again it's template is simple. Blank white one

      Delete
    8. Yes give time till this weekend. Let us try to update this post to contain whole blade code

      Delete
    9. Hi suhasrkms

      please read after
      [UPDATED 12-06-2021] On our viewers request, we are including a sample blade file for password reset

      Delete