<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Smitter</title>
    <description>The latest articles on DEV Community by Smitter (@smitterhane).</description>
    <link>https://dev.to/smitterhane</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F388149%2Ff7658170-b831-469f-855a-997041a3fcbc.jpg</url>
      <title>DEV Community: Smitter</title>
      <link>https://dev.to/smitterhane</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/smitterhane"/>
    <language>en</language>
    <item>
      <title>Building my portfolio like it's infinity gauntlet</title>
      <dc:creator>Smitter</dc:creator>
      <pubDate>Sat, 31 Jan 2026 19:23:24 +0000</pubDate>
      <link>https://dev.to/smitterhane/building-my-portfolio-like-its-infinity-gauntlet-5e8i</link>
      <guid>https://dev.to/smitterhane/building-my-portfolio-like-its-infinity-gauntlet-5e8i</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/new-year-new-you-google-ai-2025-12-31"&gt;New Year, New You Portfolio Challenge Presented by Google AI&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;Hi there! I'm &lt;strong&gt;Zacky&lt;/strong&gt;, a Fullstack Developer enthusiastic about building applications that solve real-world "people problems".&lt;/p&gt;

&lt;p&gt;I work across the stack to bring ideas to life, primarily utilizing &lt;em&gt;JavaScript&lt;/em&gt;, &lt;em&gt;Node.js&lt;/em&gt;, &lt;em&gt;PHP&lt;/em&gt;, &lt;em&gt;PostgreSQL&lt;/em&gt;, and &lt;em&gt;MySQL&lt;/em&gt;. Recently, I've also been diving deep into the world of &lt;em&gt;Rust&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;My development philosophy centers on creating tools that help others. For example, I created and maintain &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/react-loading-indicators" rel="noopener noreferrer"&gt;RLI&lt;/a&gt;&lt;/strong&gt;, an open-source React component library of elegant loading indicators that has a growing popularity on NPM.&lt;/p&gt;

&lt;p&gt;I built this portfolio to showcase not just my projects, but my ability to blend technical &lt;em&gt;"how-to"&lt;/em&gt; with creative, interactive design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Portfolio
&lt;/h2&gt;


