his is what I chose to write about. It was the expertise my client was looking for, but it has since led to over $100K worth of work with this single client, both in my niche and on projects completely unrelated.</p><p id="17ad">Finding a niche is a good idea, but it doesn’t need to define what you do forever. You can use it as a foot in and a way of building your profile.</p><h1 id="ca76">2. I solved my client's problem</h1><p id="3bda">My client was originally looking for writers who had worked in the careers space to write content about changing careers. They had a specific brief they wanted to fill.</p><p id="fc29">Although they contacted me, I didn’t take that they wanted me as a given, and I still wrote a proposal detailing how I could help them achieve their goal. I focused on what I could do <i>FOR </i>them, solving their problem, and outlining clearly how I would approach the task. I told them my credentials, but I made my proposal about them and what they needed.</p><p id="ec1a">It is a common freelancer mistake to launch into what they have achieved, who they’ve worked for, and what qualifications they have without linking this to how it will help the client. Above anything else, they want to know how <i>YOU</i> are going to help <i>THEM</i>.</p><h1 id="fcc5">3. I provided proof</h1><p id="33db">We already know that Upwork has got itself known for having some poor-quality clients and freelancers. To stand above the 18 million, it’s important to show that you are not a wannabe with no experience. You are an expert at what you do.</p><p id="c5fb">To do this, you need proof. I have a writing portfolio I link to when pitching for work, I have testimonials on my Upwork profile, and I have recommendations on LinkedIn that I can also share.</p><p id="2eb3">It’s important that you can back up your talk with hard evidence showing what you can do. Especially for clients paying the biggest sums. They want to be sure they are getting the quality they are willing to pay for.</p><h2 id="799c">What have I learnt?</h2><p id="d224">The fact that people think you can’t get good clients on Upwork can be an advantage. If you have the right mindset and approach, it’s easier than you think to stand above the 18 million freelancers, many of whom aren’t expecting to strike it big. Many are aiming low, pricing low, and putting in the effort that the low expectation equates to.</p><p id="d52e">If you really have expertise to offer, and you put in the effort to pitch yourself in the right way, there are top clients to be had on Upwork.</p><h2 id="08d1">There’s more…</h2><p id="98a5">If you like my work, I have a series of articles about how to make money on Upwork in the pipeline.</p><p id="9fed">Here is my latest:</p><div id="af67" cla
Options
ss="link-block">
<a href="https://readmedium.com/how-i-made-100k-on-upwork-and-became-top-rated-with-a-100-success-score-a305ef7d8e01">
<div>
<div>
<h2>How I Made £100K on Upwork and Became Top Rated With a 100% Success Score</h2>
<div><h3>If I can do it, so can you</h3></div>
<div><p>medium.com</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*talqtG9SwMex4wuI)"></div>
</div>
</div>
</a>
</div><p id="d650">You can follow me or subscribe to my list here on Medium, or you can join my Substack community, <a href="https://redefiningsuccess.substack.com/">Redefining Success</a>, for even more. I’m looking forward to connecting.</p><p id="e0a8">Check out some of my latest posts:</p><div id="ed1c" class="link-block">
<a href="https://readmedium.com/how-you-define-success-could-be-the-key-to-your-happiness-7e87f5a5b9f2">
<div>
<div>
<h2>How You Define Success Could Be the Key to Your Happiness</h2>
<div><h3>And also your unhappiness…</h3></div>
<div><p>medium.com</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*y6XeGW7HiHo0F9_o)"></div>
</div>
</div>
</a>
</div><div id="071c" class="link-block">
<a href="https://readmedium.com/how-a-train-hopper-made-me-see-how-messed-up-our-working-system-is-8f5dc3b6dd3c">
<div>
<div>
<h2>How a Train Hopper Made Me See How Messed Up Our Working System Is</h2>
<div><h3>We’ve got it so backwards</h3></div>
<div><p>medium.com</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*S1pUr2HzkJKbUSZB)"></div>
</div>
</div>
</a>
</div><div id="1424" class="link-block">
<a href="https://readmedium.com/when-i-called-myself-a-writer-the-money-came-in-fc77468e0627">
<div>
<div>
<h2>When I Called Myself a Writer, the Money Came In</h2>
<div><h3>What you tell yourself matters</h3></div>
<div><p>medium.com</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*AYK0DtsukpP2-1cF)"></div>
</div>
</div>
</a>
</div></article></body>
Build a Login System in Node.js
How to use Passport.js for user authentication in your node app
You’re a talented web developer in extremely high demand. Time and time again, you’ve proven yourself capable of building extremely complex apps with big success.
Let’s start with an example. A local school desires its students to view their academic progress and homework right from an app. Due to your glowing recommendations, naturally, the school department hires you. These are their requirements:
Students first log in to the app using their email and required credentials. If an existing account is not found, they are prompted to create an account.
If an existing account is found, the student can now view their academic progress and homework.
A logout option is also provided so that the student can sign out from the app if they are using a public computer.
The student cannot access the dashboard unless they are logged in.
This tutorial will be focusing on the login and logout system portion of the website. This is called user authentication. If you’re using JavaScript, a library called Passport.js can be used for user authentication. Passport.js is essentially middleware used for authentication in Node.Js.
This is your objective as it meets the requirements of the client:
The objective of this tutorial
Get Started
Before typing any code, first install the following modules:
express for handling your routes
express-session for building a user session
express-ejs-layouts layout support for ejs in Express
connect-flash will be used to display flash messages. We will cover more on this later.
passport to handle user authentication
passport-local, which is a strategy(authentication mechanism) with a username and password
mongoose for storing users in the database
bcrypt for encrypting your passwords before you store them in your database. It’s a necessity to never store passwords in plain text for obvious security reasons.
ejs module to send data from Express to ejs files
This is the command you should run:
npm i expressexpress-session express-ejs-layouts connect-flash passport passport-local mongoose bcrypt ejs
When that’s done, follow the further steps listed below for the initial stages.
The index.js route
Create a folder in your project directory with the name of route. Here, create a JavaScript file called index.js. In the end, the location of index.js
will be at routes/index.js.
In routes/index.js, write the following code:
line 4: When the user navigates to the root directory (performs a GET request) render the welcome.ejs page.
line 8: When the user does a GET request to the register page, render the register.ejs page.
line 12: Export the router instance so that it can be used in other files.
The users.js route
Go to your routes folder and create a file called users.js such that the users.js location is routes/users.js.
In routes/users.js,
Lines 5 to 9: Handle the respective GET requests and render the appropriate pages
Lines 12 to 14: Handle the respective POST requests. They will be filled in later on in this tutorial.
app.js
This will be your main file. In your root directory, create a file called app.js. Here, write the following code:
line 11: Tells Express that you will be using ejs as your template engine
Now that you have defined your routes, let’s create the ejs files that will be rendered to the screen.
Create a views folder in your root directory and write the following files. These are standard, static ejs files. You can find the explanations for the code in the EJS documentation website.
layout.ejs
In views/layout.ejs:
<html><head><title>Node.Js and Passport App</title></head><body><%- body %></body></html>
register.ejs
welcome.ejs
<html><h1>Welcome!</h1><p>Create an account or login</p><ahref="/users/register">Register</a><ahref="/users/login"> Login</a></html>
login.ejs
Note: You have used the name attributes for the elements in the form as you will extract the values in the form by identifying each element by name.
To run this code, go to the command line to run the app.js file.
nodeapp
Go to localhost:3000 and you will find your output to be identical to this:
Output of the code showing each corresponding route
You have finally completed your beginning stages. It’s now time to use Mongoose to save your users in your database.
Save Users to Database
The user schema and model
As usual, you have to define a schema before creating documents and saving them to the database. First, create the models directory and there create a file called user.js such that it is models/user.js. First, let’s create a schema in user.js. Next, we’ll create a model from that schema.
In models/user.js:
This means that your model will have a name, an email, its associated password, and the date of creation.
On line 20 , we’re using that schema in your User model. All of your users will have the data in this format.
Handling the POST request to the register directory: validation checks
In this step, you will create a document in the MongoDB database with the client-provided data.
At the beginning of the routes/users.js file, import the Mongoose library, and import the User model that you just created.
const User= require("../models/user.js")
Now, in the routes/users.js file, find the following piece of code:
Handling the register POST request
Within this handle, write the following code:
Line 1: Extract the values from the elements in the form. You are taking out the email, the name of the user, his password. The last field (password2 ) is a validation check to ensure that the user has confirmed that the password they are typing is correct.
Lines 4-6: If any of the fields has not been filled, add an appropriate message to the error array.
Lines 8–10: If the passwords don’t match, add the appropriate message to the error array.
Lines 13–15: Check whether the password has a minimum of six characters.
Lines 16–23: If any content within the error array is present, re-render the register.ejs page and then send the appropriate data along with the errors array. All of the contents of this array will be displayed on the page.
Lines 24–36: You have successfully passed the validation! Now you will first find if there is already a user present in the database via the email. If there is, then you will re-render the register.ejs page and display the relevant error. Otherwise, create a new user with the provided email, name, and its associated password. Bear in mind that you haven’t saved it yet. You will save it after encrypting the password.
As an example, let’s run the code and enter a single-character password so that it re-renders the page:
Output of the code after you deliberately enter the wrong options
You now need to display the errors, that is, display the contents of the errors array.
Display the errors
Now go to views/register.ejs and find the following piece of code (this will be around the beginning of the file):
Code to find at views/register.ejs
When you’ve found it, write the following line just under this h1 tag:
<%- include ('./partials/messages') %>
This line means import a new file that will help display the messages.
Go to your views directory, create a new directory called partials, and within partials, create a file called messages.ejs. There, write the following code.
This code says that if there are any errors present, then display the contents of the array with its own paragraph(p) element.
Re-run the code and write a single character password. This will be the output:
Notice that you have now displayed the error message
If you leave any of the fields empty, then you will get this error message:
Two error messages displayed in this form
Make both password fields contain different values:
Three error messages displayed in this form
Handling POST requests to the register: save the users to the database
In this step, you will save the registered users to the MongoDB database. You will first encrypt their passwords and then save them to the database.
In routes/users.js, find the following piece of code:
Code in routes/users.js
Within this else block, write the following piece of code:
And on that note, end the else statement here.
Lines 2–7 : Generate a salt, hash the user’s password. Assign this encrypted value to the user’s password and then save the client to the database.
Line 10 : When the document is saved without errors, then redirect the user to the login directory, where the user will now log in with their credentials.
This will be the output of the code when you register yourself as a user:
Code output
Since you have logged out the contents of the document in your console, here’s the output in the console:
Contents of the newUser document
Enter a registered email. As expected, you get an error telling you that the email has already been stored:
Code output showing that you have an error
With this step, you’ve finally saved users to the database. Let’s move on to creating flash messages with Express.
At the end of this section, this is what your code looks like:
Flash Messaging With Express
When you register an account on a website, notice it redirects you to the login page, along with displaying a success message indicating that you’ve successfully logged in. That success message is called a flash message.
In this section, we’ll create a flash message.
Before moving on, start by importing the following two libraries within app.js.
You are now importing passport-local with its Strategy instance for a user authentication mechanism with a simple username and password. Since you will be comparing passwords this time, you need to decrypt the password that was returned by the database. For this reason, you will also bring in bcrypt. Furthermore, since you are essentially comparing passwords returned from the database, you will import User model for database-related operations.
Further on, type the following code:
Line 2: Configure the passport instance such that it will be using the LocalStrategy strategy. You have to specify the usernameField option, as this option will be used to identify the email address that will be compared against the database. You have identified with this option that you will be using the email input type element in the form. You can specify the passwordField option as well. However, by default, it is password, so you don’t need to specify it here.
Lines 5–24: First, find whether the given email address is present in the database. If it is not, it’ll throw an error that the email isn’t recognized. Later on, you then compare whether the user-entered password matches the password in the database. If it does, it will return the relevant user information.
Lines 25–34: In order to support login sessions, passport will use the serialize and deserialize methods on the user instances to and from the session.
Handling the POST request to the login directory
You now need to tell Passport where you want to use user authentication. You will use this authentication mechanism on the login page.
Go to /routes/users.js and find the following piece of code:
routes/users.js
Within this POST handler, write the following lines of code:
You can now use user authentication functionality in your app. However, you are not done yet. You still need to handle the redirect to the dashboard directory.
Go to /routes/index.js and type the following code:
The req.logout function is created by Passport. As the name suggests, it logs out the user session. Later on, you send a success flash message and then redirect the user to the login page.
This will be the output of the code:
Output of the code
However, if you now go to localhost:3000/dashboard, you’re greeted with a server error. Now let’s handle this.
This creates a function called ensureAuthenticated, which will ensure that a user has logged in (req.isAuthenticated()). If so, it moves on to the next middleware. If not, it throws an error and redirects the user to the login page again.
Now, go to /routes/index.js and import this function:
Passport documentation contains everything you need to know about user authentication out of the box, but it’s out of order, which is why I find it a bit confusing. Nevertheless, here are the best resources available needed to learn about Passport.
This was a long tutorial! Thank you for making it this far. In the case of confusion, you are advised to deconstruct the code and research on what function does what- never give up! Thank you so much for making it to the end. Have a great day!