&lt;div class="ltag__cloud-run"&gt;
  &lt;iframe height="600px" src="https://iamzacky-1025592661494.us-central1.run.app"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;(Note: If the embed above doesn't work, you can view the live site here: &lt;a href="https://zacky.dev" rel="noopener noreferrer"&gt;zacky.dev&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;For this portfolio, I wanted a tech stack that offered the speed of a Single Page Application (SPA) with the security and robustness of a backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Stack &amp;amp; Tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; &lt;a href="https://remix.run/" rel="noopener noreferrer"&gt;Remix.js&lt;/a&gt; (Fullstack React framework)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Noteworthy Libraries&lt;/strong&gt; &lt;a href="https://threejs.org/" rel="noopener noreferrer"&gt;Three.js&lt;/a&gt;, &lt;a href="https://mui.com/material-ui/" rel="noopener noreferrer"&gt;Material UI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language:&lt;/strong&gt; TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment:&lt;/strong&gt; Google Cloud Run&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Editor:&lt;/strong&gt; &lt;a href="https://antigravity.google/" rel="noopener noreferrer"&gt;Antigravity&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Design Decisions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid Architecture:&lt;/strong&gt; Using Remix allowed me to keep the user experience snappy (SPA feel) while securely handling sensitive credentials and logic on the server side.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; I implemented lazy loading for pages to ensure the initial load time is instant, fetching resources only when the user needs them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility &amp;amp; UX:&lt;/strong&gt; The site features a meticulously designed Dark and Light mode, giving users control over their viewing preference. The UI was designed to be visually appealing and modern without sacrificing intuitiveness to finding information without clutter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SEO:&lt;/strong&gt; Sever Side Rendering enable the website to load rendered pages to help boost SEO ranking.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The AI Assistant
&lt;/h3&gt;

&lt;p&gt;I utilized &lt;strong&gt;Google Gemini 3.0&lt;/strong&gt; and Antigravity code Editor throughout the development process. Gemini was a personal tutor throughout the development process.&lt;br&gt;When I was stuck on complex logic, Gemini broke down the deep concepts, allowing me to understand the "why" before I patched up the "how."&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm Most Proud Of
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Successful GCP Deployment
&lt;/h3&gt;

&lt;p&gt;I am extremely proud of the successful deployment of this portfolio to Google Cloud Run. It was a significant achievement for me, as it demonstrated my ability to deploy a full-stack application to the cloud. The deployment process was smooth and seamless, and I was able to find information I needed from the Docs.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The 3D Interactive Experience
&lt;/h3&gt;

&lt;p&gt;I am extremely excited about the 3D interactive page. I wanted to move beyond standard web layouts, so I decided to write custom shaders to render 3D animations directly in the browser. I used ThreeJS to achieve this.&lt;/p&gt;

&lt;p&gt;This was a steep learning curve. &lt;strong&gt;Gemini 3.0&lt;/strong&gt; was instrumental here; it helped me bridge the gap between my JavaScript knowledge and the complex math required for shader languages. The result is a fluid, interactive visual that I think really shines spotlight on the portfolio.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Fully responsive design
&lt;/h3&gt;

&lt;p&gt;Responsive design is important for any website, and I'm proud to have implemented it in this portfolio. I used a combination of CSS media queries and JavaScript to ensure that the website is accessible on all devices.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Solving Problems (The RLI Library)
&lt;/h3&gt;

&lt;p&gt;I'm also proud to feature my open-source work directly on the site. Showcasing &lt;strong&gt;&lt;a href="https://github.com/hane-smitter/react-loading-indicator" rel="noopener noreferrer"&gt;RLI&lt;/a&gt;&lt;/strong&gt; (React Loading Indicators) demonstrates that I don't just build websites; I build solutions that other developers rely on. Seeing that project pull traction on NPM is a huge motivator for me to keep shipping open-source code.&lt;/p&gt;




&lt;p&gt;Thank you very much for reading this far. Your thoughts and feedback are much appreciated.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>googleaichallenge</category>
      <category>portfolio</category>
      <category>gemini</category>
    </item>
    <item>
      <title>I built Zeet. A Git-like version Control System</title>
      <dc:creator>Smitter</dc:creator>
      <pubDate>Mon, 13 Jan 2025 06:52:00 +0000</pubDate>
      <link>https://dev.to/smitterhane/i-built-zeet-a-git-like-version-control-system-n5o</link>
      <guid>https://dev.to/smitterhane/i-built-zeet-a-git-like-version-control-system-n5o</guid>
      <description>&lt;h2&gt;
  
  
  🚀 Source Code
&lt;/h2&gt;

&lt;p&gt;You can find the source code for Zeet on &lt;a href="https://github.com/hane-smitter/zeet" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎬 DEMO
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://asciinema.org/a/7t4qnJHib15cYWQkOCqhAXY55?autoplay=1" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fasciinema.org%2Fa%2F7t4qnJHib15cYWQkOCqhAXY55.svg" alt="zeet demo in asciicast" width="682" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;Some time back, my curiosity about the inner workings of Git led me on an exciting journey. I sifted through various resources(though not Git’s source code) to understand how Git works. Inspired, I wrote an &lt;a href="https://dev.to/smitterhane/understand-git-and-ease-the-rest-of-your-learning-32c3"&gt;article&lt;/a&gt; summarizing my findings. What stook with me from &lt;a href="https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F" rel="noopener noreferrer"&gt;git-scm book&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The major difference between Git and any other VCS (Subversion and friends included) is the way Git thinks about its data.&lt;br&gt;&lt;br&gt;
Conceptually, most other systems store information as a list of file-based changes.&lt;br&gt;&lt;br&gt;
Git doesn’t think of or store its data this way. Instead, Git thinks of its data more like a series of snapshots of a miniature filesystem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That insight stayed with me, but I didn't do much with it—until I stumbled upon a challenge to build a Version Control System (VCS). I embraced it eagerly, seeing it as an opportunity to transform my theoretical knowledge into a tangible project. And so, I worked on &lt;strong&gt;Zeet&lt;/strong&gt;—a lightweight, Git-inspired VCS built with &lt;strong&gt;Node.js&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Zeet Works
&lt;/h2&gt;

&lt;p&gt;Much like Git, Zeet manages repository versions as snapshots. It uses a &lt;code&gt;.zeet&lt;/code&gt; directory to store all its data locally, but unlike Git, the snapshots are not compressed.&lt;/p&gt;

&lt;p&gt;The process involves three main areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Working Directory&lt;/em&gt;: Where you edit files.&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Staging Area&lt;/em&gt;: Files added here are prepared for commits.&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Local Database&lt;/em&gt;: Stores snapshots of committed changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Zeet captures the essence of Git while offering simplicity for educational and hobbyist purposes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features of Zeet
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🛠️ What Zeet Can Do
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Repository Initialization&lt;/strong&gt;: Create a Zeet repository with a &lt;code&gt;.zeet&lt;/code&gt; subdirectory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Staging Files&lt;/strong&gt;: Add files to the staging area before committing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Committing Changes&lt;/strong&gt;: Save staged files to the local database with descriptive messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branching&lt;/strong&gt;: Work on parallel branches and switch between them effortlessly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merging&lt;/strong&gt;: Merge branches intelligently using fast-forward or 3-way merges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conflict Detection and Resolution&lt;/strong&gt;: Detect conflicts during merges, mark them with symbols (&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt;, &lt;code&gt;=======&lt;/code&gt;, &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;), and resolve them manually.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File Ignoring&lt;/strong&gt;: Specify files to ignore using &lt;code&gt;.zeetignore&lt;/code&gt; or &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit History&lt;/strong&gt;: View detailed and colorized logs of commit histories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diffs&lt;/strong&gt;: Compare changes between commits, branches, or files.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🛑 What Zeet Cannot Do (Yet)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Show the repository status beyond staged, untracked, or deleted files.&lt;/li&gt;
&lt;li&gt;  Clone remote repositories.&lt;/li&gt;
&lt;li&gt;  Perform rebase merges.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to use Zeet
&lt;/h2&gt;

&lt;p&gt;Install Zeet globally via npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;`&lt;/span&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; zeet&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Node.js v20+&lt;/li&gt;
&lt;li&gt;  A basic understanding of CLI tools&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Core Commands
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;See usage&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zeet &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Initialize Repository&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zeet init
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stage Files&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zeet add &amp;lt;file1&amp;gt; &amp;lt;file2&amp;gt; ...
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;To stage all files:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zeet add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Commit changes&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zeet commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Your Commit message"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;View commit history&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zeet log
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Branch Management:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a branch:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zeet branch &amp;lt;branch-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switch branches:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zeet switch &amp;lt;branch-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Merge branches&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;zeet merge &amp;lt;branch-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Merge conflicts will be detected and marked for manual resolution.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;View diffs&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;zeet diff &amp;lt;commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Compares two commits:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;zeet diff &amp;lt;commit-hash1&amp;gt; &amp;lt;commit-hash2&amp;gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;In place of &lt;code&gt;&amp;lt;commit-hash&amp;gt;&lt;/code&gt;, you can alternatively specify branch or path to a file under repository.&lt;/p&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Final toughts
&lt;/h2&gt;

&lt;p&gt;Zeet is a hobby project that distills the essence of Git into a minimal yet functional version control system. While it’s not as robust as Git, it showcases the core principles of version control, making it a great tool for learning and experimenting.&lt;/p&gt;

&lt;p&gt;Want to contribute? Head over to the &lt;a href="https://github.com/hane-smitter/zeet" rel="noopener noreferrer"&gt;Zeet repository on GitHub&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
We could make Zeet even better.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>git</category>
      <category>discuss</category>
      <category>node</category>
    </item>
    <item>
      <title>Git things right🟢✔️ using rebase workflow in a software team</title>
      <dc:creator>Smitter</dc:creator>
      <pubDate>Mon, 21 Aug 2023 11:19:24 +0000</pubDate>
      <link>https://dev.to/smitterhane/git-things-right-using-rebase-workflow-in-a-software-team-jjp</link>
      <guid>https://dev.to/smitterhane/git-things-right-using-rebase-workflow-in-a-software-team-jjp</guid>
      <description>&lt;p&gt;Git has many powers and one of them is &lt;strong&gt;flexibility&lt;/strong&gt;. Different approaches(workflows) can be leveraged to efficiently build software collaboratively, and teams can pick their best fit. Common in a Git team, branching is a godsent technique used to build new features in isolation without impacting stability in main branch. Later when a feature is complete, it's branch is merged into main, and that branch becomes obsolete and perhaps deleted.&lt;/p&gt;

&lt;p&gt;It is odd how people treat &lt;code&gt;git rebase&lt;/code&gt; like a plague to avoid when working on public branches i.e, branches other team members have pulled down from remote into their devices/local repos. That is okay. They are people. Coming from this article you shouldn't be one of them but a &lt;code&gt;git user&lt;/code&gt; who doesn't have to sweat over using &lt;code&gt;git rebase&lt;/code&gt; again.&lt;br&gt;
We'll discuss why &lt;strong&gt;Git rebase workflow&lt;/strong&gt; in a Git team, is an exciting thing you are missing while still clutched to the &lt;strong&gt;Git merge workflow&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; To better relate with the rest of the article, you need to be at least familiar with creating branches in Git and merging them. &lt;small&gt;By the way, it is super easy&lt;/small&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To breakdown matters into chunks you can digest, let's assume of a company called "XYZ", that has a wonderful software product 😎️.&lt;br&gt;&lt;br&gt;
This company uses a &lt;strong&gt;Gitflow&lt;/strong&gt; workflow to build its software. Ideally, its branching strategy comprises of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;main&lt;/code&gt; - This is the name given to a main branch that holds production ready code. Or call it stable version.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;develop&lt;/code&gt; - This is also a main branch that contains newly integrated features (&lt;em&gt;that are not yet ready to be released to production&lt;/em&gt;). The unstable version.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;release&lt;/code&gt;- Branch that helps prepare a new stable release. Usually stemmed off the &lt;code&gt;develop&lt;/code&gt; branch, for testing, documentation generation, bugfixes and other related preparations. It must be merged back to both &lt;code&gt;develop&lt;/code&gt; and &lt;code&gt;main&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;hotfix&lt;/code&gt;- Branch that fixes bug discovered in production release(&lt;code&gt;main&lt;/code&gt; branch). It &lt;strong&gt;must&lt;/strong&gt; be fixed. And after being fixed, it is merged back to both &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;develop&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;feature&lt;/code&gt; - Branch that developers work on when building new features that come up. Collectively reffered to as &lt;em&gt;feature&lt;/em&gt;/&lt;em&gt;topic branch&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You could choose your own name conventions. Importantly, the branches should still hold their purpose and usecase.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;develop&lt;/code&gt; branches are considered &lt;strong&gt;main branches&lt;/strong&gt;, i.e they are long-lived branches, while the rest are supporting branches that aid parallel development, usually short-lived.&lt;/p&gt;

&lt;p&gt;For elaborating the Git rebase workflow, we will focus on activity done on &lt;code&gt;develop&lt;/code&gt; branch.&lt;/p&gt;
&lt;h2&gt;
  
  
  Scenario
&lt;/h2&gt;

&lt;p&gt;Let's narrow down the persona to you, a developer working in this "XYZ" company .&lt;br&gt;&lt;br&gt;
Several features have come up, that need to be built and integrated into the company's software product. And you have been assigned one of them. The rest is distributed to other developers.&lt;br&gt;&lt;br&gt;
So for example, you need to build a new feature in the software that allows a user to locate gas stations nearby.&lt;/p&gt;

&lt;p&gt;To go about this, you start off with &lt;code&gt;git checkout develop&lt;/code&gt;. Then perform a &lt;code&gt;git pull&lt;/code&gt; to integrate latest changes that may be in the remote but not in you local &lt;code&gt;develop&lt;/code&gt; branch. And you branch off from &lt;code&gt;develop&lt;/code&gt;. The new branch is &lt;code&gt;feature&lt;/code&gt; branch, where you work on your assigned task.&lt;/p&gt;

&lt;p&gt;After you are done, you are ready to merge your changes back into &lt;code&gt;develop&lt;/code&gt; branch.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Please note&lt;/strong&gt; that at this time, other developers who finished working on their assigned features earlier than you, have already integrated their work into &lt;code&gt;develop&lt;/code&gt; branch. So, &lt;code&gt;develop&lt;/code&gt; branch has evolved and after another &lt;code&gt;git pull&lt;/code&gt; from it, commit history in your local repository can be visualized into this:&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5tfoudyg1ysja5d3yxvo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5tfoudyg1ysja5d3yxvo.png" alt="Fork-shape commit history" width="300" height="226"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Merging policy
&lt;/h2&gt;

&lt;p&gt;This company has its own take and philosophies about their project's commit history.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;develop&lt;/code&gt; branch commit history should be &lt;strong&gt;linear&lt;/strong&gt;, replaying &lt;strong&gt;thoughtful&lt;/strong&gt; commits that happened in feature branch incorporated into it. &lt;strong&gt;No&lt;/strong&gt; squash merging of feature branch. To reason out: In real world features can be complex, so it is important to maintain feature commits to explain how we arrived at point B coming from point A.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;main&lt;/code&gt; branch should have one commit per each release. Practically, a &lt;em&gt;squash merge&lt;/em&gt;. Meaning it will have a diminished project history. A good commit message should tell the features incorporated at the time of that release.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;release&lt;/code&gt; and &lt;code&gt;hotfix&lt;/code&gt; - These branches add improvements to codebase in &lt;em&gt;main branches&lt;/em&gt;. After improvements are made, they are &lt;em&gt;squash merged&lt;/em&gt; into &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;develop&lt;/code&gt;. Good commit message is important too.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The problem with Git merge workflow
&lt;/h2&gt;

&lt;p&gt;Now that we know how this company desires commit history of its project to be organized, let's look at one way one could decide to integrate work.&lt;/p&gt;

&lt;p&gt;Suppose you use &lt;code&gt;git merge&lt;/code&gt; to incorporate work from one branch into another, you do the following steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout develop &lt;span class="c"&gt;# Check out public branch&lt;/span&gt;
git pull origin develop &lt;span class="c"&gt;# Pull in latest commits from the remote copy&lt;/span&gt;
git merge feature &lt;span class="c"&gt;# Incorporate work from feature branch&lt;/span&gt;
git push &lt;span class="c"&gt;# Share your changes to the remote&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That is the Git merge workflow. And it is legendary at being easy to pickup, that it builds a striking adoption by most Git users.&lt;br&gt;&lt;br&gt;
The branch's history tree looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqb598dpk0wshyfzyv3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqb598dpk0wshyfzyv3d.png" alt="Git merge non-linear hist shape" width="400" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Commit history tree can be observed on the left edge when you run &lt;code&gt;git log --graph --oneline&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A &lt;strong&gt;merge commit&lt;/strong&gt; is generated which combines two branch histories. The commit history in &lt;code&gt;develop&lt;/code&gt; becomes &lt;strong&gt;non-linear&lt;/strong&gt;. That is to say, the commit history is not &lt;em&gt;straight&lt;/em&gt; since it breaks from an evolving main line and later rejoins. Already, a &lt;em&gt;non-linear&lt;/em&gt; project history is not what the company wants on this branch.&lt;br&gt;&lt;br&gt;
Aside from this company's preferences, the following are the &lt;strong&gt;cons of using a Git merge workflow&lt;/strong&gt;:&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;  Git merge workflow does not enforce an individual developer to build, test and work out code differences while at the &lt;em&gt;feature branch level&lt;/em&gt; before merging to &lt;em&gt;main&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;  This workflow generates &lt;em&gt;merge commits&lt;/em&gt; that can really clutter the commit history. A disaster class history can happen especially if you team with committers that are relatively new to Git or are using GUI that hides the actual results from them.&lt;/li&gt;
&lt;li&gt;  If you need to review work for whatever reason, it is very difficult to do so with a cluttered history filled with noise jamming the radar.&lt;/li&gt;
&lt;li&gt;  Merge commits created, can result in duplication of old commits because someone merged in a branch that branched off at a far away older commit. This maybe an old branch or the developer did not branch off at the right spot.&lt;/li&gt;
&lt;li&gt;  A project's history can aid in debugging, e.g when finding a commit that introduced a bug. Git merge workflow can confuse things with merge commits, e.g when using &lt;code&gt;git bisect&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;An &lt;strong&gt;ideal&lt;/strong&gt; linear project history desired on the &lt;code&gt;develop&lt;/code&gt; branch looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fma4w1nof7ozzaba66j7q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fma4w1nof7ozzaba66j7q.png" alt="Linear hist shape" width="400" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All commits from &lt;code&gt;feature&lt;/code&gt; branch are placed on &lt;strong&gt;top&lt;/strong&gt; of &lt;code&gt;develop&lt;/code&gt; branch and &lt;strong&gt;in order&lt;/strong&gt; they occured. Also, there is no extraneous merge commit.&lt;/p&gt;
&lt;h2&gt;
  
  
  Git rebase workflow for a linear commit history
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git rebase&lt;/code&gt; can achieve the desired commit history like shown in the above image.&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;gotcha&lt;/em&gt; about &lt;code&gt;git rebase&lt;/code&gt; is that it does its work by &lt;strong&gt;rewriting history&lt;/strong&gt;, which can cause chaos when performed on a public branch other developers have based their work on; like in our case, the &lt;code&gt;develop&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;To avoid rewriting history, we need to ensure that when work from a separate branch is incorporated into &lt;code&gt;develop&lt;/code&gt;, it is &lt;strong&gt;fast-forwaded&lt;/strong&gt;. That is to mean commits made on the separate branch, are appended on &lt;strong&gt;top&lt;/strong&gt; of existing history of current branch. Thereby avoiding rewrite on existing history.&lt;/p&gt;

&lt;p&gt;To make git perform a &lt;em&gt;fast-forward&lt;/em&gt; when integrating work from separate branches, we have to prepare commit history between them, especially when they have both evolved.&lt;br&gt;&lt;br&gt;
For instance, when &lt;code&gt;feature&lt;/code&gt; branch was first created:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout develop
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feature &lt;span class="c"&gt;# Create feature branch and switch to it&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Commit history in &lt;code&gt;feature&lt;/code&gt; started off on a &lt;strong&gt;base commit&lt;/strong&gt;(&lt;code&gt;c2&lt;/code&gt;) which is the latest commit on &lt;code&gt;develop&lt;/code&gt; branch &lt;strong&gt;&lt;em&gt;at that time&lt;/em&gt;&lt;/strong&gt;. More work committed from the branch, evolved the history with new commits(&lt;code&gt;c3...c5&lt;/code&gt;) on top of the base commit.&lt;br&gt;&lt;br&gt;
Now at this time, enough work has been done on &lt;code&gt;feature&lt;/code&gt; branch and we are ready to integrate these changes back into &lt;code&gt;develop&lt;/code&gt;. However, the starting &lt;em&gt;base commit&lt;/em&gt; of the &lt;code&gt;feature&lt;/code&gt; branch is &lt;strong&gt;no longer&lt;/strong&gt; the &lt;em&gt;latest commit/tip&lt;/em&gt; of the &lt;code&gt;develop&lt;/code&gt; branch:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvmd99gpdkit9yyca9xgs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvmd99gpdkit9yyca9xgs.png" alt="Feature branch history shape before rebase" width="435" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In other words, &lt;code&gt;develop&lt;/code&gt; branch has evolved with newer commits by other team members since the last time &lt;code&gt;feature&lt;/code&gt; was created off from it.&lt;/p&gt;

&lt;p&gt;Therefore if we need a &lt;em&gt;fast-forward&lt;/em&gt; merge to be &lt;strong&gt;possible&lt;/strong&gt;, we have to update the base of &lt;code&gt;feature&lt;/code&gt; branch so it is anchored onto the latest commit(&lt;code&gt;c7&lt;/code&gt;) that is the tip of &lt;code&gt;develop&lt;/code&gt; branch. Then changes that were committed in &lt;code&gt;feature&lt;/code&gt; are &lt;em&gt;freshly committed&lt;/em&gt; onto the top of the updated base &lt;em&gt;in the order they occured&lt;/em&gt;(&lt;code&gt;c3'...c5'&lt;/code&gt;), hence the nomenclature and internal working of &lt;code&gt;git rebase&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foibs8iptoujtm9voedpl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foibs8iptoujtm9voedpl.png" alt="Feature branch history shape after rebase" width="435" height="295"&gt;&lt;/a&gt;&lt;/p&gt;







&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;c3'...c5'&lt;/code&gt; are new commits with same changes like in &lt;code&gt;c3...c5&lt;/code&gt;(before rebasing). Rebasing changes their commit IDs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After we rebase &lt;code&gt;feature&lt;/code&gt; branch, we head into &lt;code&gt;develop&lt;/code&gt; branch and traffic lights should be "green 🟢" for us to integrate new work in which Git will fast-forward. This is so because the &lt;strong&gt;base commit in &lt;code&gt;feature&lt;/code&gt; branch is reachable as most recent commit on current branch(&lt;code&gt;develop&lt;/code&gt;)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Typically, these are the steps in a &lt;code&gt;git rebase&lt;/code&gt; workflow in your local repository:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout develop &lt;span class="c"&gt;# Checkout public branch&lt;/span&gt;
git pull origin develop &lt;span class="c"&gt;# Get and incorporate latest changes&lt;/span&gt;
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feature &lt;span class="c"&gt;# Create feature branch and switch to it&lt;/span&gt;
    &lt;span class="c"&gt;# Work on the new feature, make commits, test... Until you are done!&lt;/span&gt;
git fetch origin &lt;span class="c"&gt;# Refresh local repo store of remote copies&lt;/span&gt;
git rebase origin/develop &lt;span class="c"&gt;# Rebase to update feature branch base with latest develop branch commits&lt;/span&gt;
git checkout develop &lt;span class="c"&gt;# Head back to public branch&lt;/span&gt;
git pull origin develop &lt;span class="c"&gt;# Integrate latest commits from remote copy&lt;/span&gt;
git rebase feature &lt;span class="c"&gt;# Bring in commits of feature branch onto the top&lt;/span&gt;
git push &lt;span class="c"&gt;# Share the changes to remote copy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To reiterate, the 2&lt;sup&gt;nd&lt;/sup&gt; last command: &lt;code&gt;git rebase feature&lt;/code&gt;, &lt;strong&gt;does not&lt;/strong&gt; rewrite history. Git checks and sees that history of the checked out branch(&lt;code&gt;develop&lt;/code&gt;), forms the base/ancestor of &lt;code&gt;feature&lt;/code&gt; branch. So to include work done in the separate branch, it just appends commits done in &lt;code&gt;feature&lt;/code&gt; branch onto the top of &lt;code&gt;develop&lt;/code&gt;'s history. In git parlance, this is a &lt;em&gt;fast-forward&lt;/em&gt;, where Git simplifies work and just moves the &lt;code&gt;develop&lt;/code&gt; branch to point to the same commit the &lt;code&gt;feature&lt;/code&gt; branch is pointing.&lt;br&gt;&lt;br&gt;
So &lt;code&gt;develop&lt;/code&gt; branch and &lt;code&gt;feature&lt;/code&gt; branch are pointing to the same commit.&lt;br&gt;&lt;br&gt;
The result is a linear history same for both branches. The project history is as illustrated:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhfnjzpfup5y4v1q4fdrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhfnjzpfup5y4v1q4fdrg.png" alt="Git rebase workflow linear history" width="400" height="220"&gt;&lt;/a&gt;&lt;/p&gt;





&lt;p&gt;Alternatively, at the 2&lt;sup&gt;nd&lt;/sup&gt; last command, instead of &lt;code&gt;git rebase feature&lt;/code&gt;, you could use &lt;code&gt;git merge feature&lt;/code&gt; and still the result is a &lt;em&gt;fast-forward&lt;/em&gt;; merge commit is not generated in a &lt;em&gt;fast-forward&lt;/em&gt;. Also, you could use &lt;code&gt;git merge feature --ff-only&lt;/code&gt; to merge two lines of work &lt;em&gt;only if fast-forward is possible&lt;/em&gt;. This can help mitigate risk of rewriting history on public branch; when a step on the workflow is missed or out of order. &lt;small&gt;But anyway, Git will warn if you try to push a rewritten history.&lt;/small&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Should you use a Git rebase workflow?
&lt;/h2&gt;

&lt;p&gt;The choice between &lt;em&gt;git merge&lt;/em&gt; and &lt;em&gt;git rebase&lt;/em&gt; workflows can seem so pointless 🤷‍♂️. Because, in a nutshell, they both introduce changes from one branch into another. At least, this is the case for a Git user solely concerned about the final work.&lt;/p&gt;

&lt;p&gt;Beyond the surface, the choice between the two comes down to maintainance of a project's commit history. Decision on a project's history can be based on two philosophies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Commit history is a &lt;strong&gt;record&lt;/strong&gt; of what actually transpired and should be preserved.&lt;/li&gt;
&lt;li&gt; Commit history is a &lt;strong&gt;publication&lt;/strong&gt; and it should be presented in high quality.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If a project gravitates to keeping a record of what actually transpired in its doing(regardless of organization), &lt;em&gt;Git merge workflow&lt;/em&gt; is better suited. On the other hand, if a project should maintain a chronological and accessible history to tell a coherent story of how a project evolved, &lt;em&gt;Git rebase workflow&lt;/em&gt; should be the choice.&lt;br&gt;
There are far more advantages to keeping a high quality history that is clean and linear, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  It helps understand the story of how a solution was implemented.&lt;/li&gt;
&lt;li&gt;  There is clear snapshots of development stages of a project that can be referenced or used as starting points in future.&lt;/li&gt;
&lt;li&gt;  Cherry-picks, rollbacks and other versioning intentions become easier when history is orderly.&lt;/li&gt;
&lt;li&gt;  It outlines the evolution of the project in an easy to follow manner.&lt;/li&gt;
&lt;li&gt;  It allows to make simple compares when regressions are detected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overally why a Git rebase workflow is better than Git merge workflow is: Git rebase workflow is an outright ambassador for a linear commit history. The way it does this is by avoiding a merge commit while replaying the commits of a feature branch onto the tip of main. Also, Git rebase workflow allows you to resolve conflicts from feature branch before merging to main.&lt;/p&gt;

&lt;p&gt;Git rebase workflow can be ideal in open-source contributions where you rebase a feature branch and create a &lt;em&gt;pull request&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Final words
&lt;/h2&gt;

&lt;p&gt;Thanks for reading. I hope I cleared your doubts. And now you can make informed decision about history of your project.&lt;br&gt;&lt;br&gt;
Follow me here on Dev so you can be first to know of new nuggets that drop.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__388149"&gt;
    &lt;a href="/smitterhane" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F388149%2Ff7658170-b831-469f-855a-997041a3fcbc.jpg" alt="smitterhane image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/smitterhane"&gt;Smitter&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/smitterhane"&gt;💻Software Engineer ・ 🐧Fervent linux user ・🦀Learning Rust

https://npmjs.com/package/react-loading-indicators&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;I have an &lt;a href="https://twitter.com/intent/user?screen_name=smitterhane" rel="noopener noreferrer"&gt;&lt;strong&gt;X&lt;/strong&gt;(formerly twitter)&lt;/a&gt; account. We can connect 🤝.&lt;br&gt;&lt;br&gt;
You also need to hear this🙂: I maintain an open source library. See it in &lt;a href="https://github.com/hane-smitter/react-loading-indicator" rel="noopener noreferrer"&gt;Github&lt;/a&gt;. I appreciate your star⭐ should you like the &lt;a href="https://react-loading-indicators.netlify.app" rel="noopener noreferrer"&gt;work(DEMO)&lt;/a&gt;. I use a rebase workflow with it. Finally, explore my creativity practiced on &lt;a href="https://lookupzach.netlify.app" rel="noopener noreferrer"&gt;my personal website&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>git</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>13 CSS Tricks that will give you an adrenaline rush🤯</title>
      <dc:creator>Smitter</dc:creator>
      <pubDate>Mon, 17 Jul 2023 09:13:07 +0000</pubDate>
      <link>https://dev.to/smitterhane/13-css-tricks-that-will-give-you-an-adrenaline-rush-5908</link>
      <guid>https://dev.to/smitterhane/13-css-tricks-that-will-give-you-an-adrenaline-rush-5908</guid>
      <description>&lt;p&gt;CSS is gaining powers with recent web evolution. And it is &lt;em&gt;very clever with tricks&lt;/em&gt; that were long existing or that have emerged. Perhaps tricks shared here will school you with CSS tricks from the depths you were yet to explore.&lt;br&gt;&lt;br&gt;
Let's dive in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9h0zu01b575pwsngkbz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9h0zu01b575pwsngkbz.gif" alt="child makes small dive in sand beach" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;h2&gt;
  
  
  Draw a triangle using border
&lt;/h2&gt;

&lt;p&gt;It can be an overkill to load images in cases where you need simple triangles e.g when adding an arrow pointer to a tooltip.&lt;/p&gt;

&lt;p&gt;Using only CSS, you can create a triangle using borders.&lt;br&gt;&lt;br&gt;
It is quite an old trick. Ideally, on an element with zero width and height, you set borders on it. All border colors are transparent &lt;strong&gt;except&lt;/strong&gt; the one that will form an arrow. To create an arrow pointing upwards, for example, the bottom border is colored while the left and right are transparent. No need to include the top border. The border width determines size of the arrow:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.upwards-arrow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;crimson&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This creates an arrow pointing upwards like shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fae7uxue6iaxv188eka88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fae7uxue6iaxv188eka88.png" alt="CSS border triangle" width="718" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see this &lt;a href="https://codepen.io/chriscoyier/pen/DELgOJ" rel="noopener noreferrer"&gt;codepen&lt;/a&gt; that visualizes the concept should it be tricky to create a mental picture.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Interchange background of an element
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;z-index&lt;/code&gt; property arranges how an element is stacked onto other positioned elements. At times you may set a &lt;code&gt;z-index&lt;/code&gt; property on a child element to be lower and it ends up hiding behind the background of its parent. To prevent this, you can cause a new &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context" rel="noopener noreferrer"&gt;stacking context&lt;/a&gt; on the parent element to prevent child elements from going behind it. One way way to create a stacking context is to use &lt;code&gt;isolation: isolate&lt;/code&gt; css style declaration.&lt;br&gt;&lt;br&gt;
We can use this stacking context technique to create hover effect that interchanges a button's background. For example:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.join-now&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#5dbea3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;isolation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* If ommitted, child pseudo element will be stacked behind */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.join-now&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#33b249&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt; &lt;span class="m"&gt;500ms&lt;/span&gt; &lt;span class="n"&gt;ease-out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.join-now&lt;/span&gt;&lt;span class="nd"&gt;:hover::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The code above interchanges the background of the &lt;code&gt;button&lt;/code&gt; when hovered. The background changes without interfering with the text on the foreground, as seen in the gif below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuibp055h7w18i480kxg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuibp055h7w18i480kxg.gif" alt="button background hover effect" width="262" height="216"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Center an element
&lt;/h2&gt;

&lt;p&gt;Probably, you already know how to center an element using &lt;code&gt;display: flex;&lt;/code&gt; and &lt;code&gt;display: grid;&lt;/code&gt;. Yet another &lt;strong&gt;unpopular&lt;/strong&gt; way to center an element on the x axis is to use &lt;code&gt;text-align&lt;/code&gt; CSS property. This property works out of the box when centering text. To also center other elements in the DOM, a child element needs to have a display of &lt;code&gt;inline&lt;/code&gt;. It could be &lt;code&gt;inline-block&lt;/code&gt; or any other inline...&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.parent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Pill 💊 shape button
&lt;/h2&gt;

&lt;p&gt;You can make buttons that are pill-shaped by setting the border-radius of a button to be a very high value. Certainly, the border-radius should be higher than the height of the button.&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* value higher than height of the button */&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fdd835&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkdvdfflm53w2cxize54t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkdvdfflm53w2cxize54t.jpg" alt="pill-shaped button" width="370" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Height of the button may increase with design changes. Hence you will often find it convenient to set &lt;code&gt;border-radius&lt;/code&gt; with a very high value so that your css keeps working regardless if the button grows.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Easily add beautiful loading indicator to your website
&lt;/h2&gt;

&lt;p&gt;As it is with developers, it is often a boring task to divert your focus to creating a beautiful loading indicator for your website. This focus is better utilized building other important parts of a project that deserve attention.&lt;/p&gt;

&lt;p&gt;As you are reading, odds are high you also find this an annoying hurdle. That is why i took the time to take away this hurdle away from you and prepare nicely done loading indicators packaged in a library so you can &lt;em&gt;"plug 'n play"&lt;/em&gt; from your dream project. It is a whole collection and you just need to pick the one that pulls the spark 💖 on you. Just see the simple usage of this &lt;a href="https://www.npmjs.com/package/react-loading-indicators" rel="noopener noreferrer"&gt;library&lt;/a&gt;, with the source available on &lt;a href="https://github.com/hane-smitter/react-loading-indicator" rel="noopener noreferrer"&gt;Github&lt;/a&gt;. Don't forget to leave a star ⭐.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Easy dark or light mode
&lt;/h2&gt;

&lt;p&gt;You only require a few lines of CSS to enable a dark/light mode on your website. You just need to let browsers know that your website can display correctly in system dark/light mode:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;light&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;color-scheme&lt;/code&gt; property can be set on any DOM element other than &lt;code&gt;html&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then set variables that control background color and text color through your website, making it even more bullet proof by checking for browser support:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--bg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--txt-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@supports&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CanvasText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="py"&gt;--bg-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="py"&gt;--txt-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CanvasText&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you don't set &lt;code&gt;background-color&lt;/code&gt; on an element, it will inherit the browser-defined system color for the dark/light theme matched. These system colors can be different between different browsers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Setting &lt;code&gt;background-color&lt;/code&gt; explicitly can be useful in combination with &lt;code&gt;prefers-color-scheme&lt;/code&gt; to give a different shade of color different from the default that the browser sets.&lt;/p&gt;

&lt;p&gt;Below is the dark/light mode in action. User's preference is simulated between dark and light mode.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctuq2pv1knqckdlzfklx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctuq2pv1knqckdlzfklx.gif" alt="Default dark and light mode demo" width="600" height="324"&gt;&lt;/a&gt;&lt;/p&gt;
Website reactive to system dark/light mode




&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Truncate overflowing text with an ellipsis(&lt;code&gt;...&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;This trick has been around for a while to &lt;em&gt;aesthetically trim&lt;/em&gt; long text. But you may still have missed it.&lt;br&gt;&lt;br&gt;
All you need is the following CSS:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="nc"&gt;.intro&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ellipsis&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Just implement these rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explicit width, so bounds for clipping will ever be reached.&lt;/li&gt;
&lt;li&gt;Browser wraps below long text that do not fit within an element's width. So you need to prevent that: &lt;code&gt;white-space: nowrap;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Content that overflows should be clipped: &lt;code&gt;overflow: hidden;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Pad a string with an ellipsis(&lt;code&gt;...&lt;/code&gt;) when text is about to be clipped: &lt;code&gt;text-overflow: ellipsis;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Result looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F617f221bdw7fetthqszk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F617f221bdw7fetthqszk.png" alt="clipped text" width="372" height="123"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Truncate long text to a number of lines
&lt;/h2&gt;

&lt;p&gt;This is slightly different from the trick above. This time, text is clipped limiting content to a number of lines.&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="nc"&gt;.intro&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;-webkit-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-webkit-box-orient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;vertical&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;-webkit-line-clamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Truncate when no. of lines exceed 3 */&lt;/span&gt;
    &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Output looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgt1grhjkpsz26kkgh238.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgt1grhjkpsz26kkgh238.png" alt="Text truncated on number of lines" width="417" height="166"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Stop overworking yourself writing &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;right&lt;/code&gt;, &lt;code&gt;bottom&lt;/code&gt;, &lt;code&gt;left&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;When working with positioned elements, you often write code like this:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.some-element&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This can be simplified using an &lt;code&gt;inset&lt;/code&gt; propety:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.some-element&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;inset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Or if you have different values for &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;right&lt;/code&gt;, &lt;code&gt;bottom&lt;/code&gt; and &lt;code&gt;left&lt;/code&gt;, you can set them respectively in the order like: &lt;code&gt;inset: -10px 0px -10px 0px&lt;/code&gt;. This shorthand works the same way as margin.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Serve optimized images
&lt;/h2&gt;

&lt;p&gt;Try throttling to a slow internet in the browser Dev tools and visit a website made up of HD images like &lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;unsplash&lt;/a&gt;. That's how to experience the pain of your website visitors trying to enjoy your high HD content from geographical areas with slow internet.&lt;br&gt;&lt;br&gt;
But you can provide a rescue especially with the &lt;code&gt;image-set&lt;/code&gt; CSS trick.&lt;/p&gt;

&lt;p&gt;You can give options to a browser to let it decide the most appropriate image that suits a user's device. For instance:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.banner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url("elephant.png")&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;-webkit-image-set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sx"&gt;url("elephant.webp")&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"image/webp"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sx"&gt;url("elephantHD.webp")&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"image/webp"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sx"&gt;url("elephant.png")&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"image/png"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sx"&gt;url("elephantHD.png")&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"image/png"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The code above will set the background image of an element.&lt;br&gt;&lt;br&gt;
If &lt;code&gt;-webkit-image-set&lt;/code&gt; is supported, then background image will be an optimized image, i.e an image of supported MIME type and that better suits the resolution power of the user's device.&lt;br&gt;&lt;br&gt;
For example: Since a higher quality image is directly proportional to a larger size, a user who has a high resolution device but in a poor network, will prompt the browser to decide on serving a supported image with lower resolution. Ii is logical not to make a user wait for the HD image to load.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; An image that the browser decides as the best fit, is what is downloaded&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h2&gt;
  
  
  Counters
&lt;/h2&gt;

&lt;p&gt;You don't have to get stuck on how the browser renders a numbered list. You can implement your own design utilizing &lt;code&gt;counters()&lt;/code&gt;. Here's how:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c"&gt;/* Define &amp;amp; Initialize Counter */&lt;/span&gt;
    &lt;span class="nl"&gt;counter-reset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;list-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;skyblue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.75rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c"&gt;/* Increment counter by 1 */&lt;/span&gt;
    &lt;span class="nl"&gt;counter-increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c"&gt;/* Show incremented count padded with `.` */&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s1"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Output looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F79v85kh0ddt9ednqcgox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F79v85kh0ddt9ednqcgox.png" alt="CSS counter" width="411" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This works for any other DOM element apart from &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt;.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Form validation visual cues
&lt;/h2&gt;

&lt;p&gt;With only CSS, you can display helping visual cues to users regarding the validity of input entered in the forms. We can use &lt;code&gt;:valid&lt;/code&gt; and &lt;code&gt;:invalid&lt;/code&gt; CSS pseudo classes on form elements to apply appropriate styles when their contents validate successfully or not.&lt;/p&gt;

&lt;p&gt;Consider the following HTML page structure:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Regex in pattern attribute means input can accept `firstName Lastname` (whitespace sepearated names) --&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- And invalidates any other symbols like `*` --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
    &lt;span class="na"&gt;pattern=&lt;/span&gt;&lt;span class="s"&gt;"([a-zA-Z0-9]\s?)+"&lt;/span&gt;
    &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Enter full name"&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; will be used to show validation results.&lt;/p&gt;

&lt;p&gt;And the CSS below styles an input regarding its validation result:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:placeholder-shown&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nd"&gt;:invalid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:placeholder-shown&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nd"&gt;:invalid&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"✖"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:placeholder-shown&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nd"&gt;:valid&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"✓"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;So we have achieved interactivity without consulting any javascript. A full codepen implementing this technique is shown below:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/hane-smitter/embed/wvQpvZL?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Select text with one click
&lt;/h2&gt;

&lt;p&gt;This trick is inclined towards improving copy and paste experience for website users. Using &lt;code&gt;user-select: all&lt;/code&gt;, you can enable easy text selection with one click. All text node below that element is selected.&lt;/p&gt;

&lt;p&gt;On the other hand, you can disable text selection with &lt;code&gt;user-select: none;&lt;/code&gt;. Alternative way to disable text selection is placing text inside &lt;code&gt;content: '';&lt;/code&gt; property of &lt;code&gt;::before&lt;/code&gt; or &lt;code&gt;::after&lt;/code&gt; CSS pseudo element.&lt;/p&gt;


&lt;/li&gt;

&lt;/ol&gt;




&lt;p&gt;Thanks for reading. See you in the next article. Follow me here on Dev to be notified.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__388149"&gt;
    &lt;a href="/smitterhane" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F388149%2Ff7658170-b831-469f-855a-997041a3fcbc.jpg" alt="smitterhane image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/smitterhane"&gt;Smitter&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/smitterhane"&gt;💻Software Engineer ・ 🐧Fervent linux user ・🦀Learning Rust

https://npmjs.com/package/react-loading-indicators&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Also connect with me on &lt;a href="https://twitter.com/intent/user?screen_name=smitterhane" rel="noopener noreferrer"&gt;twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>css</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Uncanny visual symbols of a git conflict explained</title>
      <dc:creator>Smitter</dc:creator>
      <pubDate>Tue, 20 Jun 2023 13:24:37 +0000</pubDate>
      <link>https://dev.to/smitterhane/uncanny-visual-symbols-of-a-git-conflict-explained-568p</link>
      <guid>https://dev.to/smitterhane/uncanny-visual-symbols-of-a-git-conflict-explained-568p</guid>
      <description>&lt;p&gt;Git is such a popular Version Control System. It needs no introduction.&lt;br&gt;&lt;br&gt;
Software development is a collaborative task where git helps track and versions the changes made. When working in a team setting, conflicts are frequent visitors. I am not refferring to people coming to blows, but Git encountering lines in files that have received edits from two branches during a merge operation.&lt;/p&gt;

&lt;p&gt;Therefore a &lt;em&gt;git conflict&lt;/em&gt; arises &lt;strong&gt;when two separate branches have made edits to the same line in a file&lt;/strong&gt;, or &lt;strong&gt;when a file has been deleted in one branch but edited in the other&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you inspect an affected file in a merge conflict, there are strange symbols that appear in the lines where the conflict has occured. Ideally when git encounters a conflict during a merge, it will edit the content of the affected files with visual indicators that mark edits received from both sides of the involved branches.&lt;/p&gt;

&lt;p&gt;These symbols are &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt;, &lt;code&gt;=======&lt;/code&gt; and &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;, like in the example illustration below of a merge conflict:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmwoxnsb13aylkwqlfiec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmwoxnsb13aylkwqlfiec.png" alt="Merge conflict symbols" width="622" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What these symbols mean
&lt;/h2&gt;

&lt;p&gt;Its simple.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;&lt;code&gt;=======&lt;/code&gt;&lt;/strong&gt; is a symbol that separates edits recived from both branches. The content above and enclosed between &lt;strong&gt;&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;code&gt;=======&lt;/code&gt;&lt;/strong&gt; is the receiving branch. More specifically the branch that is currently checked out and receiving work from another branch.&lt;br&gt;&lt;br&gt;
And the content below &lt;strong&gt;&lt;code&gt;=======&lt;/code&gt;&lt;/strong&gt;, enclosed between &lt;strong&gt;&lt;code&gt;=======&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;&lt;/strong&gt;, is the merging branch.&lt;/p&gt;

&lt;p&gt;It is helpful to search a project for these symbols during a merge to find where conflicts need to be resolved.&lt;/p&gt;

&lt;p&gt;To fix a conflict, you as a developer has to decide which either side of the &lt;strong&gt;&lt;code&gt;=======&lt;/code&gt;&lt;/strong&gt; symbol you want to stick with. Once decided, you can replace the symbols with the content you have chosen. Once you are certain you have fixed all the conflicts pointed out by Git, you can mark resolved by runnig &lt;code&gt;git add&lt;/code&gt; on the file(s) and finally &lt;code&gt;git commit&lt;/code&gt; to complete the merge operation.&lt;/p&gt;

&lt;p&gt;If somehow later this merge turns to be a mistake, you might want to equip yourself with git techniques to undo. I wrote an article that teaches exactly that: &lt;a href="https://dev.to/smitterhane/turn-around-your-git-mistakes-in-17-ways-2mn1"&gt;how to undo mistakes in Git&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;

</description>
      <category>git</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>github</category>
    </item>
    <item>
      <title>How to calculate CSS specificity of your style rules</title>
      <dc:creator>Smitter</dc:creator>
      <pubDate>Tue, 06 Jun 2023 13:16:15 +0000</pubDate>
      <link>https://dev.to/smitterhane/how-to-calculate-css-specificity-of-your-style-rules-moj</link>
      <guid>https://dev.to/smitterhane/how-to-calculate-css-specificity-of-your-style-rules-moj</guid>
      <description>&lt;p&gt;In this article, you will learn how to calculate CSS specificity of the styles you write by computing a compound number to measure specificity weight by CSS selector.&lt;/p&gt;

&lt;p&gt;First off,&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Specificity&lt;/strong&gt; is the algorithm browsers use to establish the CSS &lt;em&gt;declarations&lt;/em&gt; that will get applied to an element, when it is referenced by two or more &lt;em&gt;style rules&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
Specificity algorithm calculates &lt;strong&gt;weight&lt;/strong&gt; of CSS selector, and among competing selectors targetting one element, the selector with the greatest &lt;strong&gt;weight&lt;/strong&gt; will win to apply CSS declarations to that element.&lt;/p&gt;
&lt;h2&gt;
  
  
  Visual definition of CSS terms
&lt;/h2&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl3x75xjxvo0whrx5mio7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl3x75xjxvo0whrx5mio7.jpg" alt="CSS syntax definitions" width="506" height="424"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The 3-column value
&lt;/h2&gt;

&lt;p&gt;The specificity algorithm bases weight calculation around a &lt;strong&gt;three-column compound number&lt;/strong&gt;. Each column represents weight that correspond to the three types of CSS selectors, i.e &lt;strong&gt;ID&lt;/strong&gt;, &lt;strong&gt;CLASS&lt;/strong&gt; and &lt;strong&gt;TYPE&lt;/strong&gt;. This &lt;em&gt;three-column compound number&lt;/em&gt; starts off with zeroes looking like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9e3sbft0tein8avvue1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9e3sbft0tein8avvue1d.png" alt="Specificity 3-column value initial" width="300" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;ID column&lt;/strong&gt; - Includes &lt;strong&gt;only&lt;/strong&gt; &lt;em&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors" rel="noopener noreferrer"&gt;ID selectors&lt;/a&gt;&lt;/em&gt;, such as &lt;code&gt;#app&lt;/code&gt;. For each ID in a matching selector, add &lt;strong&gt;&lt;code&gt;[1, 0, 0]&lt;/code&gt;&lt;/strong&gt; to the weight value.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;CLASS column&lt;/strong&gt; - Includes &lt;em&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors" rel="noopener noreferrer"&gt;class selectors&lt;/a&gt;&lt;/em&gt;, such as &lt;code&gt;.myInput&lt;/code&gt;, &lt;em&gt;attribute selectors&lt;/em&gt; e.g &lt;code&gt;[type="password"]&lt;/code&gt;, and &lt;em&gt;pseudo-classes&lt;/em&gt; such as &lt;code&gt;:hover&lt;/code&gt;, &lt;code&gt;:first-of-type&lt;/code&gt;, e.t.c. For each class, attribute selector, or pseudo-class in a matching selector, add &lt;strong&gt;&lt;code&gt;[0, 1, 0]&lt;/code&gt;&lt;/strong&gt; to the weight value.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;TYPE column&lt;/strong&gt; - Includes &lt;em&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors" rel="noopener noreferrer"&gt;type selectors&lt;/a&gt;&lt;/em&gt;, such as &lt;code&gt;p&lt;/code&gt;, &lt;code&gt;h2&lt;/code&gt;, and &lt;code&gt;a&lt;/code&gt;, and &lt;em&gt;pseudo-elements&lt;/em&gt; like &lt;code&gt;::before&lt;/code&gt;, &lt;code&gt;::placeholder&lt;/code&gt;, and all other selectors with double-colon(&lt;code&gt;::&lt;/code&gt;) notation. For each type or pseudo-element in a matching selector, add &lt;strong&gt;&lt;code&gt;[0, 0, 1]&lt;/code&gt;&lt;/strong&gt; to the weight value.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Specificity comparison
&lt;/h2&gt;

&lt;p&gt;Let's look at the following rule, which is composed of 7 selectors to target a &lt;code&gt;span&lt;/code&gt; element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#app&lt;/span&gt; &lt;span class="nf"&gt;#navigation&lt;/span&gt; &lt;span class="nf"&gt;#list&lt;/span&gt; &lt;span class="nc"&gt;.sub-list&lt;/span&gt; &lt;span class="nc"&gt;.item&lt;/span&gt; &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* declarations here */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are &lt;strong&gt;3 ID selectors&lt;/strong&gt;(&lt;code&gt;#app&lt;/code&gt;, &lt;code&gt;#navigation&lt;/code&gt;, &lt;code&gt;#list&lt;/code&gt;). So the &lt;em&gt;three-column value&lt;/em&gt; becomes &lt;strong&gt;&lt;code&gt;[3, 0, 0]&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Then &lt;strong&gt;2 class selectors&lt;/strong&gt;(&lt;code&gt;.sub-list&lt;/code&gt;, &lt;code&gt;.item&lt;/code&gt;). The &lt;em&gt;three-column value&lt;/em&gt; compounds to &lt;strong&gt;&lt;code&gt;[3, 2, 0]&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Then &lt;strong&gt;2 type selectors&lt;/strong&gt;(&lt;code&gt;p&lt;/code&gt;, &lt;code&gt;span&lt;/code&gt;). The &lt;em&gt;three-column value&lt;/em&gt; compounds to &lt;strong&gt;&lt;code&gt;[3, 2, 2]&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Now provided the number in each column is &lt;strong&gt;&lt;code&gt;9&lt;/code&gt; or less&lt;/strong&gt;, we can concatenate the numbers in each column to get a base10 number as the resultant specificity weight. So in this case we have a calculated specificity weight as &lt;code&gt;322&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; This is not how specificity is calculated by CSS processor inside browsers, but only a blue print. Normally in browsers, the specificity is not calculated in base 10 number system, but in a larger number, often unspecified.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Suppose we have another rule styling the same &lt;code&gt;span&lt;/code&gt; element looking like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#navigation&lt;/span&gt; &lt;span class="nf"&gt;#list&lt;/span&gt; &lt;span class="nc"&gt;.sub-list&lt;/span&gt; &lt;span class="nc"&gt;.item&lt;/span&gt; &lt;span class="nc"&gt;.wrapper&lt;/span&gt; &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* declarations here */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Likewise in the style rule above, 7 selectors are used to target the &lt;code&gt;span&lt;/code&gt; element. Difference being that we have &lt;strong&gt;2 ID selectors&lt;/strong&gt; and &lt;strong&gt;3 class selectors&lt;/strong&gt;, which results in the &lt;em&gt;three-column value&lt;/em&gt; &lt;strong&gt;&lt;code&gt;[2, 3, 2]&lt;/code&gt;&lt;/strong&gt;. Hence a specificity weight &lt;code&gt;232&lt;/code&gt;. Because &lt;code&gt;322&lt;/code&gt; is greater than &lt;code&gt;232&lt;/code&gt;, the former has precedence over the latter. Therefore, the former style rule will be processed to style the &lt;code&gt;span&lt;/code&gt; element.&lt;/p&gt;

&lt;h2&gt;
  
  
  Selectors that add no weight to specificity calculation
&lt;/h2&gt;

&lt;p&gt;The universal selector &lt;code&gt;*&lt;/code&gt; and the pseudo-class &lt;code&gt;:where()&lt;/code&gt; with its parameters &lt;strong&gt;do not add onto specificity weight&lt;/strong&gt; so their weight is &lt;strong&gt;&lt;code&gt;[0, 0, 0]&lt;/code&gt;&lt;/strong&gt;; &lt;em&gt;but they do match elements&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Combinators, such as &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator," rel="noopener noreferrer"&gt;&lt;code&gt;+&lt;/code&gt;&lt;/a&gt;,&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Child_combinator," rel="noopener noreferrer"&gt;&lt;code&gt;&amp;gt;&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_combinator," rel="noopener noreferrer"&gt;&lt;code&gt;~&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_combinator," rel="noopener noreferrer"&gt;&lt;code&gt;" "&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Column_combinator," rel="noopener noreferrer"&gt;&lt;code&gt;||&lt;/code&gt;&lt;/a&gt;, may make a selector more specific in what is selected but they &lt;strong&gt;don't&lt;/strong&gt; add any weight to specificity.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;:not()&lt;/code&gt;, &lt;code&gt;:has()&lt;/code&gt; and &lt;code&gt;:is()&lt;/code&gt; pseudo classes add no weight by themselves. However their parameters &lt;strong&gt;do impact weight in specificity calculation&lt;/strong&gt;. Therefore, the weight calculated from the selectors, is inclusive of the weight from the parameters of these pseudo-classes.&lt;br&gt;&lt;br&gt;
Incase of a parameter list, weight by the parameters with the highest specificity is used. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* 
&amp;lt;span id="intro" class="lead"&amp;gt;...&amp;lt;/span&amp;gt; 
*/&lt;/span&gt;

&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.lead&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;#intro&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* calculated specificity - [1, 0, 1] */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above snippet, inside the &lt;code&gt;:is()&lt;/code&gt; parameter list, &lt;code&gt;#intro&lt;/code&gt; has higher weight (&lt;code&gt;[1, 0, 0]&lt;/code&gt;) than &lt;code&gt;.lead&lt;/code&gt; (&lt;code&gt;[0, 1, 0]&lt;/code&gt;) . Hence weight by &lt;code&gt;#intro&lt;/code&gt; is used to sum up with weight by the &lt;code&gt;span&lt;/code&gt; selector resulting to &lt;code&gt;[1, 0, 1]&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Consider the following &lt;span id="sample-html"&gt;HTML&lt;/span&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        ...
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;main&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"myElement"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"myInput"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the below CSS, three rules are targeting &lt;code&gt;&amp;lt;input /&amp;gt;&lt;/code&gt; element to set a color. For a given input, &lt;code&gt;color&lt;/code&gt; value is applied should its selectors specificity weight have precedence over the other matching selectors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* FIRST RULE */&lt;/span&gt;
&lt;span class="nf"&gt;#myElement&lt;/span&gt; &lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="nc"&gt;.myInput&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* [1, 1, 1] */&lt;/span&gt;

&lt;span class="c"&gt;/* SECOND RULE */&lt;/span&gt;
&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:required&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* [0, 2, 1] */&lt;/span&gt;

&lt;span class="c"&gt;/* THIRD RULE */&lt;/span&gt;
&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* [0, 0, 4] */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the above rules have selectors matching the same and only &lt;code&gt;&amp;lt;input /&amp;gt;&lt;/code&gt; element on our HTML. The input will have a color &lt;code&gt;red&lt;/code&gt; because the &lt;em&gt;first rule has the highest specificity weight&lt;/em&gt;, i.e &lt;code&gt;111&lt;/code&gt; is the greatest number from the weights of &lt;code&gt;111&lt;/code&gt;, &lt;code&gt;021&lt;/code&gt; and &lt;code&gt;004&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The last rule has &lt;strong&gt;4 type selctors&lt;/strong&gt;(&lt;code&gt;html&lt;/code&gt;, &lt;code&gt;body&lt;/code&gt;, &lt;code&gt;main&lt;/code&gt;, &lt;code&gt;input&lt;/code&gt;). Increasing even more type selctors will still result in &lt;code&gt;&amp;lt;input /&amp;gt;&lt;/code&gt; being color &lt;code&gt;red&lt;/code&gt; since specificity weight by type selector is always lower than ID selector.&lt;/p&gt;

&lt;h2&gt;
  
  
  Excercise
&lt;/h2&gt;

&lt;p&gt;Consider the same html to deduce the result of the below CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.myInput&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="nc"&gt;.myInput&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;:where&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;#myElement&lt;/span&gt; &lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;What will happen to border on the &lt;code&gt;&amp;lt;input /&amp;gt;&lt;/code&gt; element?&lt;/em&gt;&lt;br&gt;&lt;br&gt;
Share your answer in the comments👍️.&lt;/p&gt;
&lt;h2&gt;
  
  
  A Column number that is greater than &lt;code&gt;9&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I had mentioned earlier that to get the specificity weight you concatenate the column values to get a number like &lt;code&gt;322&lt;/code&gt;. This is because for less than 10 selectors of a type(&lt;em&gt;either ID, Class or Type&lt;/em&gt;), we can calculate the specificity in the base 10. Hence concatenating, we can get a number in the base10 number system.&lt;/p&gt;

&lt;p&gt;This is not the case when we have 10 and above selectors of a type. High number of selectors can occur when using nesting feature of css preprocessors like &lt;a href="https://sass-lang.com" rel="noopener noreferrer"&gt;sass&lt;/a&gt; to generate css. You can end up with &lt;em&gt;three-column value&lt;/em&gt; like &lt;code&gt;[11, 7, 19]&lt;/code&gt;. You can't concatenate the numbers to obtain a &lt;strong&gt;decimal specificity weight&lt;/strong&gt; in this case.&lt;/p&gt;

&lt;p&gt;But instead you can convert the column numbers to a higher base.&lt;br&gt;&lt;br&gt;
For example, lets say we have a three-column value of &lt;code&gt;[11, 7, 19]&lt;/code&gt;. To calculate the weight, we can pick a base number that is &lt;strong&gt;larger than the largest column number&lt;/strong&gt; in the &lt;em&gt;three-column value&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
Let's pick a base number &lt;code&gt;20&lt;/code&gt; which is bigger than &lt;code&gt;19&lt;/code&gt;(largest number in &lt;code&gt;[11, 7, 19]&lt;/code&gt;). Then multiply out the three columns starting rightmost working to the left. And add the results, like shown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(20) * 19       =     380
(20*20) * 7     =   2 800
(20*20*20) * 11 =  88 000
-------------------------
Total in decimal = 91 180

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Doing this will also require you to use that base number to calculate specificity weight for the other competing selectors. Thankfully, CSS processor handles all this for you. so you just have to understand "why a certain style has been applied and not the other".&lt;/p&gt;

&lt;h2&gt;
  
  
  Equivalent weights
&lt;/h2&gt;

&lt;p&gt;Where 2 or more style rules have exactly the same specificity weight, the most recent rule will take precedence. However you can force a rule to a higher precedence over other equivalent rules using &lt;code&gt;!important&lt;/code&gt; keyword like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#00ff00&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you do this, all previous style rules with equivalent weight are overridden(including ones using &lt;code&gt;!important&lt;/code&gt;) and any equivalent rules that are processed will be ignored.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#00ff00&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* [0, 0, 1] */&lt;/span&gt;
&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ff0000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* [0, 0, 1] */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both rules have the same weight but the first rule will take precedence because of use of &lt;code&gt;!important&lt;/code&gt; keyword. Otherwise, the second rule would have taken precendence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;CSS has a simple syntax with alot happening behind scenes with the CSS processor. We have talked about specificity in this article, but specificity only comes to play after browser has determined &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade" rel="noopener noreferrer"&gt;cascade origin and importance&lt;/a&gt;. You can explore more which is beyond scope of this article.&lt;/p&gt;

&lt;p&gt;In a nutshell, knowing specificity of your styles helps you construct rules and understand what precedence they will have.&lt;br&gt;&lt;br&gt;
We have not talked about &lt;em&gt;inline styles&lt;/em&gt;, which are the &lt;strong&gt;most specific&lt;/strong&gt;, meaning that when an inline style is applied, it has the highest specificty overriding any style in the style sheet. The only way to override an inline style from a style sheet is to use &lt;code&gt;!important&lt;/code&gt; keyword.&lt;/p&gt;




&lt;p&gt;&lt;b&gt;Meet me aside on&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://twitter.com/intent/user?screen_name=smitterhane" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.linkedin.com/in/zacky-aduoli" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/hane-smitter" rel="noopener noreferrer"&gt;Github&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I periodically share useful content you may not want to miss.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>Build a Robust JWT Auth System in Node.js: Access and Refresh Token Strategy</title>
      <dc:creator>Smitter</dc:creator>
      <pubDate>Tue, 30 May 2023 12:39:05 +0000</pubDate>
      <link>https://dev.to/smitterhane/a-meticulous-jwt-api-authentication-guide-youve-been-looking-for-47dg</link>
      <guid>https://dev.to/smitterhane/a-meticulous-jwt-api-authentication-guide-youve-been-looking-for-47dg</guid>
      <description>&lt;p&gt;&lt;small&gt;&lt;b&gt;part 5&lt;/b&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Summary:&lt;/strong&gt; This article walks you through how to implement JSON Web Token(JWT) Authentication to create solid user login feature for web appllications. Tricky concepts on &lt;strong&gt;access token&lt;/strong&gt; and &lt;strong&gt;refresh token&lt;/strong&gt; are demystified on how they add up to securing endpoints.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note 🔔&lt;/strong&gt;&lt;/em&gt;:&lt;br&gt;&lt;br&gt;
&lt;em&gt;You can jump ahead to the final work, the complete API and front-end can be found on &lt;a href="https://github.com/hane-smitter/MERN_login_system" rel="noopener noreferrer"&gt;Github&lt;/a&gt;✩.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Common Misconception
&lt;/h2&gt;

&lt;p&gt;The most common advice is &lt;strong&gt;do not waste time implementing login&lt;/strong&gt;. Now as years go by and you climb the career ladder, it is important to &lt;em&gt;understand how the whole system works&lt;/em&gt; to elevate yourself as an architect and make more educated design decisions. Authentication is one of the areas you need to understand how it consolidates into a system. More reasons why you should know authentication is listed in &lt;a href="https://dev.to/smitterhane/3-tier-authentication-understand-and-conceptualize-the-process-2g3m#why-build-auth"&gt;this blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When thinking about authentication, the common mental picture people have is a login HTML page submitting data to a backend API that cross checks submitted data with what is in the DB. While that is true for the bare bones of an authentication system, there is finer details that need to be done right which we would discuss in the rest of the blog.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Table of Contents&lt;/b&gt;&lt;br&gt;
  &lt;/p&gt;
&lt;ol&gt;

    &lt;li&gt;

Getting started
        &lt;ul&gt;

            &lt;li&gt;Dependencies used&lt;/li&gt;

            &lt;li&gt;What we will do&lt;/li&gt;

            &lt;li&gt;Directory structure&lt;/li&gt;

        &lt;/ul&gt;

    &lt;/li&gt;

    &lt;li&gt;

What we will do
      &lt;ul&gt;

        &lt;li&gt;Declare environment variables&lt;/li&gt;

        &lt;li&gt;Create &lt;code&gt;User&lt;/code&gt; database model&lt;/li&gt;

        &lt;li&gt;Add email service&lt;/li&gt;

        &lt;li&gt;Create validators&lt;/li&gt;

        &lt;li&gt;Create authentication middleware&lt;/li&gt;

        &lt;li&gt;Create controller functions&lt;/li&gt;

        &lt;li&gt; Create application routes &lt;/li&gt;

        &lt;li&gt;Register routes&lt;/li&gt;

      &lt;/ul&gt;

    &lt;/li&gt;

    &lt;li&gt;Conclusion&lt;/li&gt;

  &lt;/ol&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;This is a coding tutorial. And to save length of the article better spent on the &lt;em&gt;"fun stuff"&lt;/em&gt;, there is a starting repo from &lt;a href="https://github.com/hane-smitter/MERN_login_system_starter" rel="noopener noreferrer"&gt;Github&lt;/a&gt; to base your work on. Change into &lt;strong&gt;&lt;code&gt;server&lt;/code&gt; directory&lt;/strong&gt; which is what we need in this blog.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article assumes you already have &lt;a href="https://nodejs.org/en/download/" rel="noopener noreferrer"&gt;NodeJS&lt;/a&gt; installed in your computer.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Dependencies
&lt;/h3&gt;

&lt;p&gt;The following third-party dependencies are used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/express" rel="noopener noreferrer"&gt;Express&lt;/a&gt; - A web framework hosted on NodeJS runtime, to handling requests coming to our server.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/express-validator" rel="noopener noreferrer"&gt;Express Validator&lt;/a&gt; - To run server-side validation.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/bcryptjs" rel="noopener noreferrer"&gt;Bcryptjs&lt;/a&gt; - To crumble plain text into irreversible hashes.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/cookie-parser" rel="noopener noreferrer"&gt;Cookie Parser&lt;/a&gt; - To parse cookies in incoming HTTP request.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/cors" rel="noopener noreferrer"&gt;Cors&lt;/a&gt; - To configure our backend to understand CORS protocol.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/dotenv" rel="noopener noreferrer"&gt;Dotenv&lt;/a&gt; - To load variables declared in &lt;code&gt;.env&lt;/code&gt; file into the project's environment.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/jsonwebtoken" rel="noopener noreferrer"&gt;Jsonwebtoken&lt;/a&gt; - To facilitate token-based authentication, &lt;em&gt;i.e access and refresh token&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/mongoose" rel="noopener noreferrer"&gt;Mongoose&lt;/a&gt; - An object modelling tool for MongoDB to enforce a specific mongoDB schema.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/nodemailer" rel="noopener noreferrer"&gt;Nodemailer&lt;/a&gt; - To send emails from NodeJs application.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/nodemon" rel="noopener noreferrer"&gt;Nodemon&lt;/a&gt; - To restart server app whenever file changes occur.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These dependencies are already listed in &lt;code&gt;package.json&lt;/code&gt; of the starter repo. To include them in your project, ensure you are in &lt;code&gt;server&lt;/code&gt; directory root and run &lt;code&gt;npm install&lt;/code&gt; from the terminal.&lt;/p&gt;

&lt;p&gt;Starter repository has some steps covered:&lt;/p&gt;

&lt;ol&gt;
    &lt;li id="db-integration"&gt;
        &lt;span&gt;
            Database integration
            (in &lt;a href="https://dev.to/smitterhane/database-integration-in-nodeexpress-a-maintainable-approach-dfa"&gt;part
                    2&lt;/a&gt;)
            
        &lt;/span&gt;
    &lt;/li&gt;
    &lt;li id="cors-integration"&gt;
        &lt;span&gt;
            Cross Origin Resource Sharing
            (in &lt;a href="https://dev.to/smitterhane/keep-cors-error-under-control-2099"&gt;part
                    3&lt;/a&gt;)
            
        &lt;/span&gt;
    &lt;/li&gt;
    &lt;li id="error-handling-integration"&gt;
        &lt;span&gt;
            Express.js error handling
            (in &lt;a href="https://dev.to/smitterhane/deftly-handle-exceptions-in-nodeexpress-application-208m"&gt;part
                    4&lt;/a&gt;)
            
        &lt;/span&gt;
    &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What we will do
&lt;/h3&gt;

&lt;p&gt;An overview outline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Declare environment variables&lt;/strong&gt; in &lt;code&gt;.env&lt;/code&gt; file that will be loaded into application environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create &lt;code&gt;User&lt;/code&gt; database model&lt;/strong&gt; to represent a user in our application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add email service&lt;/strong&gt; to send emails from our application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create validators&lt;/strong&gt; to validate data coming from client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create authentication middleware&lt;/strong&gt; to check for authentication on protected routes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create controller functions&lt;/strong&gt; to handle HTTP request and process a response for a matched route.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create routes&lt;/strong&gt;. So a specific functionality is provided at each route.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Register routes&lt;/strong&gt;, So internal routing mechanism can match HTTP request to a route.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Directory structure
&lt;/h3&gt;

&lt;p&gt;Final directory structure we will have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;📂server/
    ├── 📄.env
    └── 📂src/
        ├── 📄index.js
&lt;span class="gi"&gt;+       ├── 📂models/ 📄User.js
+       ├── 📂services/
+       │   └── 📂email/
+       │       ├── 📄email.js
+       │       └── 📄sendEmail.js
+       ├── 📂validators/
+       │   ├── 📄index.js
+       │   ├── 📄auth-validators.js
+       │   └── 📄user-validators.js
+       ├── 📂middlewares/ 📄authCheck.js
+       ├── 📂controllers/
+       │   └── 📂user/
+       │       ├── 📄index.js
+       │       ├── 📄auth.controller.js
+       │       └── 📄user.controller.js
+       ├── 📂routes/
+       │   ├── 📄index.js
+       │   └── 📄user.routes.js
&lt;/span&gt;        ├── 📂config/
        │   └── ...
        └── 📂dbConn/
             └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's dive in&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6j6fgwd2xydueb8ujuf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6j6fgwd2xydueb8ujuf.gif" alt="Child jumps into shallow pool" width="480" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;h2&gt;
  
  
  Declare environment variables
&lt;/h2&gt;

&lt;p&gt;Environment variables are key-value pairs that the operating system provides to applications at runtime. They store configuration data, such as database credentials or API keys, allowing applications to adapt to different environments (e.g., development, testing, production) without altering the code. These variables are kept in the system's memory (RAM) and away from application code so running applications can access them securely and efficiently.&lt;/p&gt;

&lt;p&gt;We'll make use of environment variables to store configuration variables that are sensitive or personal or both.&lt;/p&gt;

&lt;p&gt;Let's &lt;em&gt;declare environment variables&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
Create &lt;code&gt;.env&lt;/code&gt; file at &lt;code&gt;server&lt;/code&gt; directory root, i.e &lt;code&gt;server/&lt;/code&gt;(refer above). Declare the variables as follows:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AUTH_REFRESH_TOKEN_SECRET=2Kp6BjSKl3boT6+Zf3D0tw
AUTH_REFRESH_TOKEN_EXPIRY=1d
AUTH_ACCESS_TOKEN_SECRET=bkZaWfqssqzE0fg1TMCHqQ
AUTH_ACCESS_TOKEN_EXPIRY=120s
RESET_PASSWORD_TOKEN_EXPIRY_MINS=15
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;For the &lt;em&gt;"xxx_TOKEN_SECRET"s&lt;/em&gt;, you can input any value. Random characters is ideal. NodeJs can help generate random characters on the fly; In your terminal run: &lt;code&gt;node -e "console.log(crypto.randomBytes(32).toString('base64'))"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Realize how we set expiration time of our authentication tokens &lt;em&gt;i.e &lt;strong&gt;Refresh Token&lt;/strong&gt; expiration time(&lt;code&gt;AUTH_REFRESH_TOKEN_EXPIRY&lt;/code&gt;) is longer than &lt;strong&gt;Access Token&lt;/strong&gt;'s (&lt;code&gt;AUTH_ACCESS_TOKEN_EXPIRY&lt;/code&gt;)&lt;/em&gt;. Also, the &lt;strong&gt;Access Token&lt;/strong&gt; expiration time is reasonably short.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AUTH_REFRESH_TOKEN_SECRET&lt;/code&gt; - Holds value of the &lt;strong&gt;secret to sign&lt;/strong&gt; JWT &lt;em&gt;Refresh Token&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
&lt;code&gt;AUTH_REFRESH_TOKEN_EXPIRY&lt;/code&gt; - Holds value of the &lt;strong&gt;expiration time&lt;/strong&gt; of the JWT &lt;em&gt;Refresh Token&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
&lt;code&gt;AUTH_ACCESS_TOKEN_SECRET&lt;/code&gt; - Holds value of the &lt;strong&gt;secret to sign&lt;/strong&gt; JWT &lt;em&gt;Access Token&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
&lt;code&gt;AUTH_ACCESS_TOKEN_EXPIRY&lt;/code&gt; - Holds value of the &lt;strong&gt;expiration time&lt;/strong&gt; of the JWT &lt;em&gt;Access Token&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
&lt;code&gt;RESET_PASSWORD_TOKEN_EXPIRY_MINS&lt;/code&gt; - Expiry time of the password reset link.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;.env&lt;/code&gt; file &lt;strong&gt;declares&lt;/strong&gt; environment variables in plain text(it does not load them into OS environment). We will use &lt;code&gt;dotenv&lt;/code&gt; library to read variables in &lt;code&gt;.env&lt;/code&gt; file and actually load them into our application's environment(OS). Also &lt;strong&gt;be sure to add &lt;code&gt;.env&lt;/code&gt; file to your &lt;code&gt;.gitignore&lt;/code&gt;&lt;/strong&gt; to avoid sharing your &lt;code&gt;.env&lt;/code&gt; variables.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h2&gt;
  
  
  Create &lt;code&gt;User&lt;/code&gt; database model
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;database model&lt;/strong&gt;, is an interface for interacting with the database to query for operations like &lt;em&gt;reading, creating, updating&lt;/em&gt; and &lt;em&gt;deleting&lt;/em&gt; records.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;User&lt;/code&gt; model will represent a user of our application. This is the only model we will need for this tutorial. We'll use Mongoose to create this model.&lt;/p&gt;

&lt;p&gt;Create a file &lt;strong&gt;&lt;code&gt;User.js&lt;/code&gt;&lt;/strong&gt; at the path: &lt;code&gt;server/src/models/&lt;/code&gt;(refer). Paste the following code in this file:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bcryptjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 👇 Created in part 4&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CustomError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../config/errors/CustomError&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Pull in Environment variables&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ACCESS_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTH_ACCESS_TOKEN_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;expiry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTH_ACCESS_TOKEN_EXPIRY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTH_REFRESH_TOKEN_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;expiry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTH_REFRESH_TOKEN_EXPIRY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESET_PASSWORD_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;expiry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RESET_PASSWORD_TOKEN_EXPIRY_MINS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="cm"&gt;/*
1. CREATE USER SCHEMA
*/&lt;/span&gt;

&lt;span class="cm"&gt;/*
2. SET SCHEMA OPTION
*/&lt;/span&gt;

&lt;span class="cm"&gt;/*
3. ATTACH MIDDLEWARE
*/&lt;/span&gt;

&lt;span class="cm"&gt;/*
4. ATTACH CUSTOM STATIC METHODS
*/&lt;/span&gt;

&lt;span class="cm"&gt;/*
5. ATTACH CUSTOM INSTANCE METHODS
*/&lt;/span&gt;

&lt;span class="cm"&gt;/*
6. COMPILE MODEL FROM SCHEMA
*/&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;UserModel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The snippet above imports dependencies we will use. We have pulled in environment variables, available in &lt;code&gt;process.env&lt;/code&gt; and assigned them to constants for ease of access. We have &lt;strong&gt;6 parts&lt;/strong&gt;(commented) in the code snippet above.&lt;/p&gt;

&lt;p&gt;Under the &lt;b&gt;1&lt;sup&gt;st&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;1. CREATE USER SCHEMA&lt;/code&gt;), add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First name is required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Last name is required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email is required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;resetpasswordtoken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;resetpasswordtokenexpiry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;We have defined the schema for a user in our application. In other words, the attributes a user entity will have. Hence users stored in the database will be expected to each have these attributes. Some are optional while others are required.&lt;br&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt; that we have defined &lt;code&gt;tokens&lt;/code&gt; in the database schema where we will store &lt;strong&gt;refresh tokens&lt;/strong&gt; generated for a user&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;b&gt;2&lt;sup&gt;nd&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;2. SET SCHEMA OPTION&lt;/code&gt;), add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;toJSON&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;virtuals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// return fields we need&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This ensures that every time a document is retrieved from the &lt;code&gt;User&lt;/code&gt; model, only the relevant data intended for the API response is returned.&lt;/p&gt;

&lt;p&gt;In the &lt;b&gt;3&lt;sup&gt;rd&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;3. ATTACH MIDDLEWARE&lt;/code&gt;), add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;save&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isModified&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;genSalt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This is a mongoose middleware that runs before a document is saved to the database. And it ensures that &lt;em&gt;password&lt;/em&gt; attribute of a &lt;em&gt;user&lt;/em&gt; is hashed &lt;em&gt;if it was modified&lt;/em&gt;. Therefore, when a user is newly created, password of the user is hashed. The next time it is hashed once again is &lt;strong&gt;only&lt;/strong&gt; when a user's password attribute is changed. Probably when a user has updated their password.&lt;/p&gt;

&lt;p&gt;In the following parts, we have custom methods we are setting on the &lt;code&gt;UserSchema&lt;/code&gt;. They will be available on the &lt;code&gt;User&lt;/code&gt; model and are helpful in avoiding redundant code from the controllers.&lt;/p&gt;

&lt;p&gt;Under the &lt;b&gt;4&lt;sup&gt;th&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;4. ATTACH CUSTOM STATIC METHODS&lt;/code&gt;), add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findByCredentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;UserModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Wrong credentials!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email or password is wrong!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;passwdMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;passwdMatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Wrong credentials!!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email or password is wrong!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;We have created a &lt;strong&gt;static method&lt;/strong&gt; that is invokable directly on &lt;em&gt;&lt;code&gt;User&lt;/code&gt; model&lt;/em&gt; rather than its &lt;em&gt;instance&lt;/em&gt;, enabled by the &lt;code&gt;statics&lt;/code&gt; property on the &lt;code&gt;UserSchema&lt;/code&gt;. This method simply finds a user by &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt;. It throws an exception if the find is not successful.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt; how we generate user-defined exception using custom error constructor(&lt;code&gt;throw new CustomError(...)&lt;/code&gt;). That is explained in Express.js error handling&lt;/em&gt;. Otherwise you can use the in-built &lt;code&gt;new Error()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;b&gt;5&lt;sup&gt;th&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;5. ATTACH CUSTOM INSTANCE METHODS&lt;/code&gt;), we will add &lt;strong&gt;three instance methods&lt;/strong&gt; that will be invokable on the &lt;code&gt;User&lt;/code&gt; model instance:&lt;/p&gt;

&lt;p&gt;Add the &lt;strong&gt;first instance method&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateAcessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Create signed access token&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="na"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nx"&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expiry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This instance method generates an &lt;em&gt;access token&lt;/em&gt;. The &lt;em&gt;access token&lt;/em&gt; is a &lt;em&gt;signed jwt&lt;/em&gt; embedded with user instance data.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; We use traditional functions because they have &lt;code&gt;this&lt;/code&gt; binding. Using arrow functions will not produce expected results.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Add the &lt;strong&gt;second instance method&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateRefreshToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Create signed refresh token&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expiry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a 'refresh token hash' from 'refresh token'&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rTknHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Save 'refresh token hash' to database&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rTknHash&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Similar to &lt;em&gt;first instance method&lt;/em&gt;, this method generates a &lt;strong&gt;refresh token&lt;/strong&gt; which is a &lt;em&gt;signed jwt&lt;/em&gt; embedded with user instance data. We store the refresh token in the DB. It will be useful in implementing a log out from all devices feature as seen later in the blog.&lt;br&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; We store a hashed version of the refresh token in the database which is a security practice to prevent changing users' password should the database be compromised&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Add the &lt;strong&gt;third instance method&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateResetToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resetTokenValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resetTokenSecret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Separator of `+` because generated base64url characters doesn't include this character&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resetToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resetTokenValue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resetTokenSecret&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a hash&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resetTokenHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resetTokenSecret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resetTokenValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetpasswordtoken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resetTokenHash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetpasswordtokenexpiry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RESET_PASSWORD_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expiry&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Sets expiration age&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;resetToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This instance method creates a &lt;strong&gt;reset token&lt;/strong&gt; and a &lt;strong&gt;reset token hash&lt;/strong&gt;. We use NodeJs native &lt;code&gt;crypto&lt;/code&gt; module to create &lt;code&gt;resetTokenValue&lt;/code&gt; and &lt;code&gt;resetTokenSecret&lt;/code&gt;. A &lt;code&gt;resetToken&lt;/code&gt; is obtained by concatenating these parts. We also create a &lt;code&gt;resetTokenHash&lt;/code&gt; from these parts. We return plaintext &lt;code&gt;resetToken&lt;/code&gt; while &lt;code&gt;resetTokenHash&lt;/code&gt; is saved to the database. In the database, we also set an expiry to the reset token so that it is expired after a duration or after use.&lt;/p&gt;

&lt;p&gt;The first part(&lt;code&gt;resetTokenValue&lt;/code&gt;) is created with &lt;strong&gt;&lt;code&gt;base64url&lt;/code&gt;&lt;/strong&gt; encoding. The second part(&lt;code&gt;resetTokenSecret&lt;/code&gt;) is created with &lt;strong&gt;&lt;code&gt;hex&lt;/code&gt;&lt;/strong&gt; encoding. These encodings allow to concatenate the two parts, to form a &lt;strong&gt;resultant &lt;code&gt;resetToken&lt;/code&gt;&lt;/strong&gt;. A plus(&lt;code&gt;+&lt;/code&gt;) separator is specially used; since both of these encodings will never generate the &lt;code&gt;+&lt;/code&gt; character.&lt;br&gt;&lt;br&gt;
&lt;em&gt;&lt;code&gt;hex&lt;/code&gt; encoding may be straight forward, i.e represented by only 16 symbols(&lt;code&gt;0-9&lt;/code&gt; and &lt;code&gt;A-F&lt;/code&gt;). Learn more about &lt;code&gt;base64url&lt;/code&gt; encoding &lt;a href="https://www.rfc-editor.org/rfc/rfc4648#section-5" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;b&gt;6&lt;sup&gt;th&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;6. COMPILE MODEL FROM SCHEMA&lt;/code&gt;): we &lt;strong&gt;compile a model&lt;/strong&gt; from the schema integrated with additional definitions outlined in previous parts:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Add email service
&lt;/h2&gt;

&lt;p&gt;Our application needs to send emails, an example usecase is sending password reset link to a user.&lt;br&gt;
We will use nodemailer as a &lt;a href="https://help.returnpath.com/hc/en-us/articles/220569547-What-is-a-Mail-User-Agent-MUA-" rel="noopener noreferrer"&gt;Mail User Agent&lt;/a&gt;(&lt;em&gt;MUA&lt;/em&gt;) to send emails from our NodeJs application; by connecting to an SMTP server.&lt;/p&gt;

&lt;p&gt;We will use &lt;a href="https://mailtrap.io/" rel="noopener noreferrer"&gt;Mailtrap&lt;/a&gt; as our &lt;strong&gt;SMTP server&lt;/strong&gt;, responsible to deliver emails.&lt;br&gt;&lt;br&gt;
Mailtrap can be used for email delivery. Apart from that, it offers a feature great for testing, that is, it can be used as fake SMTP server. This means &lt;em&gt;we can use Mailtrap's SMTP server to receive emails from our NodeJs application and emulate sending without actual delivery&lt;/em&gt;. This service is ideal &lt;strong&gt;to test and view emails we send without spamming real recipients or flooding your own inboxes&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
When you're ready to &lt;em&gt;send emails to real inboxes&lt;/em&gt;, you can upgrade your Mailtrap account to enable actual email delivery. Alternatively, you can configure Nodemailer to work with a different provider &lt;em&gt;such as Sendgrid or &lt;a href="https://www.brevo.com/" rel="noopener noreferrer"&gt;Brevo&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You will need to get credentials from mailtrap to use their SMTP service. Follow this &lt;a href="https://help.mailtrap.io/article/5-smtp-integration" rel="noopener noreferrer"&gt;guide&lt;/a&gt; to get necessary credentials for SMTP integration.&lt;/p&gt;

&lt;p&gt;Once you've completed the guide, you should have the following credentials ready:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Host&lt;/li&gt;
&lt;li&gt;Port&lt;/li&gt;
&lt;li&gt;Username&lt;/li&gt;
&lt;li&gt;Password&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We'll directly add the &lt;strong&gt;Host&lt;/strong&gt; and &lt;strong&gt;Port&lt;/strong&gt; to the Nodemailer configuration options. To protect sensitive information, we'll store the &lt;strong&gt;Username&lt;/strong&gt; and &lt;strong&gt;Password&lt;/strong&gt; in environment variables.&lt;br&gt;&lt;br&gt;
Open &lt;code&gt;.env&lt;/code&gt; file located at &lt;code&gt;server/&lt;/code&gt; directory root(refer above). Append new variables:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;AUTH_EMAIL_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;Username&amp;gt;
&lt;span class="nv"&gt;AUTH_EMAIL_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;Password&amp;gt;
&lt;span class="nv"&gt;EMAIL_FROM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;Email sender&amp;gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;code&gt;EMAIL_FROM&lt;/code&gt; is the sender in an email delivery. You can fill with your own email.&lt;/p&gt;

&lt;p&gt;Create the file: &lt;strong&gt;&lt;code&gt;email.js&lt;/code&gt;&lt;/strong&gt;. According to the directory structure for this tutorial(refer above), it should be at the path: &lt;code&gt;server/src/services/email/&lt;/code&gt;.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Paste in the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodemailer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nodemailer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Pull in Environments variables&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;EMAIL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;authUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTH_EMAIL_USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;authPass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTH_EMAIL_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mailOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create reusable transporter object using the default SMTP transport&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transporter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nodemailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;smtp.mailtrap.io&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2525&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EMAIL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EMAIL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authPass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Send mail with defined transport object&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;transporter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMail&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mailOptions&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mailOptions&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mailOptions&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mailOptions&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mailOptions&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;In above snippet we have exported a &lt;code&gt;main()&lt;/code&gt; function that connects our application to Mailtrap SMTP server facilitated with nodemailer's &lt;code&gt;createTransport(...)&lt;/code&gt;. Emails from our application are forwarded to SMTP server for actual sending using nodemailer's &lt;code&gt;transporter.sendMail(...)&lt;/code&gt;. An &lt;code&gt;info&lt;/code&gt; object is returned containing the delivery information.&lt;/p&gt;

&lt;p&gt;Open/create a second file &lt;code&gt;sendEmail.js&lt;/code&gt;. It should be located at &lt;code&gt;server/src/services/email/&lt;/code&gt;, beside &lt;code&gt;email.js&lt;/code&gt;(refer above).&lt;/p&gt;

&lt;p&gt;Paste in the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./email.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fixedMailOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EMAIL_FROM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mailOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fixedMailOptions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mailOptions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Short and sweet ✔. We are calling imported &lt;code&gt;main()&lt;/code&gt; function and passing to it &lt;code&gt;mailOptions&lt;/code&gt; to run email sending. We then export the &lt;code&gt;sendEmail()&lt;/code&gt; that will be used in our application.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Create validators
&lt;/h2&gt;

&lt;p&gt;Form data submitted from client to server &lt;strong&gt;cannot be trusted&lt;/strong&gt;. We need to &lt;em&gt;enforce validation rules&lt;/em&gt; for these data before we can start processing them in our server.&lt;/p&gt;

&lt;p&gt;For server-side validation, we'll use &lt;a href="https://express-validator.github.io/docs/" rel="noopener noreferrer"&gt;express-validator&lt;/a&gt; which according to the docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;express-validator&lt;/em&gt; is a set of &lt;a href="http://expressjs.com/" rel="noopener noreferrer"&gt;express.js&lt;/a&gt; middlewares that wraps &lt;a href="https://github.com/validatorjs/validator.js" rel="noopener noreferrer"&gt;validator.js&lt;/a&gt; validator and sanitizer functions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Being wrapped in express.js middlewares, means it would be easy to work with in an express.js application.&lt;/p&gt;

&lt;p&gt;Let's create our &lt;strong&gt;first set&lt;/strong&gt; of validators.&lt;br&gt;&lt;br&gt;
Create a file &lt;code&gt;auth-validators.js&lt;/code&gt; located at &lt;code&gt;server/src/validators/&lt;/code&gt;(refer above). Add the following code in it:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express-validator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../models/User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loginValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email CANNOT be empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email is invalid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notEmpty&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password CANNOT be empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signupValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firstName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Firstname CANNOT be empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lastName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lastname CANNOT be empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email CANNOT be empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email is invalid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;custom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Finding if email exists in Database&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emailExists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailExists&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;E-mail already in use&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password CANNOT be empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isLength&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password MUST be at least 4 characters long&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forgotPasswordValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email CANNOT be empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email is invalid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetPasswordValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resetToken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notEmpty&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Reset token missing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password CANNOT be empty&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isLength&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password MUST be at least 4 characters long&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;passwordConfirm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;custom&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Passwords DO NOT match&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The code snippet above exports validation rules to be used on requests carrying data received from client-side forms. These are rules about a user's authentication.&lt;/p&gt;

&lt;p&gt;For the &lt;strong&gt;second set&lt;/strong&gt; of validators, create &lt;code&gt;user-validators.js&lt;/code&gt; located at &lt;code&gt;server/src/validators/&lt;/code&gt;(refer above).&lt;/p&gt;

&lt;p&gt;And paste in the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;param&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express-validator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchUserProfileValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notEmpty&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User id missing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The above snippet exports validation rule(s) that act on user object in our application.&lt;/p&gt;

&lt;p&gt;Lastly, we would like to export all the validation rules from a single file.&lt;br&gt;&lt;br&gt;
Create &lt;code&gt;index.js&lt;/code&gt; at &lt;code&gt;server/src/validators/&lt;/code&gt;(refer above). And paste in:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authValidators&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./auth-validators&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userValidators&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./user-validators&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;authValidators&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;userValidators&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Simply, we are combining all validation rules and exporting as a single object.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Create authentication middleware
&lt;/h2&gt;

&lt;p&gt;An authentication middleware will intercept HTTP requests to check for authentication.&lt;br&gt;&lt;br&gt;
A request is allowed to proceed to a resource after it has passed authentication check.&lt;/p&gt;

&lt;p&gt;Let's create this middleware. So create &lt;code&gt;authCheck.js&lt;/code&gt;. According to directory structure(refer above), it should be at the path: &lt;code&gt;server/src/middlewares/&lt;/code&gt;.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Paste in the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AuthorizationError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../config/errors/AuthorizationError.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Pull in Environment variables&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ACCESS_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTH_ACCESS_TOKEN_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requireAuthentication&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authHeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;authHeader&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bearer &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authentication Error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are unauthenticated!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;invalid_access_token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;error_description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unknown authentication scheme&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accessTokenParts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;authHeader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aTkn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;accessTokenParts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aTkn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Attach authenticated user and Access Token to request object&lt;/span&gt;
        &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aTkn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Authentication check didn't go well&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;expired_access_token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;error_description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;access token is expired&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TokenExpiredError&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authentication Error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Token lifetime exceeded!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nx"&gt;expParams&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Above snippet is an express middleware that checks if a request is authenticated in the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The request has an &lt;em&gt;access token&lt;/em&gt; present in the &lt;code&gt;Authorization&lt;/code&gt; header. A &lt;strong&gt;Bearer&lt;/strong&gt; token is expected, so we use the split function to get everything after the space. Any errors thrown here will end up in the &lt;code&gt;catch&lt;/code&gt; block.&lt;/li&gt;
&lt;li&gt;Verify if the &lt;em&gt;access token&lt;/em&gt; is valid.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A request is considered authenticated if all goes well in the above steps. It would then be allowed to proceed to a protected resource.&lt;br&gt;&lt;br&gt;
Otherwise, an exception is &lt;code&gt;throw&lt;/code&gt;n with a custom error constructor &lt;code&gt;AuthorizationError()&lt;/code&gt; which would return an authentication failure response regarding the &lt;a href="https://www.rfc-editor.org/rfc/rfc9110.html#field.www-authenticate" rel="noopener noreferrer"&gt;HTTP specs&lt;/a&gt; for returning &lt;em&gt;unauthorized/unauthenticated error&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h2&gt;
  
  
  Create controller functions
&lt;/h2&gt;

&lt;p&gt;In this part we write controllers; the program logic for routes in our application. In express, they are also known as &lt;em&gt;route handlers&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Typically in a routing mechanism, a controller registered for a particular path/route will be run when that route matches. Below are &lt;strong&gt;routes&lt;/strong&gt; in our application. We will write controllers for these routes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/api/users/login&lt;/code&gt;&lt;/strong&gt; - User login.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/api/users/signup&lt;/code&gt;&lt;/strong&gt; - User signup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/api/users/logout&lt;/code&gt;&lt;/strong&gt; - User logout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/api/users/master-logout&lt;/code&gt;&lt;/strong&gt; - User logout from all devices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/api/users/reauth&lt;/code&gt;&lt;/strong&gt; - Refresh Access Token.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/api/users/forgotpass&lt;/code&gt;&lt;/strong&gt; - Forgot password.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/api/users/resetpass&lt;/code&gt;&lt;/strong&gt; - Reset password.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/api/users/me&lt;/code&gt;&lt;/strong&gt; - Get profile of logged in user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/api/users/:id&lt;/code&gt;&lt;/strong&gt; - Get profile of user by Id.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So let's get started with creating controllers.&lt;/p&gt;

&lt;p&gt;Create &lt;strong&gt;&lt;code&gt;auth.controller.js&lt;/code&gt;&lt;/strong&gt;. It should be at the path: &lt;code&gt;server/src/controllers/user/&lt;/code&gt;(refer above).&lt;br&gt;&lt;br&gt;
This file will contain controllers that alter user's authentication.&lt;/p&gt;

&lt;p&gt;Paste the following code inside the file:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;validationResult&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express-validator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../models/User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sendEmail&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../services/email/sendEmail&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// 👇Were created in part 4&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CustomError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../config/errors/CustomError&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AuthorizationError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../config/errors/AuthorizationError&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Top-level constants&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTH_REFRESH_TOKEN_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;refreshTkn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;sameSite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;None&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;maxAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ACCESS_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTH_ACCESS_TOKEN_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RESET_PASSWORD_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;expiry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RESET_PASSWORD_TOKEN_EXPIRY_MINS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="cm"&gt;/*
  1. LOGIN USER
*/&lt;/span&gt;

&lt;span class="cm"&gt;/*
  2. SIGN UP USER 
*/&lt;/span&gt;

&lt;span class="cm"&gt;/*
  3. LOGOUT USER
*/&lt;/span&gt;

&lt;span class="cm"&gt;/*
  4. LOGOUT USER FROM ALL DEVICES
*/&lt;/span&gt;

&lt;span class="cm"&gt;/*
  5. REGENERATE NEW ACCESS TOKEN
*/&lt;/span&gt;

&lt;span class="cm"&gt;/*
  6. FORGOT PASSWORD
*/&lt;/span&gt;

&lt;span class="cm"&gt;/*
  7. RESET PASSWORD
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The snippet above has imported modules/dependencies to aid writing logic in controller functions. Global scoped constants which are objects, are also declared. They store environment variables.&lt;br&gt;&lt;br&gt;
Moreover, &lt;code&gt;const REFRESH_TOKEN&lt;/code&gt; constant holds &lt;em&gt;cookie configurations&lt;/em&gt; in &lt;code&gt;cookie&lt;/code&gt; property we will use to set cookie(s) on a HTTP response.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;WHAT YOU NEED TO KNOW ABOUT COOKIES&lt;/strong&gt; in decoupled applications communicating to each other via an API:&lt;/em&gt;&lt;br&gt;&lt;br&gt;
By default, &lt;strong&gt;browsers will not send cookies in cross-origin requests&lt;/strong&gt;. Since we are building an API that we intend to consume from &lt;em&gt;client-side sitting on a different origin&lt;/em&gt;, we have to &lt;em&gt;set some configurations on the cookie to store in a user's browser&lt;/em&gt;. These configurations will allow the cookie to be sent back when cross-site request to our server is made.&lt;br&gt;&lt;br&gt;
These configurations are what are contained in &lt;code&gt;cookie&lt;/code&gt; property of &lt;code&gt;const REFRESH_TOKEN&lt;/code&gt; object. More specifically in the &lt;code&gt;options&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="na"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;refreshTkn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;sameSite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;None&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;maxAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;We have set &lt;strong&gt;&lt;code&gt;sameSite&lt;/code&gt;&lt;/strong&gt; property to &lt;code&gt;"None"&lt;/code&gt; which in a cookie context means that the browser can send the cookie with cross site requests.&lt;br&gt;&lt;br&gt;
However, setting a &lt;code&gt;SameSite&lt;/code&gt; attribute to &lt;code&gt;None&lt;/code&gt; will also require you to set &lt;code&gt;Secure&lt;/code&gt; attribute, &lt;em&gt;implying a cookie is only sent in an encrypted request over the HTTPS protocol&lt;/em&gt;. Hence in cookie configurations above, we also set &lt;strong&gt;&lt;code&gt;secure&lt;/code&gt;&lt;/strong&gt; to &lt;code&gt;true&lt;/code&gt;. &lt;em&gt;Localhost&lt;/em&gt; is not a https protocol but it is treated special &lt;em&gt;i.e cookie should still be sent even with &lt;code&gt;secure=true&lt;/code&gt;&lt;/em&gt;. You can learn more about &lt;em&gt;cookie sameSite attribute&lt;/em&gt; &lt;a href="https://web.dev/samesite-cookies-explained/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Another property is &lt;strong&gt;&lt;code&gt;httpOnly&lt;/code&gt;&lt;/strong&gt; set to &lt;code&gt;true&lt;/code&gt;. In cookie context, a cookie with &lt;code&gt;httponly&lt;/code&gt; attribute stored in the browser is &lt;strong&gt;inaccessible&lt;/strong&gt; to scripts running on the browser.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;&lt;code&gt;maxAge&lt;/code&gt;&lt;/strong&gt; property sets the age of the cookie to expire in browser.&lt;/p&gt;

&lt;p&gt;In the snippet above; where we shared code for &lt;code&gt;auth.controller.js&lt;/code&gt;, we have &lt;strong&gt;7 parts&lt;/strong&gt; numbered each in a multiline comment. We will write controller functions in parts.&lt;/p&gt;

&lt;p&gt;In the &lt;b&gt;1&lt;sup&gt;st&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;1. LOGIN USER&lt;/code&gt;), Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="cm"&gt;/* Custom methods on user are defined in User model */&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByCredentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Identify and retrieve user by credentials&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateAcessToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Create Access Token&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateRefreshToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Create Refresh Token&lt;/span&gt;

        &lt;span class="c1"&gt;// SET refresh Token cookie in response&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Send Response on successful Login&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;strong&gt;Notice🕵&lt;/strong&gt; that we create controllers with the signature of an express middleware, &lt;em&gt;i.e &lt;code&gt;(req, res, next) =&amp;gt; {...}&lt;/code&gt;&lt;/em&gt;. Creating this way will allow us to use &lt;code&gt;next()&lt;/code&gt; to pass error encountered here to the error handling midleware configured earlier on.&lt;/p&gt;

&lt;p&gt;You'll see this piece of code frequently:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;It captures validation errors on the &lt;code&gt;req&lt;/code&gt;uest object. Validators are &lt;em&gt;route level middlewares&lt;/em&gt; added before controllers that need user data validation in a route. They enforce validation rules on data in &lt;code&gt;req&lt;/code&gt;uest object. Validation result including errors are &lt;strong&gt;aggregated&lt;/strong&gt; on the request object, hence validation result is available in &lt;code&gt;req&lt;/code&gt;uest object from our controllers. We &lt;code&gt;throw&lt;/code&gt; an error using a &lt;code&gt;CustomError&lt;/code&gt; constructor if data validation errors are found in &lt;code&gt;req&lt;/code&gt;uest object.&lt;/p&gt;

&lt;p&gt;Aside from data validation, the exported controller shared above stipulates control flow for a user login:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify user by login credentials received.&lt;/li&gt;
&lt;li&gt;Generate Access and Refresh Tokens for the identified user.&lt;/li&gt;
&lt;li&gt;Set a cookie in response with &lt;em&gt;Refresh Token&lt;/em&gt; as its value.&lt;/li&gt;
&lt;li&gt;Send response with &lt;em&gt;Access Token&lt;/em&gt; in the body.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the &lt;b&gt;2&lt;sup&gt;nd&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;2. SIGN UP USER&lt;/code&gt;), Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="cm"&gt;/* Custom methods on newUser are defined in User model */&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Save new User to DB&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateAcessToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Create Access Token&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateRefreshToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Create Refresh Token&lt;/span&gt;

        &lt;span class="c1"&gt;// SET refresh Token cookie in response&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Send Response on successful Sign Up&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The flow of user sign up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save new user with user data from &lt;code&gt;req&lt;/code&gt;uest body.&lt;/li&gt;
&lt;li&gt;Generate Access and Refresh Tokens for the new user.&lt;/li&gt;
&lt;li&gt;Set a cookie in response with &lt;em&gt;Refresh Token&lt;/em&gt; as its value.&lt;/li&gt;
&lt;li&gt;Send response with &lt;em&gt;Access Token&lt;/em&gt; included in the body.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We include authentication tokens in response because presumably after a successful sign up, the frontend would want to automatically login a user.&lt;/p&gt;

&lt;p&gt;In the &lt;b&gt;3&lt;sup&gt;rd&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;3. LOGOUT USER&lt;/code&gt;), Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Authenticated user ID attached on `req` by authentication middleware&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cookies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="c1"&gt;// Create a refresh token hash&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rTknHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenObj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;tokenObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;rTknHash&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Set cookie expiry option to past date so it is destroyed&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expireCookieOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{},&lt;/span&gt;
            &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;expires&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Destroy refresh token cookie with `expireCookieOptions` containing a past date&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expireCookieOptions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;205&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;To logout a user:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We obtain refresh token from cookie in incoming request.&lt;/li&gt;
&lt;li&gt;Create a hash of the retrieved refresh token to match it with the hashed version stored in the database.&lt;/li&gt;
&lt;li&gt;Remove the corresponding hashed refresh token from the list of tokens associated with the user’s record in the database.&lt;/li&gt;
&lt;li&gt;Set the refresh token's cookie expiration date to a past time, ensuring that browsers delete it immediately upon receipt.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note 🔔&lt;/strong&gt;&lt;/em&gt;:&lt;br&gt;&lt;br&gt;
How we have handled logout is &lt;strong&gt;designed&lt;/strong&gt; to preserve the &lt;strong&gt;stateless&lt;/strong&gt; nature of JWTs. By destroying refresh token, it prevents a user from refreshing(renewing) their access token.&lt;br&gt;&lt;br&gt;
However, we do not implement a blocklist to immediately invalidate the current access token, meaning it remains valid until it expires.&lt;br&gt;&lt;br&gt;
While a blocklist could be integrated into the &lt;em&gt;authentication middleware&lt;/em&gt; to invalidate Access Tokens instantly, maintaining such a list would contradict the &lt;em&gt;stateless&lt;/em&gt; principles of JWTs, even though it effectively ensures immediate Access Token invalidation upon logout.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the &lt;b&gt;4&lt;sup&gt;th&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;4. LOGOUT USER FROM ALL DEVICES&lt;/code&gt;), Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logoutAllDevices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Authenticated user ID attached on `req` by authentication middleware&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Set cookie expiry to past date to mark for destruction&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expireCookieOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{},&lt;/span&gt;
            &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;expires&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Destroy refresh token cookie&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expireCookieOptions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;205&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;It is the same concept as &lt;code&gt;logout&lt;/code&gt; controller. Only that this time, we destroy all tokens in a user's record, with the line of code: &lt;code&gt;user.tokens = undefined;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;b&gt;5&lt;sup&gt;th&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;5. REGENERATE NEW ACCESS TOKEN&lt;/code&gt;), Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;refreshAccessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cookies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authentication error!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are unauthenticated&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;realm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Obtain new Access Token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no_rft&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;error_description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Refresh Token is missing!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decodedRefreshTkn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rTknHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;REFRESH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userWithRefreshTkn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;decodedRefreshTkn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tokens.token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rTknHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;userWithRefreshTkn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authentication Error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are unauthenticated!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;realm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Obtain new Access Token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// GENERATE NEW ACCESSTOKEN&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newAtkn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userWithRefreshTkn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateAcessToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cache-Control&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no-store&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;Pragma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no-cache&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="c1"&gt;// Send response with NEW accessToken&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newAtkn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JsonWebTokenError&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are unauthenticated&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="na"&gt;realm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Obtain new Access Token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;error_description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;token error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The &lt;code&gt;refreshAccessToken&lt;/code&gt; controller:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extracts refresh token from the incoming HTTP request's cookies.&lt;/li&gt;
&lt;li&gt;Decodes the extracted refresh token to access its payload.&lt;/li&gt;
&lt;li&gt;Generates a hash of the original (encoded) refresh token extracted from the cookies.&lt;/li&gt;
&lt;li&gt;Query the database to find a user that matches two criteria:

&lt;ol&gt;
&lt;li&gt;The user's &lt;code&gt;_id&lt;/code&gt; matches the one stored in the &lt;em&gt;decoded&lt;/em&gt; refresh token payload.&lt;/li&gt;
&lt;li&gt;The user's stored refresh token hash matches the hash generated in step 3.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;If a matching user is found, generate a &lt;em&gt;new&lt;/em&gt; Access Token containing embedded relevant user data retrieved from the database.&lt;/li&gt;

&lt;li&gt;Send HTTP response containing the newly generated Access Token.&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;In the &lt;b&gt;6&lt;sup&gt;th&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;6. FORGOT PASSWORD&lt;/code&gt;), Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forgotPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MSG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`If &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;
        &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;__&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is found with us, we've sent an email to it with instructions to reset your password.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="c1"&gt;// If email is not found, we throw an exception BUT with 200 status code&lt;/span&gt;
        &lt;span class="c1"&gt;// because it is a security vulnerability to inform users&lt;/span&gt;
        &lt;span class="c1"&gt;// that the Email is not found.&lt;/span&gt;
        &lt;span class="c1"&gt;// To avoid username enumeration attacks, no extra response data is provided when an email is successfully sent. (The same response is provided when the username is invalid.)&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Reset link sent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MSG&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;resetToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateResetToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;resetToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resetToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resetPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-reset-base&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;origin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Origin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resetUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resetPath&lt;/span&gt;
            &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resetPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resetToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
            &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/resetpass/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resetToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password reset URL: %s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resetUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emailMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
                &amp;lt;h1&amp;gt;You have requested to change your password&amp;lt;/h1&amp;gt;
                &amp;lt;p&amp;gt;You are receiving this because someone(hopefully you) has requested to reset password for your account.&amp;lt;br/&amp;gt;
                Please click on the following link, or paste in your browser to complete the password reset.
                &amp;lt;/p&amp;gt;
                &amp;lt;p&amp;gt;
                &amp;lt;a href=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resetUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; clicktracking=off&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;resetUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/a&amp;gt;
                &amp;lt;/p&amp;gt;
                &amp;lt;p&amp;gt;
                &amp;lt;em&amp;gt;
                    If you did not request this, you can safely ignore this email and your password will remain unchanged.
                &amp;lt;/em&amp;gt;
                &amp;lt;/p&amp;gt;
                &amp;lt;p&amp;gt;
                &amp;lt;strong&amp;gt;DO NOT share this link with anyone else!&amp;lt;/strong&amp;gt;&amp;lt;br /&amp;gt;
                &amp;lt;small&amp;gt;
                    &amp;lt;em&amp;gt;
                    This password reset link will &amp;lt;strong&amp;gt;expire after &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;
                        &lt;span class="nx"&gt;RESET_PASSWORD_TOKEN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expiry&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; minutes.&amp;lt;/strong&amp;gt;
                    &amp;lt;/em&amp;gt;
                &amp;lt;small/&amp;gt;
                &amp;lt;/p&amp;gt;
            `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;emailMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Reset password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;

            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Reset link sent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;feedback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MSG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetpasswordtoken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetpasswordtokenexpiry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Internal issues standing in the way&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="mi"&gt;500&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The code above implements a forgot password handler that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Queries the database to retrieve a user account associated with the email address provided in the incoming HTTP request.&lt;/li&gt;
&lt;li&gt;Generates and sends an email to the identified user, containing a secure link for password reset.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a sample email sent to a user:&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
    &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30csloqqfs0gqnm5zp5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30csloqqfs0gqnm5zp5u.png" alt="sample reset email message" width="696" height="227"&gt;&lt;/a&gt;&lt;br&gt;Password reset email
    &lt;br&gt;
  &lt;/p&gt;

&lt;p&gt;In the &lt;b&gt;7&lt;sup&gt;th&lt;/sup&gt; part&lt;/b&gt;(&lt;code&gt;7. RESET PASSWORD&lt;/code&gt;), Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resetToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tokenValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenSecret&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="nf"&gt;decodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resetToken&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Recreate the reset Token hash&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resetTokenHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenSecret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;resetpasswordtoken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;resetTokenHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;resetpasswordtokenexpiry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$gt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The reset link is invalid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Will be hashed by mongoose middleware&lt;/span&gt;
        &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetpasswordtoken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetpasswordtokenexpiry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Email to notify owner of the account&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;h3&amp;gt;This is a confirmation that you have changed Password for your account.&amp;lt;/h3&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// No need to await&lt;/span&gt;
        &lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password changed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Password reset successful&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The code snippet implements a password reset handler that follows these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extract the &lt;em&gt;reset token&lt;/em&gt; from the incoming HTTP request.&lt;/li&gt;
&lt;li&gt;Decode the URI-encoded &lt;em&gt;reset token&lt;/em&gt; using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent" rel="noopener noreferrer"&gt;decodeURIComponent()&lt;/a&gt; to restore its original character representation.&lt;/li&gt;
&lt;li&gt;Parse the &lt;em&gt;decoded reset token&lt;/em&gt;, which is composed of two parts—a &lt;em&gt;reset token value&lt;/em&gt; and a &lt;em&gt;reset token secret&lt;/em&gt;—separated by a &lt;em&gt;&lt;code&gt;+&lt;/code&gt;&lt;/em&gt; symbol.&lt;/li&gt;
&lt;li&gt;Generate a &lt;em&gt;reset token hash&lt;/em&gt; using the parsed components, as the database stores &lt;em&gt;reset tokens&lt;/em&gt; in hashed form for security.&lt;/li&gt;
&lt;li&gt;Query the database for a user record that meets two criteria:

&lt;ol&gt;
&lt;li&gt;The stored &lt;em&gt;reset password token&lt;/em&gt; matches the generated &lt;em&gt;reset token hash&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The token's expiry time has not yet passed.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;If a matching user is found, update their password with the new password provided in the request body.&lt;/li&gt;

&lt;li&gt;Asynchronously send an email notification to the user confirming the password change, while simultaneously returning a success HTTP response to the client.&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;So we have created the first set of controller functions that control user's auth in &lt;code&gt;auth.controller.js&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Next we need to create the &lt;strong&gt;second set of controller functions&lt;/strong&gt; that act on user object in our application.&lt;/p&gt;

&lt;p&gt;Open/create &lt;strong&gt;&lt;code&gt;user.controller.js&lt;/code&gt;&lt;/strong&gt;. According to the directory structure for this tutorial, it should be at the path: &lt;code&gt;server/src/controllers/user/&lt;/code&gt;(refer above). Create the constituent directories if you do not have.&lt;br&gt;&lt;br&gt;
This file will contain controllers that act on user object in our application.&lt;/p&gt;

&lt;p&gt;Paste in the below code inside this file:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;validationResult&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express-validator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CustomError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../config/errors/CustomError&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../models/User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/* 
  1. FETCH USER PROFILE BY ID
*/&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchUserProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;retrievedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;retrievedUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="cm"&gt;/* 
  2. FETCH PROFILE OF AUTHENTICATED USER
*/&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchAuthUserProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This is straight forward. We have two functions that fetch user profile. The first one &lt;code&gt;fetchUserProfile()&lt;/code&gt;, fetches a user by ID provided in URL. And the second one &lt;code&gt;fetchAuthUserProfile&lt;/code&gt;, fetches a user by ID gotten from authentication middleware as &lt;code&gt;req.userId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We have so far created and exported controller functions in separate files. Let's export all these controllers from a single file so that we could import them in other modules with one import statement.&lt;/p&gt;

&lt;p&gt;For this, open/create a third file &lt;strong&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/strong&gt;, at the location &lt;code&gt;server/src/controllers/user/&lt;/code&gt;(refer above).&lt;br&gt;&lt;br&gt;
Add the code below in this file:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./auth.controller&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./user.controller&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;We export one object that includes all exports from the imported files.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Create application routes
&lt;/h2&gt;

&lt;p&gt;So far, we have written models and controllers. Now we need to create routes in our application. Basically, we will &lt;em&gt;specify route paths&lt;/em&gt; and the &lt;em&gt;controller&lt;/em&gt; to execute program logic at that path.&lt;/p&gt;

&lt;p&gt;For this, open/create &lt;strong&gt;&lt;code&gt;user.routes.js&lt;/code&gt;&lt;/strong&gt;, at the location &lt;code&gt;server/src/routes/&lt;/code&gt;(refer above). Create the constituent directories if you do not have.&lt;br&gt;&lt;br&gt;
Add the code below in this file:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validators&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../validators&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userControllers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../controllers/user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;requireAuthentication&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../middlewares/authCheck&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// User Login&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loginValidator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userControllers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// User Signup&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/signup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signupValidator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userControllers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signup&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// User Logout&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/logout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requireAuthentication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userControllers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// User Logout from all devices&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/master-logout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;requireAuthentication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;userControllers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logoutAllDevices&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Refresh Access Token&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/reauth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userControllers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;refreshAccessToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Forgot password&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/forgotpass&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forgotPasswordValidator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;userControllers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forgotPassword&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Reset password&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/resetpass/:resetToken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetPasswordValidator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;userControllers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetPassword&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Authenticated user profile&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/me&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;requireAuthentication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;userControllers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchAuthUserProfile&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Get user by ID&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;requireAuthentication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchUserProfileValidator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;userControllers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchUserProfile&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The code above contains the routes our application will have. We used &lt;code&gt;express.Router()&lt;/code&gt; to organize application routes into a separate file.&lt;/p&gt;

&lt;p&gt;Using the classic &lt;code&gt;router&lt;/code&gt; object, we define routes in the order of &lt;em&gt;HTTP Method&lt;/em&gt;, &lt;em&gt;route path&lt;/em&gt; and &lt;em&gt;controller&lt;/em&gt;, &lt;em&gt;i.e router.&lt;code&gt;METHOD&lt;/code&gt;(&lt;code&gt;"PATH"&lt;/code&gt;, &lt;code&gt;CONTROLLER&lt;/code&gt;)&lt;/em&gt;. In between &lt;em&gt;route path&lt;/em&gt; and &lt;em&gt;controller&lt;/em&gt;, we can add &lt;em&gt;middleware(s)&lt;/em&gt; that intercept a request for earlier processing.&lt;/p&gt;

&lt;p&gt;For instance, from the snippet above, Authentication middleware(&lt;code&gt;requireAuthentication&lt;/code&gt;) and validators(&lt;code&gt;validators.x&lt;/code&gt;) are middlewares that intercept a request before it is processed in controller(&lt;code&gt;userControllers.x&lt;/code&gt;). Authentication middleware ensures request is authenticated and validators apply validation rules on data within a request.&lt;/p&gt;

&lt;p&gt;Since the routes we have defined are all concerned with the user object in our application, let's define a &lt;em&gt;base path for these routes&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
Open/create &lt;strong&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/strong&gt;, at the location &lt;code&gt;server/src/routes/&lt;/code&gt;(refer above).&lt;br&gt;&lt;br&gt;
Add the code below in this file:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRoutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./user.routes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userRoutes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The snippet above makes &lt;code&gt;userRoutes&lt;/code&gt; available on &lt;code&gt;/users&lt;/code&gt; base path. With this pattern, if your application has another user type e.g admin, you can create another base path for it.&lt;/p&gt;

&lt;p&gt;We then export &lt;code&gt;router&lt;/code&gt; object created here.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h2&gt;
  
  
  Register routes
&lt;/h2&gt;

&lt;p&gt;We need to register routes we have created so that web traffic can be chanelled to them.&lt;/p&gt;

&lt;p&gt;Therefore we need to include these routes in the entry file of our application. Open this file, &lt;code&gt;index.js&lt;/code&gt; located at &lt;code&gt;server&lt;/code&gt; directory root, &lt;em&gt;i.e &lt;code&gt;server/&lt;/code&gt;&lt;/em&gt;(refer above).&lt;/p&gt;

&lt;p&gt;Edit the &lt;b&gt;3&lt;sup&gt;rd&lt;/sup&gt; part&lt;/b&gt; of this file like shown below:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./routes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// import the modular routes at the top&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="cm"&gt;/* 
3. APPLICATION ROUTES 🛣️
*/&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// register modular routes&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;We have imported the routes and regisered them on a base path, &lt;code&gt;"/api"&lt;/code&gt;. Therefore in the long run, user routes will be available on a path &lt;code&gt;/api/users/...&lt;/code&gt;. For example to access login route, the path is &lt;code&gt;/api/users/login&lt;/code&gt;.&lt;/p&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Cheers🥂, we have reached the end. This article has been an extensive exploration, packed with valuable information🤯 to elevate your technical prowess; perhaps the divine touch you needed. Through this process, we've successfully engineered a backend system complete with &lt;em&gt;robust&lt;/em&gt; &lt;strong&gt;user registration&lt;/strong&gt; and &lt;strong&gt;authentication&lt;/strong&gt; features.&lt;br&gt;&lt;br&gt;
It's often observed that newcomers to web development struggle to grasp the intricacies of implementing &lt;em&gt;JWT-based authentication&lt;/em&gt; correctly. Moreover, many find it challenging to incorporate essential security practices when working with JWTs.&lt;/p&gt;

&lt;p&gt;Security is an expansive and mission-critical topic. In this article we have have implemented crucial security practices to consider when using JWTs for authentication, &lt;em&gt;i.e access tokens and refresh tokens&lt;/em&gt;. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  An access token is short-lived unlike the refresh token.&lt;/li&gt;
&lt;li&gt;  Access token can be included in HTTP response body while refresh token is set in &lt;em&gt;httpOnly&lt;/em&gt; response cookie.&lt;/li&gt;
&lt;li&gt;  Secure token storage in databases, i.e in hashed form, crucial to minimize security risk should the database be compromised.&lt;/li&gt;
&lt;li&gt;  A secure process is implemented to refresh Access Tokens using Refresh Tokens.&lt;/li&gt;
&lt;li&gt;  Token clean-up on user logout:

&lt;ul&gt;
&lt;li&gt;  Clear specific token to destroy a specific login session(single log-out)&lt;/li&gt;
&lt;li&gt;  Clear all tokens to destroy all login sessions(log out from all devices)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Building an authentication API is a superb feat. However, I understand that integrating it into a frontend can still feel overwhelming for many. If you're unsure how to piece it all together to create a seamless authentication experience, don’t worry. Let me know in the comments if you would like to see the next sections, where we walk through building the frontend with React, making the process clear and straightforward.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Let's connect &lt;a href="https://x.com/intent/user?screen_name=smitterhane" rel="noopener noreferrer"&gt;@x&lt;/a&gt;. Till then...peace✌.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>api</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The history of HTTPS</title>
      <dc:creator>Smitter</dc:creator>
      <pubDate>Tue, 02 May 2023 13:46:26 +0000</pubDate>
      <link>https://dev.to/smitterhane/how-tls-was-born-to-secure-modern-age-internet-45jb</link>
      <guid>https://dev.to/smitterhane/how-tls-was-born-to-secure-modern-age-internet-45jb</guid>
      <description>&lt;p&gt;Two computers follow a series of agreed-upon steps to establish a communication tunnel with each other. A protocol outlines these compulsory steps. HTTP protocol is the protocol that clients and web servers use to communicate with each other.&lt;/p&gt;

&lt;p&gt;HTTP was developed by Tim Berners-Lee and his team between 1989-1991 while he was working at &lt;a href="https://home.web.cern.ch/" rel="noopener noreferrer"&gt;CERN&lt;/a&gt;. It was intended to exchange files between the multiple computers at the laboratory. It was a clear text protocol.&lt;br&gt;
Other computers outside of CERN adopted the protocol in their internet usage. As internet evolved, sensitive information were being shared via this protocol.&lt;br&gt;
However, since HTTP transfers data between client and server as plain text, it posed a problem. A malicious intruder that intercepts the network segment between you(the client) and the server, is able to view sensitive information such as passwords and credit card numbers. Or the intruder could intercept a client's request and serve back malicious files pretending to be the server.&lt;/p&gt;

&lt;p&gt;Therefore, adding an encryption layer to the HTTP protocol was necessary.&lt;/p&gt;

&lt;p&gt;TLS is an acronym for Transport Layer Security. And it is an &lt;em&gt;encryption layer&lt;/em&gt; added to the HTTP protocol to stop malicious intruders from snooping sensitive and restricted data happening in between client and the server. HTTP protocol that includes an encryption layer upgrades to the acronym of HTTPS(HyperText Transfer Protocol Secure). Hence sensitive information shared via HTTPS protocol can reliably be considered as safe and confidential from eavesdropping attacks.&lt;/p&gt;

&lt;p&gt;TLS was not formed outright as the step of trial and error had not to be skipped. TLS is a successor of SSL(Secure Sockets Layer).&lt;/p&gt;

&lt;h2&gt;
  
  
  SSL developments
&lt;/h2&gt;

&lt;p&gt;As mentioned above, TLS is a successor of SSL.&lt;br&gt;&lt;br&gt;
SSL was a cryptographic protocol developed by Netscape. SSL &lt;strong&gt;version 1.0&lt;/strong&gt; was developed in 1994. But it was &lt;em&gt;never publicly released&lt;/em&gt; because it was discovered to have serious flaws. In February 1995, &lt;strong&gt;version 2.0&lt;/strong&gt;, was developed and released to the public. However it was quickly discovered to contain a number of security and usability flaws.&lt;br&gt;
Microsoft released the first version of its PCT(Private Communication Technology) protocol, designed to address the security flaws in SSL Version 2. PCT never gained traction outside Microsoft products and was later on superseded with SSL version 3.&lt;/p&gt;

&lt;p&gt;Back at Netscape, the critical security issues in version 2 necessitated the complete redesign of the protocol from the ground up. SSL &lt;strong&gt;version 3.0&lt;/strong&gt; was then released in 1996.&lt;/p&gt;

&lt;h2&gt;
  
  
  Birth and timeline of TLS
&lt;/h2&gt;

&lt;p&gt;In 1996, a working group was formed at IETF(Internet Engineering Task Force) to standardize SSL. This is after an agreement where both Netscape and Microsoft would support the IETF taking over the protocol and standardizing it in an open process.&lt;/p&gt;

&lt;p&gt;Three years later(in 1999), the &lt;b&gt;1&lt;sup&gt;st&lt;/sup&gt;&lt;/b&gt; upgrade to SSL version 3.0 was published as &lt;strong&gt;TLS 1.0&lt;/strong&gt; in &lt;a href="https://datatracker.ietf.org/doc/html/rfc2246" rel="noopener noreferrer"&gt;RFC 2246&lt;/a&gt;. TLS 1.0 had minor changes to SSL 3.0 as &lt;a href="https://datatracker.ietf.org/doc/html/rfc2246#section-3" rel="noopener noreferrer"&gt;stated in the RFC&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;differences between this protocol and SSL 3.0 are not dramatic, but they are significant enough that TLS 1.0 and SSL 3.0 do not interoperate&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tiem Dierks, an editor in RFC 2246, later on says in &lt;a href="https://tim.dierks.org/2014/05/security-standards-and-name-changes-in.html" rel="noopener noreferrer"&gt;his blog&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As a part of the horsetrading, we had to make some changes to SSL 3.0 (so it wouldn't look the IETF was just rubberstamping Netscape's protocol), and we had to rename the protocol (for the same reason). And thus was born TLS 1.0 (which was really SSL 3.1).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;TLS was born as from version 1.0 and today it is still being used as the standard encryption layer on HTTP protocol. Countable TLS vesions have being released since then i.e &lt;em&gt;TLS 1.0, TLS 1.2&lt;/em&gt; and &lt;em&gt;TLS 1.3&lt;/em&gt;. The most recent version(as of 2023) is TLS 1.3 which was released in August 2018.&lt;/p&gt;

&lt;p&gt;Earlier versions of TLS have been overshadowed with the recent and more bullet-proof versions. In October 2018, Apple, Google, Microsoft, and Mozilla jointly announced they would deprecate TLS 1.0 and 1.1 in March 2020. TLS 1.0 and 1.1 were formally deprecated in &lt;a href="https://datatracker.ietf.org/doc/html/rfc8996" rel="noopener noreferrer"&gt;RFC 8996&lt;/a&gt; in March 2021.&lt;/p&gt;

&lt;p&gt;SSL has never received an update since its SSL 3.0 release in 1996 and hence new vulnerabilities have been found with the evolved cyber security attacks. SSL 3.0 was deprecated in June 2015 in &lt;a href="https://datatracker.ietf.org/doc/html/rfc7568" rel="noopener noreferrer"&gt;RFC 7568&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is the encryption protocol layer history summarized in a table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;protocol&lt;/th&gt;
&lt;th&gt;published&lt;/th&gt;
&lt;th&gt;status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SSL 1.0&lt;/td&gt;
&lt;td&gt;unpublished&lt;/td&gt;
&lt;td&gt;unpublished&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSL 2.0&lt;/td&gt;
&lt;td&gt;1995&lt;/td&gt;
&lt;td&gt;Deprecated in 2011 (&lt;a href="https://datatracker.ietf.org/doc/html/rfc6176" rel="noopener noreferrer"&gt;RFC 6176&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSL 3.0&lt;/td&gt;
&lt;td&gt;1996&lt;/td&gt;
&lt;td&gt;Deprecated in 2015 (&lt;a href="https://datatracker.ietf.org/doc/html/rfc7568" rel="noopener noreferrer"&gt;RFC 7568&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TLS 1.0&lt;/td&gt;
&lt;td&gt;1999&lt;/td&gt;
&lt;td&gt;Deprecated in 2021 (&lt;a href="https://datatracker.ietf.org/doc/html/rfc8996" rel="noopener noreferrer"&gt;RFC 8996&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TLS 1.1&lt;/td&gt;
&lt;td&gt;2006&lt;/td&gt;
&lt;td&gt;Deprecated in 2021 (&lt;a href="https://datatracker.ietf.org/doc/html/rfc8996" rel="noopener noreferrer"&gt;RFC 8996&lt;/a&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TLS 1.2&lt;/td&gt;
&lt;td&gt;2008&lt;/td&gt;
&lt;td&gt;In use since 2008&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TLS 1.3&lt;/td&gt;
&lt;td&gt;2018&lt;/td&gt;
&lt;td&gt;In use since 2018&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Despite that SSL was replaced more than 20 years ago by TLS, many people still use the term SSL when they mean TLS.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Let's connect on &lt;a href="https://twitter.com/intent/user?screen_name=smitterhane" rel="noopener noreferrer"&gt;twitter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web</category>
      <category>webdev</category>
      <category>cybersecurity</category>
      <category>web3</category>
    </item>
    <item>
      <title>Deftly🦅 Handle exceptions in Node/Express Application</title>
      <dc:creator>Smitter</dc:creator>
      <pubDate>Fri, 31 Mar 2023 09:39:27 +0000</pubDate>
      <link>https://dev.to/smitterhane/deftly-handle-exceptions-in-nodeexpress-application-208m</link>
      <guid>https://dev.to/smitterhane/deftly-handle-exceptions-in-nodeexpress-application-208m</guid>
      <description>&lt;p&gt;&lt;small&gt;Welcome to &lt;b&gt;part 4&lt;/b&gt;. Follow along this series to build a 3-tier Login System implementing core features required of an effective and usable authentication system.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Summary:&lt;/strong&gt; In this tutorial, you will learn to create user-defined exceptions and handle these exceptions (or other unexpected events) as they occur through proper error handling in express&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note 🔔&lt;/strong&gt;&lt;/em&gt;:&lt;br&gt;&lt;br&gt;
&lt;em&gt;If you would like to jump ahead to the finally built authentication system, the complete Git Repo can be found on &lt;a href="https://github.com/hane-smitter/MERN_login_system" rel="noopener noreferrer"&gt;Github&lt;/a&gt;✩.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With how Javascript engine works, when a runtime error occurs, execution will stop and an error is generated. In technical parlance, &lt;em&gt;a runtime error causes new &lt;code&gt;Error&lt;/code&gt; object to be &lt;strong&gt;created and thrown&lt;/strong&gt;&lt;/em&gt;. In such an event, the rest of code is not executed.&lt;/p&gt;

&lt;p&gt;Well, that is how Javascripts handles itself when you &lt;em&gt;write bad code&lt;/em&gt;. Likewise, the application you are building needs to handle itself when it receives &lt;em&gt;bad input&lt;/em&gt;. Or when other unexpected events occur, including a runtime error.&lt;/p&gt;

&lt;p&gt;For example, division by zero is not an error in Javascript. But logic in your application requires that it should be. The &lt;code&gt;throw&lt;/code&gt; keyword allows you to stop javascript execution whilst generating a custom defined exception. As you generate exception, you should handle it and communicate back to the user with succinct information about what went wrong.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Table of Contents&lt;/b&gt;&lt;br&gt;
  &lt;/p&gt;
&lt;ol&gt;

    &lt;li&gt;

      What we will do
      &lt;ol&gt;

        &lt;li&gt;

Create custom error constructors
        &lt;/li&gt;

&lt;li&gt;

Create error/exception handlers
        &lt;/li&gt;

&lt;li&gt;

Configure error handlers in express application
        &lt;/li&gt;

&lt;li&gt;

Error Handling in action
      &lt;/li&gt;

&lt;/ol&gt;

    &lt;/li&gt;

    &lt;li&gt;Final thoughts&lt;/li&gt;


&lt;/ol&gt;

&lt;p id="what-we-will-do"&gt;Outline of &lt;b&gt;what we will do&lt;/b&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create custom error constructors.&lt;/li&gt;
&lt;li&gt;Create error/exception handlers.&lt;/li&gt;
&lt;li&gt;Configure express application to use custom error handlers.&lt;/li&gt;
&lt;li&gt;Error Handling in action.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In an error flow control, we will &lt;code&gt;throw&lt;/code&gt; using a &lt;em&gt;custom error constructor&lt;/em&gt;, to generate a &lt;strong&gt;user-defined exception&lt;/strong&gt;. The generated exception will be processed in &lt;em&gt;error handler&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Directory structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;📂server/
└── 📂src/
    ├── 📄index.js
    └── 📂config/
&lt;span class="gi"&gt;+       ├── 📂errors/
+       │   ├── 📄AuthorizationError.js
+       │   └── 📄CustomError.js
+       └── 📂exceptionHandlers/
+           └── 📄handler.js
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the structure in regard to the &lt;code&gt;src&lt;/code&gt; directory that contains our code. We will update these files with code to provide the logic we want to achieve. You can always double check to create these files in their correct locations.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Create custom error constructors
&lt;/h2&gt;

&lt;p&gt;Certainly you may be familiar with the in-built Error constructor, &lt;em&gt;i.e &lt;code&gt;new Error()&lt;/code&gt;&lt;/em&gt;, which actually creates an Error object.&lt;/p&gt;

&lt;p&gt;Let's create custom error constructor which is a superset of the in-built &lt;code&gt;Error&lt;/code&gt;, by which we will be able to add more properties to the created Error Object we will need later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First&lt;/strong&gt;, open the file: &lt;strong&gt;&lt;code&gt;CustomError.js&lt;/code&gt;&lt;/strong&gt;. According to the directory structure for this tutorial(refer above), it should be at the path: &lt;code&gt;server/src/config/errors/&lt;/code&gt;. Create the constituent directories if you do not have.&lt;br&gt;&lt;br&gt;
Inside the opened file, paste in the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Custom Error Constructor
     * @param {any} [message] - Optional error payload
     * @param {number} [statusCode] - Optional error http status code
     * @param {string} [feedback=""] - Optional feedback message you want to provide
     */&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;feedback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CustomError&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cause&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;feedback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feedback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The snippet above simply creates a class that extends base &lt;code&gt;Error&lt;/code&gt; class that is in-built to javascript. We define a constructor that passes &lt;code&gt;message&lt;/code&gt; as first argument to the base class(&lt;em&gt;By calling &lt;code&gt;super(message)&lt;/code&gt;&lt;/em&gt;), and adds additional properties to the result &lt;em&gt;Error Object&lt;/em&gt; when the class is instantiated.&lt;/p&gt;

&lt;p&gt;To cause a &lt;em&gt;user-defined exception&lt;/em&gt; in our application, we will &lt;code&gt;throw CustomError()&lt;/code&gt;. Arguments can be passed to define properties on created &lt;em&gt;Error object&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second&lt;/strong&gt;, open/create the file: &lt;strong&gt;&lt;code&gt;AuthorizationError.js&lt;/code&gt;&lt;/strong&gt;. Expected to be at the path: &lt;code&gt;server/src/config/errors/&lt;/code&gt;(refer above).&lt;br&gt;&lt;br&gt;
Paste the following code in the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CustomError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./CustomError&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Authorization Error Constructor
     * @param {any} [message] - Error payload
     * @param {number} [statusCode] - Status code. Defaults to `401`
     * @param {string} [feedback=""] - Feedback message
     * @param {object} [authParams] - Authorization Parameters to set in `WWW-Authenticate` header
     */&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;feedback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;feedback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Call parent constructor with args&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorizationError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;authParams&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authHeaders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;WWW-Authenticate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;stringifyAuthParams&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Private Method to convert object `key: value` to string `key=value`&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;stringifyAuthParams&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;realm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;others&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authParams&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nx"&gt;realm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;realm&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;realm&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`realm=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;realm&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;otherParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;others&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;otherParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nx"&gt;otherParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;authParam&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Delete other `realm(s)` if exists&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authParam&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;realm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;others&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;authParam&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;comma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="c1"&gt;// If is last Item then no comma&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;comma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;` &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;authParam&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authParams&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;authParam&lt;/span&gt;&lt;span class="p"&gt;]}${&lt;/span&gt;&lt;span class="nx"&gt;comma&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;AuthorizationError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;AuthorizationError&lt;/code&gt; is an error intended to be generated due to &lt;em&gt;insufficient authentication&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
It is extends the &lt;code&gt;CustomError&lt;/code&gt; class adding extra properties as well. &lt;strong&gt;Majorly&lt;/strong&gt;, the constructor for this error class has a &lt;code&gt;statusCode&lt;/code&gt; that defaults to &lt;code&gt;401&lt;/code&gt; which is passed to base class(&lt;code&gt;CustomError&lt;/code&gt;) when calling &lt;code&gt;super()&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Also, we have defined &lt;code&gt;#stringifyAuthParams()&lt;/code&gt; private method to convert &lt;code&gt;authParams&lt;/code&gt; object parameter to a list of comma separated strings of format &lt;code&gt;key=value&lt;/code&gt;. The formatted string is used to generate value for the &lt;code&gt;authheaders&lt;/code&gt; property.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;New to private methods in javascript classes? Read more &lt;a href="https://dev.to/smitterhane/private-class-fields-in-javascript-es2022-3b8"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Error object created using this class will be processed by error handler to produce a &lt;strong&gt;401 - Unauthorized&lt;/strong&gt; Error response that observes the web specifications, which require a &lt;em&gt;response due to failed authentication include a &lt;code&gt;WWW-Authenticate&lt;/code&gt; header&lt;/em&gt;. Learn more &lt;a href="https://www.rfc-editor.org/rfc/rfc2617#page-3" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Create error/exception handlers
&lt;/h2&gt;

&lt;p&gt;Here we will create handlers for unexpected events that occur in our application. These handlers are important to prevent a running program from shutting down unceremoniously to its users. Furthermore they provide concise information to the user about what went wrong.&lt;br&gt;&lt;br&gt;
We will create &lt;strong&gt;two&lt;/strong&gt; error handlers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;404 case handler &lt;em&gt;i.e handler called when http request on a path that does not exist hits our server.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;General exception handler &lt;em&gt;i.e handler called when exceptions are generated from anywhere in our application&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Open the file: &lt;strong&gt;&lt;code&gt;handler.js&lt;/code&gt;&lt;/strong&gt;. According to the directory structure for this tutorial(refer above), it should be at the path: &lt;code&gt;server/src/config/exceptionHandlers/&lt;/code&gt;. Create the constituent directories if you do not have.&lt;/p&gt;

&lt;p&gt;Paste the following code inside the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 404 Error Handler&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;LostErrorHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Resource not found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Exception Handler&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AppErrorHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorizationError&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Sets headers available in Authorization Error object&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authHeaders&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// `cause` is a custom property on error object&lt;/span&gt;
    &lt;span class="c1"&gt;// that may contain any data type&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;cause&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;providedFeedback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;feedback&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// respond with error and conditionally include feedback if provided&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="nx"&gt;providedFeedback&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;feedback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;providedFeedback&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LostErrorHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AppErrorHandler&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have defined &lt;strong&gt;two&lt;/strong&gt; functions here taking the signature of express middleware.&lt;br&gt;&lt;br&gt;
&lt;em&gt;The first one&lt;/em&gt;, &lt;strong&gt;&lt;code&gt;LostErrorHandler()&lt;/code&gt; function&lt;/strong&gt; is the &lt;em&gt;404 case handler&lt;/em&gt;. Importantly, it sets a &lt;code&gt;404&lt;/code&gt; status code on the response(&lt;code&gt;res&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And the second one&lt;/em&gt;, &lt;strong&gt;&lt;code&gt;AppErrorHandler()&lt;/code&gt; function&lt;/strong&gt; has 4 parameters which distinguishes it as an &lt;strong&gt;express error middleware&lt;/strong&gt;. This is the &lt;em&gt;General exception handler&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Properties are available on the &lt;code&gt;err&lt;/code&gt; parameter of the &lt;strong&gt;&lt;code&gt;AppErrorHandler()&lt;/code&gt; function&lt;/strong&gt; depending on &lt;em&gt;error constructor that created the Error object&lt;/em&gt;. For example we see this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorizationError&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authHeaders&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We know &lt;code&gt;err&lt;/code&gt; is an &lt;em&gt;authorization error&lt;/em&gt; object when we &lt;code&gt;throw&lt;/code&gt; an exception using the custom &lt;code&gt;AuthorizationError&lt;/code&gt; constructor, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthorizationError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create an Error object that contains &lt;code&gt;authorizationError&lt;/code&gt; property set to &lt;code&gt;true&lt;/code&gt;. Also includes &lt;code&gt;authHeaders&lt;/code&gt; property e.t.c.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Configure express application to use custom error handlers.
&lt;/h2&gt;

&lt;p&gt;The last step is to configure the express application to use error handlers we have created. For this, open &lt;code&gt;index.js&lt;/code&gt; which is the entrypoint to our application. This file should be located at &lt;code&gt;server/src/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add the following code to this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;AppErrorHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;LostErrorHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./config/exceptionHandlers/handler.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/* 
  1. INITIALIZE EXPRESS APPLICATION 🏁
*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/* 
  2. APPLICATION MIDDLEWARES AND CUSTOMIZATIONS 🪛
*/&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="cm"&gt;/* 
  3. APPLICATION ROUTES 🛣️
*/&lt;/span&gt;
&lt;span class="c1"&gt;// Test route&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello Welcome to API🙃 !!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="cm"&gt;/* 
  4. APPLICATION ERROR HANDLING 🚔
*/&lt;/span&gt;
&lt;span class="c1"&gt;// Handle unregistered route for all HTTP Methods&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Forward to next closest middleware&lt;/span&gt;
    &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LostErrorHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 404 error handler middleware&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppErrorHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// General app error handler&lt;/span&gt;

&lt;span class="cm"&gt;/* 
  5. APPLICATION BOOT UP 🖥️
*/&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`App running on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;strong&gt;fourth part&lt;/strong&gt; of the snippet above, we have configured our app to handle &lt;em&gt;404 error case&lt;/em&gt; and &lt;em&gt;general errors&lt;/em&gt; that may occur from anywhere in the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A few vital things to note:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We have added error handling at &lt;em&gt;part4&lt;/em&gt; after routes for the application have been registered at &lt;em&gt;part3&lt;/em&gt;. This way, incase of incoming request requiring resource on non-existent path, a 404 error handler will catch and process this error. And it is called &lt;strong&gt;only after no route has been matched in the routes registered at &lt;em&gt;part3&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  We have added &lt;em&gt;General error handler&lt;/em&gt; middleware as the &lt;strong&gt;last-most&lt;/strong&gt; middleware in the express middleware chain. It is important to declare it last so that any unhandled errors that occur before it, can be captured and handled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hence when it comes to effective error handling in express, &lt;strong&gt;order of placement of the error handlers is important&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Cheers!🥂. Up to this point, your program should be equipped to gracefully handle unexpected errors that may occur in route handlers and middlewares.&lt;/p&gt;

&lt;p&gt;Infact, let us test run by introducing error in our application.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Error Handling in action
&lt;/h2&gt;

&lt;p&gt;To test Error Handling in our application, let's add another test route. So once again, open &lt;code&gt;index.js&lt;/code&gt; file which should be found at the path: &lt;code&gt;server/src/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Edit &lt;em&gt;part 3 this file&lt;/em&gt; to add a new route, like shown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CustomError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./config/errors/CustomError.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="cm"&gt;/* 
  3. APPLICATION ROUTES 🛣️
*/&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="c1"&gt;// Test Crash route&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/boom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Oops! matters are chaotic💥&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have added a new route,(&lt;code&gt;/boom&lt;/code&gt;) and its route handler.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: &lt;em&gt;The route handler is written with the signature of express middleware, i.e it takes three parameters. Writing as an express middleware enables us to pass any errors generated here to the application's error handler we have configured using the &lt;code&gt;next()&lt;/code&gt; function, which is available as the third parameter in the route handler.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This route handler &lt;code&gt;throw&lt;/code&gt;s an error inside a &lt;code&gt;try...catch&lt;/code&gt; construct, using our predefined &lt;em&gt;&lt;code&gt;CustomError&lt;/code&gt; class&lt;/em&gt;. We have passed a &lt;strong&gt;string message&lt;/strong&gt; and a &lt;strong&gt;number for the HTTP status code&lt;/strong&gt; we would like to return in the response. This will create an error object that will be caught by &lt;code&gt;catch()&lt;/code&gt;. Inside the &lt;code&gt;catch(){...}&lt;/code&gt; block, we simply forward the caught error to our configured error handling middleware with a single line of code: &lt;code&gt;next(error)&lt;/code&gt;. And that is it🦸.&lt;/p&gt;

&lt;p&gt;Run the program. And when you run it, open your browser or any other client you prefer &lt;em&gt;e.g postman&lt;/em&gt;. Then navigate to the route that throws an error, &lt;em&gt;i.e &lt;a href="http://localhost:8000/boom" rel="noopener noreferrer"&gt;http://localhost:8000/boom&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You should see that the error thrown in our application was handled deftly by error handler configured. And of course, our application is still running. It did not shut down.&lt;br&gt;&lt;br&gt;
Notice that the &lt;strong&gt;string message&lt;/strong&gt; and &lt;strong&gt;HTTP status code&lt;/strong&gt; passed to &lt;code&gt;CustomError&lt;/code&gt; constructor are included in the &lt;em&gt;response body and header&lt;/em&gt; respectively:&lt;/p&gt;


  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fds9uwlm8knqfqsxy2m72.png" alt="Internally handled error response" width="453" height="248"&gt;HTTP request/response made with &lt;code&gt;curl&lt;/code&gt;
  

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Well that is how you handle exceptions that can occur while running route handlers and middlewares in express. Possibly this is a compelling way since &lt;strong&gt;it reduces boiler plate code you need to write in the &lt;code&gt;catch(){...}&lt;/code&gt; block&lt;/strong&gt;, especially in the route handlers. Additionally, &lt;em&gt;"regular code"&lt;/em&gt; in route handlers is separated from &lt;em&gt;"error handling code"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Using &lt;em&gt;Custom Error constructors&lt;/em&gt; to create &lt;em&gt;Error objects&lt;/em&gt; when we &lt;code&gt;throw&lt;/code&gt; is important for providing additional properties to the Error generated. The error handler can then obtain the properties on an error and respond to a user with concise information about what went wrong.&lt;/p&gt;

&lt;p&gt;In the example where we test to see error-handling in action, we wrapped logic for the route handler inside &lt;code&gt;try...catch&lt;/code&gt; construct. If all we are going to write is &lt;strong&gt;synchronous code only&lt;/strong&gt;, &lt;em&gt;then we &lt;strong&gt;do not need to explicitly call &lt;code&gt;next(error)&lt;/code&gt; function&lt;/strong&gt; with the error caught&lt;/em&gt; which is the case inside &lt;code&gt;catch(){...}&lt;/code&gt; block. Therefore we can &lt;code&gt;throw&lt;/code&gt; without the &lt;code&gt;try...catch&lt;/code&gt; construct and Express will automatically pass the error to error-handling middleware. &lt;small&gt;&lt;em&gt;But it is worthy to avoid writing code that is magical🪄.&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;However if you write &lt;strong&gt;asynchronous operations&lt;/strong&gt;, you must call &lt;code&gt;next(error)&lt;/code&gt; function with the error returned, &lt;em&gt;so it may be caught by the error-handling middleware&lt;/em&gt;. For example we may write a route handler that has asynchronous operation like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/boom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iAlwaysReject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Operation failed!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;iAlwaysReject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Asynchronous OP&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Explicitly call next&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;em&gt;In Express 5 and above, asynchronous operations that reject or throw an error will call &lt;code&gt;next(error)&lt;/code&gt; function automatically with the thrown error or the rejected value. If no rejected value is provided, &lt;code&gt;next&lt;/code&gt; will be called with a default &lt;code&gt;Error&lt;/code&gt; object provided by the Express router.&lt;/em&gt; With above example, it means you can await without wrapping in &lt;code&gt;try...catch&lt;/code&gt; construct nor calling &lt;code&gt;next(error)&lt;/code&gt; explicitly. But why write code that is magical? 🤷‍♂️&lt;/p&gt;

&lt;p&gt;Express ships with a default error handler. Of course it is not feature rich as you may want to create your own. I guess it is good enough to get you started.&lt;/p&gt;

&lt;p&gt;Do you have other opinions? Drop them in the comment section🕳🤾. Meanwhile, I hope you found the article useful and...peace✌️.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Follow me &lt;a href="https://twitter.com/intent/user?screen_name=smitterhane" rel="noopener noreferrer"&gt;@twitter&lt;/a&gt;. I share content that may be helpful to you😃.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>express</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Keep cors error under control⚒️</title>
      <dc:creator>Smitter</dc:creator>
      <pubDate>Sun, 19 Mar 2023 09:19:11 +0000</pubDate>
      <link>https://dev.to/smitterhane/keep-cors-error-under-control-2099</link>
      <guid>https://dev.to/smitterhane/keep-cors-error-under-control-2099</guid>
      <description>&lt;p&gt;&lt;small&gt;Welcome to &lt;b&gt;part 3&lt;/b&gt;. Follow along this series to develop a &lt;em&gt;feature-packed&lt;/em&gt; 3-tier Authentication System outlined in successive parts.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Summary:&lt;/strong&gt; In this article we will learn to configure an express backend application to understand CORS Protocol&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note 🔔&lt;/strong&gt;&lt;/em&gt;:&lt;br&gt;&lt;br&gt;
&lt;em&gt;If you would like to jump ahead to the final Authentication System put together, the complete Git Repo can be found on &lt;a href="https://github.com/hane-smitter/MERN_login_system" rel="noopener noreferrer"&gt;Github&lt;/a&gt;✩.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's start here with an example case.&lt;br&gt;&lt;br&gt;
You have built a stunning user interface 😎. Now you are ready to pull data from external API and inject in the UI for display. You have scripts that make HTTP requests to API. But something is standing in the way 🛑. The console blazes fiery red and ranting🗣️:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhgpc1u099l1p7bxyjv1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhgpc1u099l1p7bxyjv1.png" alt="access-control-allow-origin header not present" width="556" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tellingly, you have run into &lt;em&gt;CORS error&lt;/em&gt;.&lt;/p&gt;


&lt;b&gt;Table of Contents&lt;/b&gt;
&lt;ol&gt;
&lt;li&gt;Why CORS Error?&lt;/li&gt;
&lt;li&gt;What is CORS?&lt;/li&gt;
&lt;li&gt;Enable CORS&lt;/li&gt;
&lt;li&gt;Enable CORS for credentialed requests&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why CORS Error?
&lt;/h2&gt;

&lt;p&gt;Using the example above, this error occurs because UI is loaded on a different port, &lt;em&gt;i.e &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/em&gt; and the scripts in it are requesting to a different port &lt;em&gt;i.e &lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt;&lt;/em&gt;. So scripts are making cross-origin requests. Well, &lt;em&gt;Same-origin&lt;/em&gt; policy is violated! And therefore the browser blocks such a request 👊.&lt;br&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; Two URLs have the &lt;strong&gt;same origin&lt;/strong&gt; if the &lt;strong&gt;protocol&lt;/strong&gt;, &lt;strong&gt;port&lt;/strong&gt; (if specified), and &lt;strong&gt;host&lt;/strong&gt; are the same for both&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It is a security motive that browsers restrict cross-origin HTTP requests initiated from scripts. &lt;strong&gt;"XMLHttpRequest"&lt;/strong&gt; and &lt;strong&gt;"Fetch"&lt;/strong&gt; are browser APIs that adhere to &lt;em&gt;same-origin policy&lt;/em&gt;. This means that a web application using these APIs can &lt;em&gt;only&lt;/em&gt; request resources from &lt;em&gt;the same origin the application was loaded from&lt;/em&gt;. In layman's language, &lt;em&gt;&lt;strong&gt;scripts in a web page can "peacefully" request to the URL shown in the address bar&lt;/strong&gt; without being hurled with confrontations by the browser&lt;/em&gt;. This way, the nightmarish &lt;em&gt;CORS error&lt;/em&gt; is well tucked out of sight.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;But with special configurations, cross-origin requests can succeed&lt;/strong&gt;. However, these configurations need to be done on the backend rather than the frontend. These configurations are what we will be looking at in this article.&lt;/p&gt;



&lt;p&gt;So,&lt;/p&gt;
&lt;h2&gt;
  
  
  What is CORS?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;CORS&lt;/em&gt; is an abbreviation for &lt;em&gt;Cross-Origin Resource Sharing&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;It is a standard that allows a server to moderate &lt;em&gt;same-origin policy&lt;/em&gt; in browsers&lt;/strong&gt;, so cross-site requests made to it can be allowed. And this involves sending appropriate CORS headers that will be verified in the browser.&lt;/p&gt;

&lt;p&gt;Ultimately this means that if you run into a CORS error, the fix lies in backend configuration.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;This is how we organize the nodejs project.&lt;/p&gt;

&lt;p&gt;Start by creating a &lt;code&gt;server&lt;/code&gt; directory and change into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"server"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nv"&gt;$d&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;code&gt;server&lt;/code&gt; directory, run &lt;code&gt;npm init -y&lt;/code&gt; to create a &lt;code&gt;package.json&lt;/code&gt; file. Add/edit the &lt;code&gt;package.json&lt;/code&gt; file to include the following script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node src/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;npm install express --save&lt;/code&gt; to install express web framework.&lt;br&gt;&lt;br&gt;
Then create &lt;code&gt;src&lt;/code&gt; directory(&lt;code&gt;mkdir src&lt;/code&gt;) inside this &lt;code&gt;server&lt;/code&gt; directory. Below is the overall directory structure.&lt;/p&gt;
&lt;h3&gt;
  
  
  Directory structure
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;📂server/
    ├── 📄package.json
    └── 📂src/
        ├── 📄index.js
&lt;span class="gi"&gt;+       └── 📂config/
+            └── 📂cors/
+                └── 📄cors.js
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the structure with focus on the &lt;code&gt;src&lt;/code&gt; directory. The &lt;code&gt;src&lt;/code&gt; directory will contain files with code we write for our project. We will add code in these files as we progress through the article. You can always double check to create these files in their correct locations.&lt;/p&gt;
&lt;h2&gt;
  
  
  Enable CORS
&lt;/h2&gt;

&lt;p&gt;We are going to configure CORS protocol on our express backend. The CORS protocol simply consists of a set of headers that indicates whether a response can be shared with the origin that requested.&lt;/p&gt;

&lt;p&gt;The set of headers that can be set on response to a CORS request are listed &lt;a href="https://fetch.spec.whatwg.org/#http-responses" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To reduce the work of setting these headers manually, we will use an npm library called &lt;a href="https://npmjs.com/package/cors" rel="noopener noreferrer"&gt;cors&lt;/a&gt;. So be sure to install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;cors &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open the entry point of our application file, i.e &lt;code&gt;index.js&lt;/code&gt;, located at &lt;code&gt;server/src/&lt;/code&gt;(refer). Add the &lt;code&gt;cors&lt;/code&gt; middleware as shown in section &lt;code&gt;2&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/* 
   1. INITIALIZE EXPRESS APPLICATION 🏁
*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/* 
   2. APPLICATION MIDDLEWARES AND CUSTOMIZATIONS 🪛
*/&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Enable Cross Origin Resource Sharing&lt;/span&gt;

&lt;span class="cm"&gt;/* 
   3. APPLICATION ROUTES 🛣️
*/&lt;/span&gt;

&lt;span class="cm"&gt;/* 
   4. APPLICATION ERROR HANDLING 🚔
*/&lt;/span&gt;

&lt;span class="cm"&gt;/* 
   5. APPLICATION BOOT UP 🖥️
*/&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App listening on port &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; The file &lt;code&gt;index.js&lt;/code&gt; has commented sections that are numbered. Some sections have logic defined in other parts of the series&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Yes, dead simple as that. The CORS headers will be set on HTTP response by the &lt;code&gt;cors()&lt;/code&gt; middleware when the browser sends a preflight request and the actual request.&lt;/p&gt;

&lt;p&gt;By default, &lt;code&gt;cors&lt;/code&gt; library sets &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; header with a wildcard(&lt;code&gt;*&lt;/code&gt;) value on the actual response.&lt;/p&gt;

&lt;p&gt;While this configuration of &lt;code&gt;cors&lt;/code&gt; library works, it will fail for Cross-Orign requests that include &lt;strong&gt;credentials&lt;/strong&gt;. Because a request that includes credentials(e.g &lt;code&gt;Cookie&lt;/code&gt; header), requires additional headers configured and that the headers are set explicitly(&lt;em&gt;not wildcarded&lt;/em&gt;). Therefore a header including a wildcard(&lt;code&gt;*&lt;/code&gt;) value will fail.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Credentials&lt;/strong&gt; are &lt;em&gt;cookies&lt;/em&gt;, &lt;em&gt;authorization headers&lt;/em&gt;, or &lt;em&gt;TLS client certificates&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Below is an example of a failure message when a request with credentials receives a response with &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; header set with a wildcard(&lt;code&gt;*&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fylgqt0vpbblcror0jrkm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fylgqt0vpbblcror0jrkm.png" alt="cors error" width="556" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

CORS error when &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; header is a wildcard




&lt;p&gt;&lt;code&gt;cors&lt;/code&gt; library needs additional configuration to set CORS headers appropriately for requests including credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable CORS for credentialed requests
&lt;/h2&gt;

&lt;p&gt;Like said earlier, credentialed requests are requests that include credentials, &lt;em&gt;i.e cookies,authorization headers or TLS client certificates&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The Authentication System we are building in this series will make use of cookies, so it's important to configure our backend to understand CORS protocol for credentialed requests.&lt;/p&gt;

&lt;p&gt;Open the file &lt;code&gt;cors.js&lt;/code&gt; which should be available at path &lt;code&gt;server/src/config/cors/&lt;/code&gt;(refer). Create the constituent directories if you do not have.&lt;/p&gt;

&lt;p&gt;Paste the following code inside &lt;code&gt;cors.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allowlist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:8000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;corsOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;allowlist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not allowed by CORS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;exposedHeaders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;WWW-Authenticate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;corsOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are allowing an &lt;code&gt;origin&lt;/code&gt; that is in &lt;code&gt;allowlist&lt;/code&gt; to access our API. Anything else is locked out; represented by passing a first argument to the &lt;code&gt;callback&lt;/code&gt; function: &lt;code&gt;callback(new Error("Not allowed by CORS"));&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
This cors option will &lt;strong&gt;explicitly set &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; response header&lt;/strong&gt; to the value of origin that has been cross-checked to exist in the &lt;code&gt;allowlist&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The next property option is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This cors option will &lt;strong&gt;set &lt;code&gt;Access-Control-Allow-Credentials&lt;/code&gt; response header to &lt;em&gt;true&lt;/em&gt;&lt;/strong&gt;, which basically gives an okay that our server will accept cookies from a cross-origin request(&lt;em&gt;Client application&lt;/em&gt;). The browser requires that this header exists in response to preflight request and before setting a cookie in client device as directed by &lt;code&gt;Set-cookie&lt;/code&gt; header of a response received.&lt;/p&gt;

&lt;p&gt;Then we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exposedHeaders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;WWW-Authenticate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This cors option will &lt;strong&gt;set &lt;code&gt;Access-Control-Expose-Headers&lt;/code&gt; response header to &lt;em&gt;WWW-Authenticate&lt;/em&gt;&lt;/strong&gt;.&lt;br&gt;
This is not mandatory but if you need to access this header(&lt;em&gt;or any other&lt;/em&gt;) with scripts running in the browser, then you need to set it.&lt;/p&gt;

&lt;p&gt;You may set other options you may need. The options we have set here should be able to understand the CORS protocol for credentialed requests.&lt;br&gt;&lt;br&gt;
What is remaining, is to include these options to the CORS middleware from the entry file of our application. Therefore open &lt;code&gt;index.js&lt;/code&gt; found at &lt;code&gt;server/src/&lt;/code&gt;(refer) and include these options in cors middleware as shown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;corsOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./config/cors/cors.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="cm"&gt;/* 
  2. APPLICATION MIDDLEWARES AND CUSTOMIZATIONS 🪛
*/&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;corsOptions&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Enable Cross Origin Resource Sharing&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congrats! This is the way! Now you can seamlessly make cross-site requests to your backend. Whether the request include credentials or not, CORS error should not intrude.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have looked at how to solve the CORS error you may run into, why it happens and what it really is. CORS error happens because the browser is reminding you to implement security in your application. We have seen how to we can configure CORS in an application that intends to work with requests that include credentials such as cookies.&lt;/p&gt;

&lt;p&gt;If you can control the backend, then you can fix CORS error, otherwise the fix is out of your control. You still may opt for hacky workarounds such as proxying requests.&lt;/p&gt;

&lt;p&gt;Fixing CORS error generally implies setting response headers.&lt;br&gt;&lt;br&gt;
These specific headers can be set using third-party libraries like &lt;a href="https://www.npmjs.com/package/cors" rel="noopener noreferrer"&gt;cors&lt;/a&gt; which is well battle-tested and effective in its job. However, you can still set the headers manually(&lt;small&gt;which creates room for errors 🤕&lt;/small&gt;).&lt;/p&gt;

&lt;p&gt;Did I leave out something? You can put it in the comments section.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;We can connect &lt;a href="https://twitter.com/intent/user?screen_name=smitterhane" rel="noopener noreferrer"&gt;@twitter&lt;/a&gt; and share ideas.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>postgres</category>
      <category>monitoring</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Database integration🪢 in node/express - A maintainable approach</title>
      <dc:creator>Smitter</dc:creator>
      <pubDate>Mon, 13 Mar 2023 06:00:00 +0000</pubDate>
      <link>https://dev.to/smitterhane/database-integration-in-nodeexpress-a-maintainable-approach-dfa</link>
      <guid>https://dev.to/smitterhane/database-integration-in-nodeexpress-a-maintainable-approach-dfa</guid>
      <description>&lt;p&gt;&lt;small&gt;Welcome to &lt;b&gt;part 2&lt;/b&gt;. Follow along this series to develop a &lt;em&gt;feature-packed&lt;/em&gt; 3-tier Authentication System outlined in successive parts.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Summary:&lt;/strong&gt; In this article, we learn to integrate a node application with a database using a promise-based ODM/ORM in a maintainable approach&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note 🔔&lt;/strong&gt;&lt;/em&gt;:&lt;br&gt;&lt;br&gt;
&lt;em&gt;A complete Repo of this series can be found on &lt;a href="https://github.com/hane-smitter/MERN_login_system" rel="noopener noreferrer"&gt;Github&lt;/a&gt;✩. Drop a star💫️ if you found it useful.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;b&gt;Table of Contents&lt;/b&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Directory Structure&lt;/li&gt;
&lt;li&gt;Create &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create &lt;code&gt;.env&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Install dependencies&lt;/li&gt;
&lt;li&gt;Set up database connection&lt;/li&gt;
&lt;li&gt;Run database connection in application&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Directory structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;📂server/
  ├── 📄package.json
  ├── 📄.env
  └── 📂src/
      ├── 📄index.js
      └── 📂dbConn/
           └── 📂mongoose/
               └── index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the structure with focus on the &lt;code&gt;src&lt;/code&gt; directory. The &lt;code&gt;src&lt;/code&gt; directory will contain files with code we write to run our application. We will add code in these files as we progress through the article. You can always double check to create these files in their correct locations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create &lt;code&gt;package.json&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;From the root level of &lt;code&gt;server&lt;/code&gt; directory, run the command &lt;code&gt;npm init -y&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
This command will generate a &lt;code&gt;package.json&lt;/code&gt; file inside our &lt;code&gt;server&lt;/code&gt; folder. Then edit the &lt;code&gt;package.json&lt;/code&gt; file to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"private"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node src/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nodemon src/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hane-smitter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MIT"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Importantly, change the &lt;code&gt;main&lt;/code&gt; property to point to &lt;code&gt;"src/index.js"&lt;/code&gt; which will be the entry file to our application. And also add &lt;code&gt;"start"&lt;/code&gt; and &lt;code&gt;"dev"&lt;/code&gt; scripts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node src/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nodemon src/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create &lt;code&gt;.env&lt;/code&gt; file
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;.env&lt;/code&gt; or &lt;em&gt;dotenv&lt;/em&gt; file is a &lt;strong&gt;key-value&lt;/strong&gt; text configuration file for defining application's environment constants.&lt;/p&gt;

&lt;p&gt;Let's create environment variables our application will use.&lt;/p&gt;

&lt;p&gt;To do this, create a &lt;code&gt;.env&lt;/code&gt; file at the &lt;code&gt;server&lt;/code&gt; directory root(refer) and add the following variable(s):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MONGODB_URI=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;MONGODB_URI&lt;/code&gt; is the MongoDB database connection string. It is currently empty but we will assign a value to it later on.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; Remember to &lt;strong&gt;include &lt;code&gt;.env&lt;/code&gt; file to your &lt;code&gt;.gitignore&lt;/code&gt;&lt;/strong&gt;, should you initialize a git project. &lt;code&gt;.env&lt;/code&gt; file is meant to be private to you and should not be shared outside of your local repository.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Install dependencies
&lt;/h2&gt;

&lt;p&gt;We have initialized our project with &lt;code&gt;package.json&lt;/code&gt; file. We can now add dependencies from the &lt;a href="https://npmjs.com" rel="noopener noreferrer"&gt;npm&lt;/a&gt; registry that we will need in this project.&lt;/p&gt;

&lt;p&gt;We will use the following dependencies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/express" rel="noopener noreferrer"&gt;Express&lt;/a&gt; - A web framework written in JavaScript and hosted within the Node.js runtime environment, to generally help us handle requests coming to our server.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/mongoose" rel="noopener noreferrer"&gt;Mongoose&lt;/a&gt; - An object modelling tool for MongoDB to allow us to enforce a specific mongoDB schema from our application.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/dotenv" rel="noopener noreferrer"&gt;Dotenv&lt;/a&gt; - To load environment variables declared in &lt;code&gt;.env&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://npmjs.com/package/nodemon" rel="noopener noreferrer"&gt;Nodemon&lt;/a&gt; - To restart our server after file changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore install the dependencies with terminal opened from the root of &lt;code&gt;server&lt;/code&gt; directory by running the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;mongoose express dotenv &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then install &lt;code&gt;nodemon&lt;/code&gt; as a &lt;strong&gt;development dependency&lt;/strong&gt;, which means that we only need &lt;code&gt;nodemon&lt;/code&gt; during development time of our application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;nodemon &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Set up database connection
&lt;/h2&gt;

&lt;p&gt;In this step, we will connect to a MongoDB database hosted in the cloud, &lt;em&gt;i.e &lt;strong&gt;MongoDB Atlas&lt;/strong&gt;&lt;/em&gt;. If you do not have MongoDB installed locally on your machine, you can still hit the ground running with the hosted version👍.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First&lt;/strong&gt;, you will &lt;em&gt;need a connection string connecting to MongoDB&lt;/em&gt; as a cloud service. Create &lt;a href="https://account.mongodb.com/account/register" rel="noopener noreferrer"&gt;MongoDB Atlas&lt;/a&gt; account or &lt;a href="https://account.mongodb.com/account/login" rel="noopener noreferrer"&gt;login&lt;/a&gt; if you already have one. Then follow this &lt;a href="https://www.mongodb.com/docs/guides/atlas/connection-string/" rel="noopener noreferrer"&gt;guide&lt;/a&gt; to obtain your connection string.&lt;/p&gt;

&lt;p&gt;Once you have your connection string, open the &lt;code&gt;.env&lt;/code&gt; file and set the &lt;code&gt;MONGODB_URI&lt;/code&gt; like shown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;MONGODB_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mongodb+srv://&amp;lt;user&amp;gt;:&amp;lt;password&amp;gt;@sample.host/&amp;lt;db_name&amp;gt;?retryWrites&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&amp;amp;w&lt;span class="o"&gt;=&lt;/span&gt;majority
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can as well substitute with URI of local mongoDB installation. In this case your connection URI will look like: &lt;code&gt;mongodb://127.0.0.1:27017/&amp;lt;dbname&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then&lt;/strong&gt;, open terminal at &lt;code&gt;server&lt;/code&gt; directory root, create &lt;code&gt;src&lt;/code&gt; directory and change into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;src
&lt;span class="nb"&gt;cd &lt;/span&gt;src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;src&lt;/code&gt; is where code we write for our backend will reside.&lt;/p&gt;

&lt;p&gt;We will start by creating a file for our MongoDB connection.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Open/create &lt;code&gt;index.js&lt;/code&gt; file located at &lt;code&gt;server/src/dbConn/mongoose/&lt;/code&gt;(refer). Paste the following code in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Pull in environment variable&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connURI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MONGODB_URI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;strictQuery&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bufferCommands&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Disable buffering&lt;/span&gt;

&lt;span class="c1"&gt;// Connect to MongoDB and store connection in variable&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connURI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ETIMEDOUT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`----&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;----`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// console.log(err);&lt;/span&gt;
        &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connURI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`----&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;----`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above is straight-forward where we get connection string to our MongoDB database from the environment variable: &lt;code&gt;const connURI = process.env.MONGODB_URI;&lt;/code&gt;. We connect to it and store the conection in &lt;code&gt;db&lt;/code&gt; variable. We chain &lt;code&gt;catch()&lt;/code&gt; to handle error that may occur during the connection. Though we don't handle the &lt;em&gt;"fulfilled"&lt;/em&gt; case here. And if a &lt;strong&gt;timeout&lt;/strong&gt; error occurs, we retry to connect. Otherwise we just log the error to the terminal.&lt;/p&gt;

&lt;p&gt;Finally we default export the mongoose connection stored in &lt;code&gt;db&lt;/code&gt; variable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run database connection in application
&lt;/h2&gt;

&lt;p&gt;Here we need to include database connection in our entry file where it will be actually run on application start-up. And we synchronize the successful database connection to server listening on &lt;em&gt;Tcp port&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Open/create the entry file to our application. This file should be &lt;code&gt;index.js&lt;/code&gt; located at &lt;code&gt;server/src/&lt;/code&gt;(refer). Remember that this is the file referenced by the &lt;code&gt;"main"&lt;/code&gt; property in our &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Add the following code inside this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbConnection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./dbConn/mongoose&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/* 
   1. INITIALIZE EXPRESS APPLICATION 🏁
 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/* 
   2. APPLICATION MIDDLEWARES AND CUSTOMIZATIONS 🪛
 */&lt;/span&gt;

&lt;span class="cm"&gt;/* 
   3. APPLICATION ROUTES 🛣️
 */&lt;/span&gt;
&lt;span class="c1"&gt;// Test route&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello Welcome to API🙃 !!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="cm"&gt;/* 
   4. APPLICATION ERROR HANDLING 🚔
 */&lt;/span&gt;

&lt;span class="cm"&gt;/* 
   5. APPLICATION BOOT UP 🖥️
 */&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ready&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`App running on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;dbConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;---Database is connected !!---&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ready&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; The file &lt;code&gt;index.js&lt;/code&gt; has commented sections that are numbered. Each section will have its logic added in other parts of the series&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the snippet above, we have imported &lt;code&gt;dotenv&lt;/code&gt; at the &lt;em&gt;very top&lt;/em&gt; to load variables from &lt;code&gt;.env&lt;/code&gt; file into the &lt;em&gt;environment of the Operating System&lt;/em&gt; as early as possible.&lt;/p&gt;

&lt;p&gt;On the &lt;strong&gt;5th section&lt;/strong&gt;, we connect to the database and once successfully connected, we emit &lt;code&gt;app&lt;/code&gt;'s &lt;code&gt;"ready"&lt;/code&gt; event that will inturn launch our application listening on a &lt;em&gt;Tcp &lt;code&gt;PORT&lt;/code&gt;&lt;/em&gt;.&lt;br&gt;&lt;br&gt;
Therefore our Nodejs Server will start listening for requests after we are certain a successful database connection has been established.&lt;/p&gt;

&lt;p&gt;We can test to see our app running on &lt;code&gt;PORT&lt;/code&gt;. Open terminal at the &lt;code&gt;server&lt;/code&gt; root and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If successful, you should see a terminal output like this:&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
   &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7276j4bt9wl4c0me8qdx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7276j4bt9wl4c0me8qdx.png" alt="Terminal npm run command" width="452" height="275"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
   Output of &lt;code&gt;npm run dev&lt;/code&gt; command&lt;br&gt;
   
   &lt;br&gt;
   &lt;/p&gt;

&lt;p&gt;Open your browser and browse to &lt;code&gt;http://localhost:8000/&lt;/code&gt; to send first request to server. &lt;em&gt;And...🫰&lt;/em&gt;, you should see TEST ROUTE has responded:&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
   &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43uxekzzpuogt3lsay2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43uxekzzpuogt3lsay2s.png" alt="Test route response" width="284" height="133"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
   TEST ROUTE response&lt;br&gt;
   
   &lt;br&gt;
   &lt;/p&gt;

&lt;p&gt;So we can draw a conclusion that we connected to our database and server then started listening on &lt;em&gt;TCP port&lt;/em&gt;. You can mess with the MongoDB connection string to see how err influences what happens next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Well that is how you can perform database integration in NodeJs application. Mongoose is a &lt;em&gt;promise-based Object Document Mapper(ODM)&lt;/em&gt;. It let's us connect and run database operation on MongoDB using an object-oriented paradigm. We have approached database integration in a maintainable fashion. You can change to a different database flavour using another &lt;em&gt;promise-based ORM/ODM&lt;/em&gt;, while having little to refactor on the entry file. Also the logic that connects to a database is placed in a &lt;em&gt;separate module&lt;/em&gt; that contains everything necessary to execute one functionality i.e connecting to a database.&lt;/p&gt;

&lt;p&gt;MongoDB has &lt;em&gt;"almost"&lt;/em&gt; zero data validation. A database is mostly useful if it has some data validation, at least when we want to work with structured data. Using an ODM like mongoose will help to validate data before we put it in the DB e.g enforcing column types. MySQL is quite a legendary with a legion of in-built data validation. Nonetheless generally ORM/ODM help working with database a bit easier with its &lt;em&gt;abstraction layer&lt;/em&gt;. Hence simplifies development.&lt;/p&gt;

&lt;p&gt;So this is how we connect to database in this series. Check out the next part where we learn how to win at CORS battleground. Yes, how to fix that irritating CORS error.&lt;/p&gt;

&lt;p&gt;You wanna say something? Light up💡 the comment section 🕳🤾.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Thanks for reading. Let's connect &lt;a href="https://twitter.com/intent/user?screen_name=smitterhane" rel="noopener noreferrer"&gt;@twitter&lt;/a&gt;. You may want to be part of the ideas I share.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>node</category>
      <category>database</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>3-tier authentication - understand and conceptualize📸🤯 the process</title>
      <dc:creator>Smitter</dc:creator>
      <pubDate>Mon, 06 Mar 2023 06:00:00 +0000</pubDate>
      <link>https://dev.to/smitterhane/3-tier-authentication-understand-and-conceptualize-the-process-2g3m</link>
      <guid>https://dev.to/smitterhane/3-tier-authentication-understand-and-conceptualize-the-process-2g3m</guid>
      <description>&lt;p&gt;&lt;small&gt;Welcome to &lt;b&gt;part 1&lt;/b&gt;. Follow along this series to develop a &lt;em&gt;feature-packed&lt;/em&gt; 3-tier Authentication System outlined in successive parts.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Summary:&lt;/strong&gt; In this article, we explore token-based authentication process in a three-tier web architecture plus the bare minimum security practices to emulate&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Table of Contents&lt;/b&gt;&lt;br&gt;
  &lt;/p&gt;
&lt;ol&gt;

    &lt;li&gt;Intro&lt;/li&gt;

    &lt;li&gt;What is this tier thing?&lt;/li&gt;

    &lt;li&gt;Authentication in three-tier architecture&lt;/li&gt;

    &lt;li&gt;

How it works
        &lt;ul&gt;

            &lt;li&gt;Log in&lt;/li&gt;

            &lt;li&gt;Accessing protected resources&lt;/li&gt;

            &lt;li&gt;Refreshing Access Token&lt;/li&gt;

        &lt;/ul&gt;

      &lt;/li&gt;

    &lt;li&gt;Security practices&lt;/li&gt;

    &lt;li&gt;Run down&lt;/li&gt;

  &lt;/ol&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;User &lt;strong&gt;authentication&lt;/strong&gt; and &lt;strong&gt;authorization&lt;/strong&gt; are core &lt;em&gt;information security processes&lt;/em&gt; in building secure systems. &lt;strong&gt;&lt;em&gt;Authentication&lt;/em&gt;&lt;/strong&gt; verifies the identity of a user or service before they can proceed to access protected resources. &lt;strong&gt;&lt;em&gt;Authorization&lt;/em&gt;&lt;/strong&gt; determines what access level is required to access protected resources, &lt;em&gt;even after you are authenticated&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Modern software is built in parts, a design commonly reffered to as &lt;strong&gt;N-tier web architecture&lt;/strong&gt;. Also called &lt;em&gt;Multi-tier architecture&lt;/em&gt;. A common form of &lt;strong&gt;N-tier&lt;/strong&gt; architecture is the &lt;strong&gt;Three-tier architecture&lt;/strong&gt;. The name &lt;em&gt;N-tier&lt;/em&gt; is coined because systems do not have to be restricted to &lt;em&gt;three tiers, for example&lt;/em&gt;. As complexity increases, it is common to have more tiers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is this tier thing?
&lt;/h2&gt;

&lt;p&gt;I hope my guess is right. You may be wondering what is a tier?&lt;/p&gt;

&lt;p&gt;Well, probably you have heard of &lt;strong&gt;MERN&lt;/strong&gt; if not &lt;strong&gt;MEAN&lt;/strong&gt;, &lt;strong&gt;MEVN&lt;/strong&gt;, ... These are just a combination of technologies(&lt;small&gt;that somehow became popular&lt;/small&gt;). What is not coming out clearly is that we have &lt;strong&gt;layers&lt;/strong&gt; when building software systems. Infact, we are reffering to &lt;strong&gt;tiers&lt;/strong&gt;...not &lt;strong&gt;layers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For instance, let us elaborate using the MERN stack.&lt;br&gt;&lt;br&gt;
You have a front-end built using &lt;strong&gt;Reactjs&lt;/strong&gt;. A combination of &lt;strong&gt;Nodejs&lt;/strong&gt; and &lt;strong&gt;Expressjs&lt;/strong&gt; to build a backend that is using &lt;strong&gt;MongoDB&lt;/strong&gt; as database storage. Typically your architecture here is a &lt;strong&gt;Three-tier architecture&lt;/strong&gt; with the following tiers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Presentation tier - The UI/front-end. (Reactjs)&lt;/li&gt;
&lt;li&gt;  Application tier - Also called the &lt;em&gt;logic tier&lt;/em&gt; or &lt;em&gt;middle tier&lt;/em&gt;. Where business logic for your app lies. (Node/Express)&lt;/li&gt;
&lt;li&gt;  Data tier - Sometimes called &lt;em&gt;database tier&lt;/em&gt;. Where information processed in the &lt;em&gt;application tier&lt;/em&gt; is stored/managed. (MongoDB)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should see that tier is like a layer. But it is called a tier because: &lt;strong&gt;&lt;em&gt;"layer"&lt;/em&gt;&lt;/strong&gt; is only a functional division of software, while a &lt;strong&gt;&lt;em&gt;"tier"&lt;/em&gt;&lt;/strong&gt; refers to &lt;strong&gt;a functional division of a software that runs on infrastructure separate from the other divisions&lt;/strong&gt;. For example MongoDB runs on a separate infrastructure from Node/Express.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication in three-tier architecture
&lt;/h2&gt;

&lt;p&gt;Whether you want to increase your internal security, improve consumer acquisition or provide a better user experience for your site visitors, it's essential to know how user authentication fits into the equation.&lt;/p&gt;

&lt;p&gt;It's fairly easy to get the ball rolling using bold &lt;em&gt;tech-stacks&lt;/em&gt; like &lt;strong&gt;MERN&lt;/strong&gt;. An outright challenge is the topic of authentication. It can be daunting to put together authentication for such a project; considering that it has parts running in separate infrastructure yet they have to work together &lt;strong&gt;to achieve a common goal&lt;/strong&gt;. Moreso being &lt;em&gt;unopinionated&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A bullet-proof authentication is critical about incorporating best secure practices regularly replacing the phased-out ones. This gives a solid reason one may opt for authentication providers e.g Auth0, Cognito, Firebase Auth, who have specialized in the authentication domain to fast-track security vulnerabilities.&lt;br&gt;&lt;br&gt;
However, there are justifiable reasons to &lt;span id="why-build-auth"&gt;&lt;b&gt;implement your own Authentication&lt;/b&gt;&lt;/span&gt;, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You want to know how authentication works(&lt;em&gt;not only using it&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;  You want user data to remain within your application.&lt;/li&gt;
&lt;li&gt;  You want a bespoke authentication solution that integrates with infrastructure component that is unique to your bussiness.&lt;/li&gt;
&lt;li&gt;  Your application has a low-security risk.&lt;/li&gt;
&lt;li&gt;  You want to avoid/reduce vendor licensing fees.&lt;/li&gt;
&lt;li&gt;  You do not want to induce points of failure with less control over it when you should be able to deal with such issues.&lt;/li&gt;
&lt;li&gt;  If the third party service at the core of your architecture decided to shut you down or compete with you or shut down themselves, then you become grounded.&lt;/li&gt;
&lt;li&gt;  Not all users are comfortable with trusting a third party in order to use your application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article we are considering a bespoke Authentication solution. We articulate a conceptual flow of a typical authentication process.&lt;/p&gt;

&lt;p&gt;The type of authentication conceptualized here is &lt;strong&gt;Token-based authentication&lt;/strong&gt; using &lt;a href="https://jwt.io" rel="noopener noreferrer"&gt;Json Web Tokens&lt;/a&gt;. This is a popular authentication protocol between &lt;em&gt;Single Page Applications(SPA&lt;small&gt;s&lt;/small&gt;)&lt;/em&gt; and &lt;em&gt;REST API&lt;small&gt;s&lt;/small&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;In &lt;strong&gt;Token-based authentication&lt;/strong&gt;, the server application generates authentication tokens, &lt;em&gt;i.e &lt;strong&gt;access token&lt;/strong&gt; and &lt;strong&gt;refresh token&lt;/strong&gt; pair&lt;/em&gt; after login credentials have been successfully verified. Then clients requesting to protected resources on the server are required to include access token in every HTTP request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Access token:&lt;/strong&gt; Is a &lt;em&gt;Json Web Token&lt;/em&gt; issued to a correctly logged-in user. It contains &lt;em&gt;insensitive&lt;/em&gt; user information embedded in it. This token needs to be provided when accessing a protected resource on the server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Refresh token:&lt;/strong&gt; Is a &lt;em&gt;Json Web Token&lt;/em&gt; also issued after successful login. HTTP request may need to get a &lt;strong&gt;new access token&lt;/strong&gt; since a server will reject an &lt;em&gt;access token that is expired/invalid&lt;/em&gt;. A &lt;em&gt;refresh token&lt;/em&gt; &lt;strong&gt;needs&lt;/strong&gt; to be included on such a request before the server can process it to provide a new access token.&lt;/p&gt;

&lt;p&gt;We'll look at the following processes in a Token-based authentication:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Log in&lt;/li&gt;
&lt;li&gt;  Accesing protected resource&lt;/li&gt;
&lt;li&gt;  Refreshing &lt;em&gt;access token&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's reflect on the login process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Log In
&lt;/h3&gt;

&lt;p&gt;Below is a visualization of a login flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdpdgd69k36uqgql9o46.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdpdgd69k36uqgql9o46.gif" alt="Login flow" width="600" height="380"&gt;&lt;/a&gt;&lt;br&gt;Login flow
  &lt;/p&gt;

&lt;p&gt;In a nutshell, the purpose of login is to &lt;em&gt;request to be authenticated&lt;/em&gt;, facilitated by an access token being sent back after successful login verification. This token is what you need in every HTTP request to gain access on protected resources on the server. Including a &lt;em&gt;valid&lt;/em&gt; access token renders a HTTP request as authenticated.&lt;/p&gt;

&lt;p&gt;The flow of login control would be like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The client submits &lt;em&gt;"username"&lt;/em&gt; and &lt;em&gt;"password"&lt;/em&gt; to the server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The server receives login credentials and verifies them against a database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once a match is found, signed &lt;em&gt;access&lt;/em&gt; &amp;amp; &lt;em&gt;refresh tokens&lt;/em&gt; are generated. These tokens are embedded with &lt;strong&gt;insensitive&lt;/strong&gt; information from the match found.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The server returns a response including the access token and refresh token.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; In the visual illustration above, access token is returned in the &lt;strong&gt;response body&lt;/strong&gt; while refresh token is returned in the &lt;strong&gt;response header&lt;/strong&gt;. The assumption is that the client is in browser environment and refresh token is set onto the &lt;strong&gt;HTTP only cookie&lt;/strong&gt; to help with secure storage of the credentials(access &amp;amp; refresh token) from the client-side.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessing protected resources
&lt;/h3&gt;

&lt;p&gt;Probably we have already stressed that accessing a protected resource on the server requires that you provide an access token sent along with the HTTP request. Like shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexhaotspqjy0cgdkfgpm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexhaotspqjy0cgdkfgpm.gif" alt="Protected Resource Access flow" width="600" height="355"&gt;&lt;/a&gt;&lt;br&gt;Protected Resource Access flow
  &lt;/p&gt;

&lt;p&gt;To access a protected resource, the flow would be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Client attaches &lt;em&gt;access token&lt;/em&gt; on &lt;code&gt;Authorization&lt;/code&gt; header of a HTTP request.&lt;/li&gt;
&lt;li&gt;  Server checks for the credential(&lt;em&gt;access token&lt;/em&gt;) in the &lt;code&gt;Authorization&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;  Validation and verification is run on the &lt;em&gt;access token&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;  Once successfully verified, server allows protected resource to be served.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A step that fails will make the server to respond with an &lt;em&gt;unauthenticated error&lt;/em&gt; commonly depicted with a &lt;code&gt;401&lt;/code&gt; HTTP status code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Refreshing Access Token
&lt;/h3&gt;

&lt;p&gt;We have not talked much about &lt;em&gt;refresh token&lt;/em&gt;. It is a big player when we want to refresh/renew &lt;em&gt;access token&lt;/em&gt;. The rule of the thumb about &lt;em&gt;Token-based authentication&lt;/em&gt; is that generated token pair &lt;strong&gt;should expire&lt;/strong&gt;. &lt;em&gt;Access token&lt;/em&gt; should have the &lt;strong&gt;shorter time to expiry&lt;/strong&gt; than &lt;em&gt;refresh token&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without&lt;/strong&gt; a &lt;em&gt;refresh token&lt;/em&gt;, a user would be interrupted to &lt;em&gt;"log in"&lt;/em&gt; again with &lt;em&gt;username/password&lt;/em&gt; to obtain a new &lt;em&gt;access token&lt;/em&gt; whenever the current one becomes invalid or expired. That rude interruption is an annoying experience to a user considering that &lt;em&gt;access token&lt;/em&gt; is short-lived.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;With&lt;/strong&gt; a &lt;em&gt;refresh token&lt;/em&gt;, client can obtain a new &lt;em&gt;access token&lt;/em&gt; without another manual &lt;em&gt;"log in"&lt;/em&gt;. And for a better user experience, a client will &lt;em&gt;automatically obtain a NEW access token in the background&lt;/em&gt; whenever a server rejects the &lt;em&gt;access token&lt;/em&gt; in HTTP request because it is &lt;em&gt;invalid or expired&lt;/em&gt;. The rejected request can then be &lt;em&gt;retried&lt;/em&gt; with the &lt;strong&gt;NEW access token&lt;/strong&gt;. All these is automated by a client without a user's intervention.&lt;br&gt;&lt;br&gt;
This process is as visualized below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flazik5ck31zkt8pdg176.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flazik5ck31zkt8pdg176.gif" alt="Refresh Access token overview" width="600" height="389"&gt;&lt;/a&gt;&lt;br&gt;Refresh Access token overview
  &lt;/p&gt;

&lt;p&gt;Procedurally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  A client includes access token in &lt;code&gt;Authorization&lt;/code&gt; header of HTTP request.&lt;/li&gt;
&lt;li&gt;  This is a protected resource, so the server checks for &lt;em&gt;access token&lt;/em&gt; in &lt;code&gt;Authorization&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;  Server authenticates the request and detects &lt;em&gt;access token&lt;/em&gt; is expired(or invalid).&lt;/li&gt;
&lt;li&gt;  Server ends the request with an &lt;strong&gt;unauthenticated error&lt;/strong&gt; response.&lt;/li&gt;
&lt;li&gt;  Client detects that the request failed due to unauthentication.&lt;/li&gt;
&lt;li&gt;  Client triggers a HTTP request to renew &lt;em&gt;access token&lt;/em&gt; and includes &lt;em&gt;refresh token&lt;/em&gt; in cookie header.&lt;/li&gt;
&lt;li&gt;  Server verifies the &lt;em&gt;refresh token&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;  Once &lt;em&gt;refresh token&lt;/em&gt; is verified, a NEW access token is generated and returned in response body.&lt;/li&gt;
&lt;li&gt;  Client receives the &lt;em&gt;NEW access token&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;  Client uses the NEW access token to retry the initial request that had failed with an &lt;em&gt;unauthenticated error&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; Maximum retries should be implemented on the client-side to avoid an infinite loop&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security practices
&lt;/h2&gt;

&lt;p&gt;The stateless principle of &lt;em&gt;Token-based authentication&lt;/em&gt; is advantagious to give your application the performance boost you just needed. This is because there is no database look-ups when authenticating requests. &lt;em&gt;Access tokens&lt;/em&gt; are stored on the client-side. Same is the case for &lt;em&gt;refresh tokens&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;However since these tokens are as sensitive as &lt;em&gt;"passwords"&lt;/em&gt;, they need to be stored securely from the client-side. You should consider implementing the following best practices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do not embed sensitive data in the tokens.&lt;/li&gt;
&lt;li&gt;Give tokens an expiration.&lt;/li&gt;
&lt;li&gt;Access tokens should be short-lived(&lt;em&gt;within minutes&lt;/em&gt;). While maintaining the stateless characteristic, &lt;em&gt;access tokens &lt;strong&gt;do not&lt;/strong&gt; have a way to be revoked&lt;/em&gt;. A short life span will allow for minimal duration of usage incase an access token lands in the hands of &lt;em&gt;"evil"&lt;/em&gt; user.&lt;/li&gt;
&lt;li&gt;Refresh tokens should be &lt;em&gt;revocable&lt;/em&gt;. Since there is no way to revoke access tokens, then at least &lt;em&gt;refresh tokens should&lt;/em&gt;. If a refresh token is reported as leaked, the token can be revoked such that refresh requests using the revoked &lt;em&gt;refresh token&lt;/em&gt; &lt;strong&gt;will fail&lt;/strong&gt;. Possibly you could think of an evil user using a stolen access token and next time they want to renew the token, the server will lock them out.&lt;/li&gt;
&lt;li&gt;Incase client is in a browser environment, &lt;em&gt;refresh tokens&lt;/em&gt; could be stored in HTTP-only cookie and &lt;em&gt;access token&lt;/em&gt; kept &lt;em&gt;in-memory&lt;/em&gt; without persisting anywhere.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Run down
&lt;/h2&gt;

&lt;p&gt;We have discussed the process of authentication and the steps involved in a typical &lt;em&gt;"Three-tier web architecture"&lt;/em&gt;. To quickly recap, we have discussed the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Modern software is built in parts with different infrastructure(tiers).&lt;/li&gt;
&lt;li&gt;  Token-based authentication is common among &lt;em&gt;N-tier architectured&lt;/em&gt; applications.&lt;/li&gt;
&lt;li&gt;  Login is a request to get authentication tokens.&lt;/li&gt;
&lt;li&gt;  Access token and refresh token are issued after successful login.&lt;/li&gt;
&lt;li&gt;  Authentication tokens issued are stored in the client-side. And they should be stored securely.&lt;/li&gt;
&lt;li&gt;  Requests to protected resources on the server need to include access token e.g in &lt;code&gt;Authorization&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;  Refresh token is used to renew &lt;em&gt;access token&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that's a wrap. Thanks for reading this far. Are you one that wants the concepts shared here translated into working solution? If it sounds like you, this series just serves you right. Check ou the next parts.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;br&gt;
Something is not clear enough? Don't hesitate to bomb💣 the comment section👇️. The explosion effect can clear your mysteries. Also reach out &lt;a href="https://twitter.com/intent/user?screen_name=smitterhane" rel="noopener noreferrer"&gt;@twitter&lt;/a&gt;. I'll be happy to help 😊.&lt;br&gt;
&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>java</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
