<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ JWT - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ JWT - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 22 May 2026 17:39:49 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/jwt/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Secure Authentication System with JWT and Refresh Tokens ]]>
                </title>
                <description>
                    <![CDATA[ Every app that handles user accounts needs a way to confirm who’s who. That’s what authentication is for, making sure the person using an app is the person they claim to be. But doing this securely is harder than it sounds. Traditional methods often ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-secure-authentication-system-with-jwt-and-refresh-tokens/</link>
                <guid isPermaLink="false">6925f655569c4dde127d2f88</guid>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JWT ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Joan Ayebola ]]>
                </dc:creator>
                <pubDate>Tue, 25 Nov 2025 18:32:53 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1764095460886/51b9c653-fa95-42f0-8c51-37f6d6805da4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Every app that handles user accounts needs a way to confirm who’s who. That’s what authentication is for, making sure the person using an app is the person they claim to be. But doing this securely is harder than it sounds.</p>
<p>Traditional methods often rely on server sessions and cookies. Those work, but they don’t always scale well, especially when you’re building APIs or mobile apps that talk to multiple services. This is why JWTs, or JSON Web Tokens, are useful. They’re small, self-contained tokens that can carry user data safely between a client and a server.</p>
<p>JWTs make it easy to verify users without constantly checking a database – but they also expire fast to reduce risk. To keep users logged in without forcing them to sign in again every few minutes, we use something called a refresh token. It’s a separate, long-lived token that can request new access tokens when the old ones expire.</p>
<p>In this guide, we’ll walk through how to build a secure authentication system using JWTs and refresh tokens. You’ll learn how to generate tokens, validate them, handle expiry, and keep everything safe from common security threats.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-understanding-jwts-json-web-tokens">Understanding JWTs (JSON Web Tokens)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-setting-up-the-project">Setting Up the Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-jwt-authentication">How to Implement JWT Authentication</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-verify-jwts-and-protect-routes">How to Verify JWTs and Protect Routes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-refresh-tokens-and-rotation">Refresh Tokens and Rotation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-understanding-jwts-json-web-tokens">Understanding JWTs (JSON Web Tokens)</h2>
<p>A JWT, short for JSON Web Token, is a compact way to share information between a client and a server. It’s often used to prove that a user is who they say they are. The token is created on the server after a user logs in and is then sent back to the client. The client then includes this token with each request, so the server knows who is making the call.</p>
<p>A JWT has three parts: a header, a payload, and a signature.</p>
<ul>
<li><p>The <strong>header</strong> usually tells the system which algorithm was used to sign the token.</p>
</li>
<li><p>The <strong>payload</strong> contains the data, such as the user’s ID or role.</p>
</li>
<li><p>The <strong>signature</strong> is the part that keeps everything secure. It’s created by hashing the header and payload with a secret key.</p>
</li>
</ul>
<p>Once created, a JWT looks like a long string of random characters separated by dots. When the client sends it back to the server, the server verifies the signature using the same secret key. If it matches, the request is trusted.</p>
<p>One of the main benefits of JWTs is that they are stateless. The server doesn’t need to store session data. Everything needed to verify the user is already inside the token. This makes them fast and easy to use in modern APIs and microservices.</p>
<p>JWTs do have a downside: they cannot be revoked easily once issued. If a token is stolen, the attacker can use it until it expires. This is why short token lifetimes matter. It’s also why refresh tokens exist.</p>
<p>In the next section, we’ll finish the basic JWT setup. After that, we’ll add refresh tokens in <strong>“Refresh Tokens and Rotation.”</strong> That part shows how to handle expiry without making users log in again.</p>
<h2 id="heading-setting-up-the-project">Setting Up the Project</h2>
<p>Before writing any code, let’s set up a simple backend where we can build and test our authentication system. For this guide, we’ll use Node.js with Express, since it’s lightweight and easy to follow. You can use any stack later once you understand the flow.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Make sure you have:</p>
<ul>
<li><p>Node.js and npm installed</p>
</li>
<li><p>A text editor (VS Code works great)</p>
</li>
<li><p>Basic knowledge of JavaScript and APIs</p>
</li>
</ul>
<h3 id="heading-1-initialize-the-project">1. Initialize the Project</h3>
<p>Create a new folder and open it in your terminal.</p>
<pre><code class="lang-bash">mkdir jwt-auth-demo
<span class="hljs-built_in">cd</span> jwt-auth-demo
npm init -y
</code></pre>
<p>This creates a <code>package.json</code> file that will track your dependencies.</p>
<h3 id="heading-2-install-dependencies">2. Install Dependencies</h3>
<p>You’ll need a few packages to get started:</p>
<ul>
<li><p><code>express</code>: the web framework</p>
</li>
<li><p><code>jsonwebtoken</code>: to create and verify tokens</p>
</li>
<li><p><code>bcryptjs</code>: to hash passwords</p>
</li>
<li><p><code>dotenv</code>: to manage environment variables</p>
</li>
</ul>
<p>Install them all at once like this:</p>
<pre><code class="lang-bash">npm install express jsonwebtoken bcryptjs dotenv
</code></pre>
<p>If you want auto-reloading while developing, install nodemon as a dev dependency:</p>
<pre><code class="lang-bash">npm install --save-dev nodemon
</code></pre>
<h3 id="heading-3-project-structure">3. Project Structure</h3>
<p>Here’s a clean structure to keep things organized:</p>
<pre><code class="lang-plaintext">jwt-auth-demo/
│
├── server.js
├── .env
├── package.json
│
├── config/
│   └── db.js
│
├── middleware/
│   └── auth.js
│
├── routes/
│   └── auth.js
│
└── models/
    └── user.js
</code></pre>
<h3 id="heading-4-basic-express-setup">4. Basic Express Setup</h3>
<p>In <code>server.js</code>, start with a minimal Express server.</p>
<pre><code class="lang-js"><span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config();
<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> app = express();

app.use(express.json());

app.get(<span class="hljs-string">'/'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  res.send(<span class="hljs-string">'JWT Auth API running'</span>);
});

<span class="hljs-keyword">const</span> PORT = process.env.PORT || <span class="hljs-number">5000</span>;
app.listen(PORT, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Server running on port <span class="hljs-subst">${PORT}</span>`</span>));
</code></pre>
<p>You can now run it using:</p>
<pre><code class="lang-bash">node server.js
</code></pre>
<p>or, if you’re using nodemon:</p>
<pre><code class="lang-bash">npx nodemon server.js
</code></pre>
<p>If everything is set up correctly, visiting <code>http://localhost:5000</code> should display <strong>“JWT Auth API running”:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760559643076/8fb7dcbf-50ca-44bc-b2a3-32273d82957f.png" alt="Screenshot of a terminal running nodemon server.js next to a browser window showing the text “JWT Auth API running” at http://localhost:5000, confirming the server started correctly." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-implement-jwt-authentication"><strong>How to Implement JWT Authentication</strong></h2>
<p>Now that your server is up, let’s add real authentication. We’ll start with user registration, password hashing, and login. Each user will get a token after logging in, which they can use to access protected routes.</p>
<h3 id="heading-1-set-up-the-user-model">1. Set Up the User Model</h3>
<p>We’ll store users in a simple database. For this demo, let’s use MongoDB with Mongoose, since it’s quick to set up and easy to scale later.</p>
<p>Install the required packages:</p>
<pre><code class="lang-bash">npm install mongoose
</code></pre>
<p>Then create <code>models/user.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>);

<span class="hljs-keyword">const</span> userSchema = <span class="hljs-keyword">new</span> mongoose.Schema({
  <span class="hljs-attr">username</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-attr">email</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-attr">password</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span> }
});

<span class="hljs-built_in">module</span>.exports = mongoose.model(<span class="hljs-string">'User'</span>, userSchema);
</code></pre>
<p>We store users with a unique email and a hashed password. The database never sees the raw password. Hashing makes stolen data harder to use.</p>
<h3 id="heading-2-connect-to-mongodb">2. Connect to MongoDB</h3>
<p>Inside <code>config/db.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>);

<span class="hljs-keyword">const</span> connectDB = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> mongoose.connect(process.env.MONGO_URI);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'MongoDB connected'</span>);
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(err.message);
    process.exit(<span class="hljs-number">1</span>);
  }
};

<span class="hljs-built_in">module</span>.exports = connectDB;
</code></pre>
<p><code>mongoose.connect</code> reads the connection string from <code>.env</code>. If the connection fails, we exit the process so we don’t continue in a broken state.</p>
<p>Update your <code>server.js</code> to include the connection:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> connectDB = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./config/db'</span>);
connectDB();
</code></pre>
<p>And don’t forget to add your MongoDB URI in the <code>.env</code> file:</p>
<pre><code class="lang-plaintext">MONGO_URI=mongodb+srv://yourusername:yourpassword@cluster.mongodb.net/auth
JWT_SECRET=your_jwt_secret_key
</code></pre>
<h3 id="heading-3-create-registration-and-login-routes">3. Create Registration and Login Routes</h3>
<p>In <code>routes/auth.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> bcrypt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'bcryptjs'</span>);
<span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);
<span class="hljs-keyword">const</span> User = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../models/user'</span>);

<span class="hljs-keyword">const</span> router = express.Router();

<span class="hljs-comment">// Register a new user</span>
router.post(<span class="hljs-string">'/register'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { username, email, password } = req.body;

    <span class="hljs-keyword">const</span> existingUser = <span class="hljs-keyword">await</span> User.findOne({ email });
    <span class="hljs-keyword">if</span> (existingUser) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'User already exists'</span> });

    <span class="hljs-keyword">const</span> hashedPassword = <span class="hljs-keyword">await</span> bcrypt.hash(password, <span class="hljs-number">10</span>);

    <span class="hljs-keyword">const</span> newUser = <span class="hljs-keyword">new</span> User({ username, email, <span class="hljs-attr">password</span>: hashedPassword });
    <span class="hljs-keyword">await</span> newUser.save();

    res.status(<span class="hljs-number">201</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'User created successfully'</span> });
  } <span class="hljs-keyword">catch</span> (err) {
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Server error'</span> });
  }
});

<span class="hljs-comment">// Login and issue JWT</span>
router.post(<span class="hljs-string">'/login'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { email, password } = req.body;

    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findOne({ email });
    <span class="hljs-keyword">if</span> (!user) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Invalid credentials'</span> });

    <span class="hljs-keyword">const</span> isMatch = <span class="hljs-keyword">await</span> bcrypt.compare(password, user.password);
    <span class="hljs-keyword">if</span> (!isMatch) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Invalid credentials'</span> });

    <span class="hljs-keyword">const</span> payload = { <span class="hljs-attr">id</span>: user._id, <span class="hljs-attr">email</span>: user.email };

    <span class="hljs-keyword">const</span> token = jwt.sign(payload, process.env.JWT_SECRET, { <span class="hljs-attr">expiresIn</span>: <span class="hljs-string">'15m'</span> });

    res.json({ token });
  } <span class="hljs-keyword">catch</span> (err) {
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Server error'</span> });
  }
});

<span class="hljs-built_in">module</span>.exports = router;
</code></pre>
<p>Add it to your server in <code>server.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> authRoutes = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./routes/auth'</span>);
app.use(<span class="hljs-string">'/api/auth'</span>, authRoutes);
</code></pre>
<h3 id="heading-4-test-it-out">4. Test It Out</h3>
<p>You can now test these routes using Postman or Insomnia.</p>
<p>Send a <code>POST</code> request to <code>/api/auth/register</code> with a JSON body:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"username"</span>: <span class="hljs-string">"demoUser"</span>,
  <span class="hljs-attr">"email"</span>: <span class="hljs-string">"demo@email.com"</span>,
  <span class="hljs-attr">"password"</span>: <span class="hljs-string">"mypassword"</span>
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760713863394/c13ddbd5-ebb1-47d1-9b6d-06bc0f33eb7d.png" alt="Screenshot of a Postman request sending a POST call to http://localhost:3000/api/auth/register with a JSON body containing a username, email, and password. The response area shows a 201 Created status and the message “User created successfully.&quot;" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The register route checks for an existing user by email. It hashes the password with a cost factor of 10 and then returns a 201 on success. We don’t log the password or include it in the response.</p>
<p>Then log in at <code>/api/auth/login</code> to receive a JWT.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760713960135/58eeaa4e-d652-4509-ad6e-756baf19ff8c.png" alt="Screenshot of a Postman request sending a POST call to http://localhost:3000/api/auth/login with a JSON body containing a username, email, and password. The response panel shows a 200 OK status and a JSON object with a generated JWT token." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The login route finds the user by email and compares the password with bcrypt.compare. If it matches, we sign a token with a small payload: the user ID and email. The JWT_SECRET signs the token so the server can verify it later. The expiresIn: '15m' setting keeps the token short-lived to limit risk. The response only includes the token. User data can be fetched from a protected route.</p>
<p>Once you get the token, copy it, you’ll use it to access protected routes later.</p>
<h2 id="heading-how-to-verify-jwts-and-protect-routes">How to Verify JWTs and Protect Routes</h2>
<p>Now that login returns a token, we should verify it on each request that needs auth. We will write a small middleware that checks the <code>Authorization</code> header, validates the token, and adds the user info to the request.</p>
<h3 id="heading-1-create-the-auth-middleware">1. Create the Auth Middleware</h3>
<p>Create <code>middleware/auth.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">auth</span>(<span class="hljs-params">req, res, next</span>) </span>{
  <span class="hljs-keyword">const</span> authHeader = req.headers.authorization || <span class="hljs-string">''</span>;
  <span class="hljs-keyword">const</span> [scheme, token] = authHeader.split(<span class="hljs-string">' '</span>);

  <span class="hljs-keyword">if</span> (scheme !== <span class="hljs-string">'Bearer'</span> || !token) {
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Missing or invalid Authorization header'</span> });
  }

  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = { <span class="hljs-attr">id</span>: decoded.id, <span class="hljs-attr">email</span>: decoded.email };
    next();
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-keyword">if</span> (err.name === <span class="hljs-string">'TokenExpiredError'</span>) {
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Access token expired'</span> });
    }
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Invalid token'</span> });
  }
}

<span class="hljs-built_in">module</span>.exports = auth;
</code></pre>
<p>What it does:</p>
<ul>
<li><p>Reads the <code>Authorization</code> header.</p>
</li>
<li><p>Checks for the <code>Bearer &lt;token&gt;</code> format.</p>
</li>
<li><p>Verifies the token with the secret.</p>
</li>
<li><p>Attaches a simple <code>user</code> object to <code>req</code> for later use.</p>
</li>
</ul>
<h3 id="heading-2-create-the-protected-route">2. Create the Protected Route</h3>
<p>Create a small profile route that returns the current user. Add <code>routes/profile.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> auth = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../middleware/auth'</span>);
<span class="hljs-keyword">const</span> User = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../models/user'</span>);

<span class="hljs-keyword">const</span> router = express.Router();

router.get(<span class="hljs-string">'/me'</span>, auth, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findById(req.user.id).select(<span class="hljs-string">'-password'</span>);
    <span class="hljs-keyword">if</span> (!user) {
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'User not found'</span> });
    }
    res.json({ user });
  } <span class="hljs-keyword">catch</span> (err) {
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Server error'</span> });
  }
});

<span class="hljs-built_in">module</span>.exports = router;
</code></pre>
<p>Wire it in <code>server.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> profileRoutes = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./routes/profile'</span>);
app.use(<span class="hljs-string">'/api/profile'</span>, profileRoutes);
</code></pre>
<p>Now a <code>GET /api/profile/me</code> call will only work with a valid token.</p>
<h3 id="heading-3-handle-token-expiry-clearly">3. Handle Token Expiry Clearly</h3>
<p>Short access tokens reduce damage if they leak. We set <code>expiresIn: '15m'</code> during login. When a token expires, the middleware returns a 401 with <code>Access token expired</code>.</p>
<p>We won’t refresh the token here because refresh requires its own endpoint, storage, and rotation rules. You’ll add that in <strong>“Refresh Tokens and Rotation.”</strong> For now, the 401 proves that the expiry is enforced.</p>
<h3 id="heading-4-testing-the-flow">4. Testing the Flow</h3>
<p>In this section, we’ll test that the server blocks requests without a valid token and allows requests with a valid token.</p>
<p>Log in at <code>/api/auth/login</code> and copy the token. Then call <code>/api/profile/me</code> with:</p>
<pre><code class="lang-typescript">Authorization: Bearer &lt;paste_token_here&gt;
</code></pre>
<p>You should see the current user without the password field.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760715340324/13779fe0-304c-460b-87ac-c86133eea2a4.png" alt="Screenshot of a Postman GET request to http://localhost:3000/api/profile/me using a valid JWT. The response shows a 200 OK status and returns the user’s _id, username, and email, confirming that the protected route works when a proper token is included." width="600" height="400" loading="lazy"></p>
<p>Then remove the header or change the token and call again. You should get a 401.</p>
<p>Next, wait for the token to expire or change <code>expiresIn</code> to a very short value for a quick test. Call again and confirm you get <code>Access token expired</code>.</p>
<h4 id="heading-tips-for-debugging">Tips for debugging</h4>
<ul>
<li><p>401 with “Missing or invalid Authorization header” means the header format is wrong. Use <code>Authorization: Bearer &lt;token&gt;</code>.</p>
</li>
<li><p>401 with “Invalid token” means the token string is wrong, signed with the wrong secret, or corrupted.</p>
</li>
<li><p>401 with “Access token expired” means the expiry check works. You will fix the client experience with the refresh endpoint later.</p>
</li>
<li><p>If all calls fail, confirm your <code>JWT_SECRET</code> is set in <code>.env</code> and that the server was restarted after changes.</p>
</li>
</ul>
<h3 id="heading-5-optional-cookie-support">5. Optional Cookie Support</h3>
<p>You can store tokens in HTTP-only cookies. The browser sends them automatically. Scripts cannot read HTTP-only cookies, which reduces the risk from XSS.</p>
<p>Install and enable cookies:</p>
<pre><code class="lang-plaintext">npm install cookie-parser
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-comment">// server.js</span>
<span class="hljs-keyword">const</span> cookieParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cookie-parser'</span>);
app.use(cookieParser());
</code></pre>
<p>Read the access token from a cookie as a fallback:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// middleware/auth.js</span>
<span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">auth</span>(<span class="hljs-params">req, res, next</span>) </span>{
  <span class="hljs-keyword">const</span> header = req.headers.authorization || <span class="hljs-string">''</span>;
  <span class="hljs-keyword">const</span> [scheme, tokenFromHeader] = header.split(<span class="hljs-string">' '</span>);
  <span class="hljs-keyword">const</span> tokenFromCookie = req.cookies?.access_token;

  <span class="hljs-keyword">const</span> token = scheme === <span class="hljs-string">'Bearer'</span> &amp;&amp; tokenFromHeader ? tokenFromHeader : tokenFromCookie;

  <span class="hljs-keyword">if</span> (!token) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'No token provided'</span> });

  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = { <span class="hljs-attr">id</span>: decoded.id, <span class="hljs-attr">email</span>: decoded.email };
    next();
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-keyword">const</span> msg = err.name === <span class="hljs-string">'TokenExpiredError'</span> ? <span class="hljs-string">'Access token expired'</span> : <span class="hljs-string">'Invalid token'</span>;
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: msg });
  }
}

<span class="hljs-built_in">module</span>.exports = auth;
</code></pre>
<p>How this works:</p>
<ul>
<li><p>The access token can live in a cookie named <code>access_token</code>.</p>
</li>
<li><p>Mark the cookie as <code>httpOnly</code> and <code>secure</code> in production.</p>
</li>
<li><p>Set <code>sameSite: 'strict'</code> to reduce CSRF risk.</p>
</li>
<li><p>For APIs used by browsers, cookies simplify sending tokens. For SPAs that call many domains, an <code>Authorization</code> header may be simpler.</p>
</li>
</ul>
<p>In the next section, we’ll use the same cookie approach for the refresh token. That section explains why refresh belongs in a cookie and how rotation blocks replay.</p>
<h2 id="heading-refresh-tokens-and-rotation">Refresh Tokens and Rotation</h2>
<p>Access tokens are short-lived and used on every request. They prove the user identity quickly. Refresh tokens live longer and are used only to get new access tokens when the old ones expire. This split keeps day-to-day requests fast and limits the damage if a token leaks.</p>
<p>We will store the refresh token in an HTTP-only cookie. This reduces exposure to scripts and keeps the flow smooth.</p>
<h3 id="heading-1-install-and-setup">1. Install and Setup</h3>
<p>We already have <code>cookie-parser</code>. We won’t add anything new for now, but we will use <a target="_blank" href="https://nodejs.org/api/crypto.html">Node’s built-in <code>crypto</code> module</a> to hash the refresh token before storing it. As a reminder, hashing means the raw token is never saved. If the database leaks, attackers cannot use the hashes to log in.</p>
<p>Create <code>models/refreshToken.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>);

<span class="hljs-keyword">const</span> refreshTokenSchema = <span class="hljs-keyword">new</span> mongoose.Schema({
  <span class="hljs-attr">user</span>: { <span class="hljs-attr">type</span>: mongoose.Schema.Types.ObjectId, <span class="hljs-attr">ref</span>: <span class="hljs-string">'User'</span>, <span class="hljs-attr">index</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-attr">tokenHash</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-attr">jti</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">index</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-attr">expiresAt</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Date</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">index</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-attr">revokedAt</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Date</span>, <span class="hljs-attr">default</span>: <span class="hljs-literal">null</span> },
  <span class="hljs-attr">replacedBy</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">default</span>: <span class="hljs-literal">null</span> }, <span class="hljs-comment">// new jti when rotated</span>
  <span class="hljs-attr">createdAt</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">Date</span>, <span class="hljs-attr">default</span>: <span class="hljs-built_in">Date</span>.now },
  <span class="hljs-attr">ip</span>: <span class="hljs-built_in">String</span>,
  <span class="hljs-attr">userAgent</span>: <span class="hljs-built_in">String</span>
});

<span class="hljs-built_in">module</span>.exports = mongoose.model(<span class="hljs-string">'RefreshToken'</span>, refreshTokenSchema);
</code></pre>
<h3 id="heading-2-token-helpers">2. Token Helpers</h3>
<p>Create <code>utils/tokens.js</code> for clean, reusable logic.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);
<span class="hljs-keyword">const</span> crypto = <span class="hljs-built_in">require</span>(<span class="hljs-string">'crypto'</span>);
<span class="hljs-keyword">const</span> RefreshToken = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../models/refreshToken'</span>);

<span class="hljs-keyword">const</span> ACCESS_TTL = <span class="hljs-string">'15m'</span>;
<span class="hljs-keyword">const</span> REFRESH_TTL_SEC = <span class="hljs-number">60</span> * <span class="hljs-number">60</span> * <span class="hljs-number">24</span> * <span class="hljs-number">7</span>; <span class="hljs-comment">// 7 days</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hashToken</span>(<span class="hljs-params">token</span>) </span>{
  <span class="hljs-keyword">return</span> crypto.createHash(<span class="hljs-string">'sha256'</span>).update(token).digest(<span class="hljs-string">'hex'</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createJti</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> crypto.randomBytes(<span class="hljs-number">16</span>).toString(<span class="hljs-string">'hex'</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">signAccessToken</span>(<span class="hljs-params">user</span>) </span>{
  <span class="hljs-keyword">const</span> payload = { <span class="hljs-attr">id</span>: user._id.toString(), <span class="hljs-attr">email</span>: user.email };
  <span class="hljs-keyword">return</span> jwt.sign(payload, process.env.JWT_SECRET, { <span class="hljs-attr">expiresIn</span>: ACCESS_TTL });
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">signRefreshToken</span>(<span class="hljs-params">user, jti</span>) </span>{
  <span class="hljs-keyword">const</span> payload = { <span class="hljs-attr">id</span>: user._id.toString(), jti };
  <span class="hljs-keyword">const</span> token = jwt.sign(payload, process.env.REFRESH_TOKEN_SECRET, { <span class="hljs-attr">expiresIn</span>: REFRESH_TTL_SEC });
  <span class="hljs-keyword">return</span> token;
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">persistRefreshToken</span>(<span class="hljs-params">{ user, refreshToken, jti, ip, userAgent }</span>) </span>{
  <span class="hljs-keyword">const</span> tokenHash = hashToken(refreshToken);
  <span class="hljs-keyword">const</span> expiresAt = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-built_in">Date</span>.now() + REFRESH_TTL_SEC * <span class="hljs-number">1000</span>);
  <span class="hljs-keyword">await</span> RefreshToken.create({ <span class="hljs-attr">user</span>: user._id, tokenHash, jti, expiresAt, ip, userAgent });
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setRefreshCookie</span>(<span class="hljs-params">res, refreshToken</span>) </span>{
  <span class="hljs-keyword">const</span> isProd = process.env.NODE_ENV === <span class="hljs-string">'production'</span>;
  res.cookie(<span class="hljs-string">'refresh_token'</span>, refreshToken, {
    <span class="hljs-attr">httpOnly</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">secure</span>: isProd,
    <span class="hljs-attr">sameSite</span>: <span class="hljs-string">'strict'</span>,
    <span class="hljs-attr">path</span>: <span class="hljs-string">'/api/auth/refresh'</span>,
    <span class="hljs-attr">maxAge</span>: REFRESH_TTL_SEC * <span class="hljs-number">1000</span>
  });
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">rotateRefreshToken</span>(<span class="hljs-params">oldDoc, user, req, res</span>) </span>{
  <span class="hljs-comment">// revoke old</span>
  oldDoc.revokedAt = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
  <span class="hljs-keyword">const</span> newJti = createJti();
  oldDoc.replacedBy = newJti;
  <span class="hljs-keyword">await</span> oldDoc.save();

  <span class="hljs-comment">// issue new</span>
  <span class="hljs-keyword">const</span> newAccess = signAccessToken(user);
  <span class="hljs-keyword">const</span> newRefresh = signRefreshToken(user, newJti);
  <span class="hljs-keyword">await</span> persistRefreshToken({
    user,
    <span class="hljs-attr">refreshToken</span>: newRefresh,
    <span class="hljs-attr">jti</span>: newJti,
    <span class="hljs-attr">ip</span>: req.ip,
    <span class="hljs-attr">userAgent</span>: req.headers[<span class="hljs-string">'user-agent'</span>] || <span class="hljs-string">''</span>
  });
  setRefreshCookie(res, newRefresh);
  <span class="hljs-keyword">return</span> { <span class="hljs-attr">accessToken</span>: newAccess };
}

<span class="hljs-built_in">module</span>.exports = {
  hashToken,
  createJti,
  signAccessToken,
  signRefreshToken,
  persistRefreshToken,
  setRefreshCookie,
  rotateRefreshToken
};
</code></pre>
<p>In this code,</p>
<ul>
<li><p>signAccessToken creates a short token with the user ID and email.</p>
</li>
<li><p>signRefreshToken creates a long-lived token with a jti value. The jti lets us rotate and track tokens.</p>
</li>
<li><p>persistRefreshToken hashes the refresh token and stores metadata like expiry and device info.</p>
</li>
<li><p>setRefreshCookie writes the HTTP-only cookie so the browser sends it to the refresh endpoint automatically.</p>
</li>
<li><p>rotateRefreshToken revokes the old token, issues a new pair, and saves the new record. Rotation blocks replay if an old refresh token is stolen.</p>
</li>
</ul>
<h3 id="heading-3-issue-refresh-token-on-login">3. Issue Refresh Token on Login</h3>
<p>Update your <code>routes/auth.js</code> login handler to create and store a refresh token, then set the cookie.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> bcrypt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'bcryptjs'</span>);
<span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);
<span class="hljs-keyword">const</span> User = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../models/user'</span>);
<span class="hljs-keyword">const</span> RefreshToken = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../models/refreshToken'</span>);
<span class="hljs-keyword">const</span> {
  createJti,
  signAccessToken,
  signRefreshToken,
  persistRefreshToken,
  setRefreshCookie
} = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../utils/tokens'</span>);

<span class="hljs-keyword">const</span> router = express.Router();

router.post(<span class="hljs-string">'/login'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { email, password } = req.body;

    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findOne({ email });
    <span class="hljs-keyword">if</span> (!user) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Invalid credentials'</span> });

    <span class="hljs-keyword">const</span> isMatch = <span class="hljs-keyword">await</span> bcrypt.compare(password, user.password);
    <span class="hljs-keyword">if</span> (!isMatch) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Invalid credentials'</span> });

    <span class="hljs-keyword">const</span> accessToken = signAccessToken(user);

    <span class="hljs-keyword">const</span> jti = createJti();
    <span class="hljs-keyword">const</span> refreshToken = signRefreshToken(user, jti);

    <span class="hljs-keyword">await</span> persistRefreshToken({
      user,
      refreshToken,
      jti,
      <span class="hljs-attr">ip</span>: req.ip,
      <span class="hljs-attr">userAgent</span>: req.headers[<span class="hljs-string">'user-agent'</span>] || <span class="hljs-string">''</span>
    });

    setRefreshCookie(res, refreshToken);

    res.json({ accessToken });
  } <span class="hljs-keyword">catch</span> (err) {
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Server error'</span> });
  }
});

<span class="hljs-built_in">module</span>.exports = router;
</code></pre>
<p>On login, we issue both tokens. The access token goes to the JSON response. The refresh token goes to an HTTP-only cookie scoped to <code>/api/auth/refresh</code>. This keeps the refresh token away from frontend code while still letting the browser send it to the refresh endpoint.</p>
<h3 id="heading-4-the-refresh-endpoint">4. The Refresh Endpoint</h3>
<p>Create an endpoint that reads the refresh cookie, verifies it, checks the database entry, and rotates it. If all checks pass, it returns a new access token and sets a new refresh cookie.</p>
<p>Add to <code>routes/auth.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { hashToken, rotateRefreshToken } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../utils/tokens'</span>);

router.post(<span class="hljs-string">'/refresh'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> token = req.cookies?.refresh_token;
    <span class="hljs-keyword">if</span> (!token) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'No refresh token'</span> });

    <span class="hljs-keyword">let</span> decoded;
    <span class="hljs-keyword">try</span> {
      decoded = jwt.verify(token, process.env.REFRESH_TOKEN_SECRET);
    } <span class="hljs-keyword">catch</span> (err) {
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Invalid or expired refresh token'</span> });
    }

    <span class="hljs-keyword">const</span> tokenHash = hashToken(token);
    <span class="hljs-keyword">const</span> doc = <span class="hljs-keyword">await</span> RefreshToken.findOne({ tokenHash, <span class="hljs-attr">jti</span>: decoded.jti }).populate(<span class="hljs-string">'user'</span>);

    <span class="hljs-keyword">if</span> (!doc) {
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Refresh token not recognized'</span> });
    }
    <span class="hljs-keyword">if</span> (doc.revokedAt) {
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Refresh token revoked'</span> });
    }
    <span class="hljs-keyword">if</span> (doc.expiresAt &lt; <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>()) {
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Refresh token expired'</span> });
    }

    <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> rotateRefreshToken(doc, doc.user, req, res);
    <span class="hljs-keyword">return</span> res.json({ <span class="hljs-attr">accessToken</span>: result.accessToken });
  } <span class="hljs-keyword">catch</span> (err) {
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Server error'</span> });
  }
});
</code></pre>
<p>The refresh endpoint verifies the cookie, checks the database record, confirms it is not expired or revoked, then rotates it. Rotation sets <code>revokedAt</code> on the old record and creates a new one with a fresh <code>jti</code>. The response returns a new access token and sets a new refresh cookie.</p>
<h3 id="heading-5-logout-and-revoke">5. Logout and Revoke</h3>
<p>On logout, revoke the current refresh token and clear the cookie.</p>
<pre><code class="lang-js">router.post(<span class="hljs-string">'/logout'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> token = req.cookies?.refresh_token;
    <span class="hljs-keyword">if</span> (token) {
      <span class="hljs-keyword">const</span> tokenHash = hashToken(token);
      <span class="hljs-keyword">const</span> doc = <span class="hljs-keyword">await</span> RefreshToken.findOne({ tokenHash });
      <span class="hljs-keyword">if</span> (doc &amp;&amp; !doc.revokedAt) {
        doc.revokedAt = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
        <span class="hljs-keyword">await</span> doc.save();
      }
    }
    res.clearCookie(<span class="hljs-string">'refresh_token'</span>, { <span class="hljs-attr">path</span>: <span class="hljs-string">'/api/auth/refresh'</span> });
    res.json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Logged out'</span> });
  } <span class="hljs-keyword">catch</span> (err) {
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Server error'</span> });
  }
});
</code></pre>
<p>Logout revokes the matching refresh token if present and clears the cookie. This ends the session cleanly on the server side and the client side.</p>
<h3 id="heading-6-client-flow">6. Client Flow</h3>
<p>Here is how the browser app should behave:</p>
<ul>
<li><p>Keep the access token in memory. Do not put it in localStorage.</p>
</li>
<li><p>Call protected APIs with the <code>Authorization</code> header or let cookies handle it if you chose the cookie approach for access.</p>
</li>
<li><p>If a call fails with <code>Access token expired</code>, call <code>/api/auth/refresh</code>. The browser sends the refresh cookie automatically.</p>
</li>
<li><p>Replace the in-memory access token with the new one.</p>
</li>
<li><p>Retry the original request.</p>
</li>
<li><p>On logout, call <code>/api/auth/logout</code> and clear any local state.</p>
</li>
</ul>
<h3 id="heading-7-security-notes">7. Security Notes</h3>
<p>There are some key steps you can take to make sure everything is secure:</p>
<h4 id="heading-separate-secrets">Separate secrets</h4>
<p>Use a different secret for access and refresh tokens. If the access secret leaks, refresh tokens still use a different key. Set <code>JWT_SECRET</code> and <code>REFRESH_TOKEN_SECRET</code> in <code>.env</code>.</p>
<h4 id="heading-https-only">HTTPS only</h4>
<p>Serve production traffic over HTTPS. Cookies marked <code>secure: true</code> only travel over HTTPS. This protects tokens in transit.</p>
<h4 id="heading-rotate-on-every-refresh">Rotate on every refresh</h4>
<p>Issue a new refresh token and revoke the old one each time you refresh. Rotation makes a stolen old token useless after the next refresh.</p>
<h4 id="heading-hash-refresh-tokens-in-the-database">Hash refresh tokens in the database</h4>
<p>Store a SHA-256 hash, not the raw token. This way a database leak does not give attackers the actual token string.</p>
<h4 id="heading-scope-and-flags-for-cookies">Scope and flags for cookies</h4>
<p>Use <code>httpOnly: true</code>, <code>secure: true</code> in production, <code>sameSite: 'strict'</code>, and a narrow <code>path</code> such as <code>/api/auth/refresh</code>. These flags reduce XSS and CSRF risk and limit where the cookie is sent.</p>
<h4 id="heading-short-access-ttl-and-moderate-refresh-ttl">Short access TTL and moderate refresh TTL</h4>
<p>Keep access tokens short, such as 15 minutes. Use a refresh lifetime like 7 days. This keeps risk low without annoying users.</p>
<h4 id="heading-device-awareness">Device awareness</h4>
<p>Store <code>ip</code> and <code>userAgent</code>. If patterns change in a suspicious way, you can revoke or challenge the session.</p>
<h4 id="heading-auditing-and-limits">Auditing and limits</h4>
<p>Log refresh events and consider rate limits on the refresh endpoint. This helps detect abuse.’</p>
<p>Add to <code>.env</code>:</p>
<pre><code class="lang-plaintext">REFRESH_TOKEN_SECRET=your_refresh_secret_key
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You now have a working authentication system that uses JWTs and refresh tokens to keep users logged in safely. The access token handles quick verification. The refresh token quietly renews access when it expires. Together, they strike a balance between security and convenience.</p>
<p>You built user registration, login, protected routes, and a full refresh flow. You also learned how to rotate refresh tokens, store them securely, and handle logout cleanly. Each step adds another layer of safety that keeps your app and users protected.</p>
<p>From here, you can expand this setup to match your real project. You can add role-based permissions, track user sessions by device, or move the logic into a dedicated authentication service. What matters most is understanding the flow and keeping tokens short-lived and well-guarded.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The JSON Web Token Handbook: Learn to Use JWTs for Web Authentication ]]>
                </title>
                <description>
                    <![CDATA[ JWT stands for JSON Web Token, and it’s one of those terms you’ll constantly come across in modern web development. At its core, a JWT is a JSON-based open standard format that allows you to represent specific claims securely between two parties. The... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-json-web-token-handbook-learn-to-use-jwts-for-web-authentication/</link>
                <guid isPermaLink="false">68e6ab03a5598a61a63ce39d</guid>
                
                    <category>
                        <![CDATA[ JSON Web Tokens (JWT) ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JWT ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ token ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sumit Saha ]]>
                </dc:creator>
                <pubDate>Wed, 08 Oct 2025 18:18:43 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759947512495/9c8aee78-1a83-4958-8c01-110e2247286d.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>JWT stands for JSON Web Token, and it’s one of those terms you’ll constantly come across in modern web development.</p>
<p>At its core, a JWT is a JSON-based open standard format that allows you to represent specific claims securely between two parties. The exciting part is how widely JWT is used, especially in microservice architectures and modern authentication systems.</p>
<p>In this article, we’ll break down what JWTs really are, explore their structure, and see exactly how they help secure web applications. By the end, you’ll understand why developers rely on JWTs every single day.</p>
<h2 id="heading-heres-what-well-cover">Here’s What We’ll Cover</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-jwt">What is a JWT?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-do-we-need-tokens">Why Do We Need Tokens?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-session-tokens-the-classic-approach">Session Tokens: The Classic Approach</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-jwt-the-modern-solution">JWT: The Modern Solution</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-jwt-structure-header-payload-amp-signature">JWT Structure: Header, Payload &amp; Signature</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-decoding-a-jwt">Example: Decoding a JWT</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-jwts-ensure-security-the-signature">How JWTs Ensure Security: The Signature</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-security-considerations-and-token-management">Security Considerations and Token Management</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-jwts-in-different-languages">How to Create JWTs in Different Languages</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-practical-implementation-jwt-authentication-with-express-mongodb">Practical Implementation: JWT Authentication with Express + MongoDB</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-project-setup-amp-dependencies">1. Project Setup &amp; Dependencies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-project-folder-structure">2. Project Folder Structure</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-step-by-step-implementation">3. Step-by-Step Implementation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-how-to-test-your-api">4. How to Test Your API</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-final-words">Final Words</a></p>
</li>
</ol>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>To follow along and get the most out of this guide, you should have:</p>
<ol>
<li><p>Basic familiarity with JavaScript / Node.js</p>
</li>
<li><p>Node.js and npm installed on your local machine</p>
</li>
<li><p>Basic understanding of HTTP and REST APIs</p>
</li>
<li><p>Understanding of JSON and how to parse/serialize it</p>
</li>
<li><p>Basic knowledge of Express (or ability to follow along)</p>
</li>
<li><p>A running instance of MongoDB (local or remote)</p>
</li>
<li><p>Experience with asynchronous code / Promises / async-await</p>
</li>
<li><p>Familiarity with environment variables / .env setup</p>
</li>
</ol>
<p>I’ve also created a video to go along with this article. If you’re the type who likes to learn from video as well as text, you can check it out here:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/6drpx_QcMdg" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-what-is-a-jwt">What is a JWT?</h2>
<p>JWTs are most commonly used for authentication today, but that wasn’t actually their original purpose. They were created to provide a standard way for two parties to securely exchange information. In fact, there’s even an industry standard specification (<a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc7519">RFC 7519</a>) that lays out exactly how JWTs should be structured and how they’re meant to be used for data exchange. Think of it like <a target="_blank" href="https://en.wikipedia.org/wiki/ECMAScript#:~:text=ECMAScript%20\(%2F%CB%88%C9%9Bkm,pages%20across%20different%20web%20browsers.">ECMAScript</a>, or ES, which defines the standard for JavaScript.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525281325/62565bc2-dc09-4565-8e5b-12b6333e6ff6.jpeg" alt="Client Server Secure Communication" class="image--center mx-auto" width="1919" height="1080" loading="lazy"></p>
<p>In real-world applications, JWTs are primarily used for authentication, and that’s the angle we’ll focus on in this article.</p>
<p>But remember that JWTs weren’t designed only for authentication. There are other ways to handle authentication too, and one of the most popular alternatives is session tokens.</p>
<h2 id="heading-why-do-we-need-tokens">Why Do We Need Tokens?</h2>
<p>Whatever authentication strategy we use, whether it’s a session token or a JWT, the underlying reason is the same: the stateless nature of the HTTP protocol.</p>
<p>When we exchange requests and responses from a browser to a server or between servers using HTTP, the protocol itself does not retain any information.</p>
<p><em>Stateless</em> means that during interactions between the client and the server, HTTP doesn’t remember any previous requests or data. In other words, every request must carry all the necessary information separately. HTTP doesn’t store any data on its own. Once it receives information, it forgets it. That’s why we say HTTP is stateless, as it has no inherent state or persistent information.</p>
<p>Think of it this way: when we access a webpage from a server, what information do we actually send to the server? If it’s a simple static website, we don’t need to send much. We just send the URL of the page to the server, and the server responds by delivering the corresponding HTML page. This means the server doesn’t need to remember any information or maintain any state, which is exactly how HTTP is designed to work, because HTTP itself is stateless.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525352836/7e6081f5-7d34-462a-9a7d-bcffd0242e00.jpeg" alt="Simple HTML Response from a Static Website" class="image--center mx-auto" width="1919" height="1080" loading="lazy"></p>
<p>But if the web application provides different responses for each user – in other words, if the website is dynamic – then sending only the URL is not sufficient. The user must also send their identity along with the URL to the server.</p>
<p>For example, if a user wants to access <code>page-1</code>, they must tell the server: “<em>I am User A, please give me page-1.</em>” The server will then respond with <code>page-1</code> accordingly. But next time, if the user requests, “<em>Now give me page-2</em>”, what will the server do? Since HTTP is stateless, if the request doesn’t include the user’s identity, the server won’t know which response to provide. This means that with every request, the user must provide their identity, right?</p>
<p>But if we look at the websites around us, do we really have to provide our identity every single time? Take Facebook as an example. Once we authenticate and log in, the server shows us the homepage when we request it, or our profile page when we request that, without requiring us to authenticate with every single request.</p>
<p>So the question is, if HTTP is stateless, how is this possible? How does the web application remember our browsing session? The answer is that, web applications can maintain sessions in different ways, and one of the most common methods is by using <strong>tokens</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525399836/7b7cdeab-4baa-4cda-bbeb-aaf4e4d4170c.jpeg" alt="How Server Remember our Browsing Session?" class="image--center mx-auto" width="1918" height="1077" loading="lazy"></p>
<h3 id="heading-session-tokens-the-classic-approach">Session Tokens: The Classic Approach</h3>
<p>There are two popular options for this. One is a <strong>Session Token</strong>, and the other is a <strong>JSON Web Token (JWT)</strong>. Let’s understand both so that it becomes clear what JWTs are and why they’re used.</p>
<p>Imagine a scenario in a company’s customer care department. A customer calls in with a complaint. The customer support representative listens to the issue and tries various troubleshooting steps but is unable to resolve the problem.</p>
<p>At this point, they forward the case to their higher management team and create a case file for the customer. This file contains all conversations with the customer and details of the troubleshooting attempts. The customer is then given a case ID or ticket ID, so that the next time they call, they don’t have to go through the same steps all over again.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525453002/c56bb7da-f6dd-4afe-b16b-966149bc7f91.jpeg" alt="Customer Care Scenerio 1 - Session Token Analogy" class="image--center mx-auto" width="1920" height="1080" loading="lazy"></p>
<p>The next day, when the customer calls again, they give their ticket ID to the customer care representative. The representative searches the system using that ticket ID, retrieves the details, and is able to respond accurately to the customer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525515798/426af5fa-ff38-4ce2-ae1b-48ca1a8f1e6c.jpeg" alt="Customer Care Scenerio 2 - Session Token Analogy" class="image--center mx-auto" width="1920" height="1080" loading="lazy"></p>
<p>This scenario illustrates how authentication works in a web application using a session token. When a user authenticates, the server creates a session and keeps track of it. A session ID is generated for that session and sent back to the user, similar to the support ticket in the earlier example. From then on, whenever the user sends a request to the server, they include this session ID or token. The server looks up the session using that ID and identifies the client. Since the server has to handle multiple clients, this session token method has become an effective and widely used strategy for authentication.</p>
<p>And how the client sends the session ID to the server can vary depending on the implementation. The most common method is to store the session ID in the browser’s cookies. The advantage of this approach is that whenever the browser sends a request to the same server, it automatically adds the cookie information to the request header. This is a built-in behaviour of browsers, so no extra steps are needed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525561275/5881de41-571d-40ca-a0f7-4022d8c41754.jpeg" alt="Session Token Example" class="image--center mx-auto" width="1920" height="1080" loading="lazy"></p>
<p>When the user authenticates, the server saves data in the browser’s cookie, and from then on, that cookie information is sent automatically with every request, allowing the server to recognize the user. This was a very popular method, although in modern applications it has become a bit outdated.</p>
<p>But this mechanism has some issues. The biggest problem is that it assumes there is only a single server. In modern web applications, there are usually multiple servers. In such cases, a load balancer sits in front and decides which server will handle the user’s request.</p>
<p>Let’s say the session token method is being used. When the user sends the first request, the load balancer forwards it to <code>Server-1</code>. <code>Server-1</code> creates a session ID and sends it back to the client. Later, when the user sends another request, the load balancer routes it to <code>Server-2</code>. But <code>Server-2</code> doesn’t have that session ID stored, so how will it know which user the request belongs to?</p>
<p>The common solution to this is to store session IDs not on a specific server but in a shared <a target="_blank" href="https://redis.io/">Redis</a> database, so that any server can verify the session ID from there. This is what’s called a <strong>Redis cache</strong>. But in a microservice architecture, this approach has a weakness. If for some reason the Redis cache goes down, the servers may still be running, but the authentication mechanism will fail. This is exactly where JSON Web Tokens come in, offering a slightly different approach.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525611999/a970e2d9-6663-4a4e-9c63-37ea13470b90.jpeg" alt="Session Token Handling Multiple Servers with Redis Cache" class="image--center mx-auto" width="1920" height="1080" loading="lazy"></p>
<h3 id="heading-jwt-the-modern-solution">JWT: The Modern Solution</h3>
<p>Let’s revisit the customer care department example. This time, imagine there’s no phone or system. The customer comes directly to the office and meets the support agent in person. Since the agent doesn’t have any system this time, they can’t store all the information like before. Instead, they write everything down on a piece of paper and tell the customer, “<em>Next time you come, bring this with you.</em>”</p>
<p>This means the method is a bit different from the previous concept, right? But there’s still a problem: “<strong>validity</strong>”. If the customer isn’t legitimate and acts maliciously, how can the support representative trust them? The next day, if the customer comes in with the same information written on a blank sheet of paper, how can the agent verify the validity of their identity?</p>
<p>In this case, a possible solution is for the customer care executive to sign the paper when giving it to the customer. Then, when the customer brings the paper back, the support representative can verify the signature and confidently provide the service.</p>
<p>JSON Web Tokens work in a similar way. Here, when the client authenticates, instead of the server saving all the information, it sends all the user’s information as a JSON token along with a signature. Later, with each subsequent request, the client sends the entire token along with the request, which contains information like which user it is, their name, and other necessary details.</p>
<p>In this case, the server doesn’t save anything, and all the information stays with the client. Each time the client sends a request with this token, the server can read it, identify which user made the request, and provide the necessary data.</p>
<p>This token is not just a simple ID. It’s a JSON object containing all the information, and this is what we call a JSON Web Token. How the client stores this JWT is entirely up to the client. The most common methods are storing it in the browser’s cookies or local storage.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525648690/691848c9-e4c2-4b3f-b3f5-06623627e38f.jpeg" alt="JSON Web Token Analogy" class="image--center mx-auto" width="1920" height="1080" loading="lazy"></p>
<h3 id="heading-jwt-structure-header-payload-amp-signature">JWT Structure: Header, Payload, &amp; Signature</h3>
<p>As mentioned, the server receives a JSON object, but a JWT doesn’t look like a regular JSON.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525702339/f74219b8-4a01-4ac4-920b-449faf103520.png" alt="JWT Structure" class="image--center mx-auto" width="1920" height="1078" loading="lazy"></p>
<p>In the image above, it may seem a bit unusual. In fact, it’s an encoded version of the JSON object, a kind of scrambled or compact representation. If you look closely, you’ll see that a JWT is divided into three parts, separated by dots. The first part is the <strong>header</strong>, the second part is the <strong>JSON payload,</strong> which essentially holds our data, and the third part is the <strong>signature</strong>.</p>
<p>If we examine each part individually:</p>
<ul>
<li><p>The <strong>header</strong> is a separate JSON object.</p>
</li>
<li><p>The <strong>payload</strong> is also a separate JSON object containing our data.</p>
</li>
<li><p>The third part is the <strong>signature</strong>.</p>
</li>
</ul>
<p>But what does the signature mean here? Simply put, the signature is a hash value. Our data is hashed using a secret key to create the signature. This secret key is kept on the server. So, when this JSON Web Token is sent to the server, the server can use that secret key to verify the signature. This ensures that the token is valid and has not been tampered with.</p>
<h2 id="heading-example-decoding-a-jwt">Example: Decoding a JWT</h2>
<p>Let’s look at an example. The best website for working with JWTs and understanding their structure is <a target="_blank" href="http://jwt.io">jwt.io</a><a target="_blank" href="https://jwt.io/">.</a> If you paste a JWT into the site, three sections appear: the header, payload, and signature. The payload is shown in the “Decoded Payload” section, which contains content and data. You’ll see there’s an ID, a JSON object with a name, and an expiration time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525738886/84c2532f-dc09-4a96-83de-ecd4a24d958f.jpeg" alt="Decoding a JWT" class="image--center mx-auto" width="636" height="367" loading="lazy"></p>
<p>The header is also a completely valid JSON object, which specifies an algorithm and shows the type –essentially indicating which algorithm will be used to create or verify this JWT.</p>
<p>So, the main data is in the “Decoded Payload” section, and the third part is the signature. Now there’s an important point to note: you might wonder where this scrambled-looking token comes from. It’s actually very simple. The data in the “Decoded Payload” is <strong>Base64 encoded</strong>, and that’s what forms the appearance of this scrambled token.</p>
<p>If you copy this part of the JWT and paste it into any online Base64 decoder, you’ll immediately see the data.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525794705/4ee950a2-2ad0-40b4-8287-fdfea9543a6f.png" alt="Base64 Encode Decode" class="image--center mx-auto" width="1919" height="1080" loading="lazy"></p>
<p>What does this mean? It means that if this data is encoded again using Base64, the same token will be generated. The header works the same way as well.</p>
<p>And the final point: the scrambled or encoded part. Is it done for security? No, it’s not for security. It’s done purely for convenience. JSON objects can be quite large, and not all programming languages handle them in the same way. In JavaScript it’s easy, but in other languages, it can sometimes cause issues. So to make it easier to handle, the data is Base64 encoded. This is not for security, as encoding it like this doesn’t make the data secure, because the information can still be viewed publicly.</p>
<p>As you can see in the diagram above, the moment you enter it on this site, your data is immediately visible. This means that no sensitive information should be stored here, only user identification details, like a user ID or other public information. <strong>Passwords or any secret keys should never be stored in the token, because they can be easily read.</strong> Even though it looks scrambled or encoded, it is actually public.</p>
<h2 id="heading-how-jwts-ensure-security-the-signature">How JWTs Ensure Security: The Signature</h2>
<p>Now let’s move to the security part, which is ensured by the signature. In our earlier paper example, a person could simply add a signature by hand.</p>
<p>But for data, the process of creating a signature is different. For data, the signature is created cryptographically using a secret key, which is the actual signature. The process of creating the signature is as follows:</p>
<ol>
<li><p>The data is Base64 encoded.</p>
</li>
<li><p>It is concatenated with the secret key.</p>
</li>
<li><p>It is encoded again in Base64.</p>
</li>
</ol>
<p>The configuration specifies an algorithm. This algorithm can be changed, but the same algorithm used to create the token must be used to verify it. In other words, the algorithm for generating and verifying the token must always be the same.</p>
<p>Finally, the data is hashed using a secret key. This secret key is not available to the public. Instead, it’s kept only on the server, usually stored securely in a server vault. When this JWT reaches the server, the server uses the secret key to verify whether the token is valid. If it doesn’t match correctly, it will display “invalid signature.” This ensures that the server can confirm whether the token has been tampered with and that its integrity is intact.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525829955/bf017016-d9fd-43cb-836a-eafe4f35540b.jpeg" alt="The Big Formula" class="image--center mx-auto" width="1224" height="1078" loading="lazy"></p>
<p>For example, if you use <code>love-you-all-from-logicbaselabs</code> as the signature, and the server verifies it, it will show “<em>signature verified</em>”. This demonstrates that the secret key exists only on the server. This ensures that even though public information is displayed, the token’s validity can be confirmed.</p>
<p>JSON Web Tokens aren’t like a password, though. They primarily serve to identify the user. The server can check the JWT to determine whether it belongs to a valid user. In other words, the JWT represents the user’s identity. It’s a very important token, containing secure content along with the signature.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759525873387/a434b453-0a38-41a5-93f3-bd12b46806f3.jpeg" alt="Signature Verification" class="image--center mx-auto" width="1920" height="1078" loading="lazy"></p>
<h2 id="heading-security-considerations-and-token-management">Security Considerations and Token Management</h2>
<p>One important thing to remember: if someone gets hold of your JWT, meaning they have the exact same token, they can easily log in as that user. They just need to send requests with that token to gain the necessary access.</p>
<p>You could think of it like this: if someone gets hold of your Facebook password, they can log in to your Facebook account. Similarly, if someone obtains your PayPal account PIN, they can easily access your account. In other words, if someone gets hold of your most secure information, there’s no way to protect it.</p>
<p>The same applies to JWTs: keeping the token safely on the client side is absolutely crucial. In this regard, we are somewhat vulnerable.</p>
<p>There is, though, one key difference. In the case of session tokens, if we assume an account has been compromised, the server can invalidate that session. In other words, no one can log in using that session ID anymore.</p>
<p>But with a JWT, the token remains valid until its expiration time. So there’s no direct way to invalidate it. Since the token is cryptographically self-contained and signed with the server’s secret key, once it’s created, it cannot be directly revoked by the server.</p>
<p>The only way to handle this is what’s done on the web: denylisting the token. In other words, the server maintains a separate database listing all JWT tokens that are denylisted. Whenever a request comes in, the server first verifies whether the token is valid. Then, through middleware, it checks whether the token is on the denylist. Only if it’s not on that list is the user allowed access.</p>
<p>So, these are the rules for using JSON Web Tokens. JWTs can be used in any programming language, especially in the context of REST APIs. They are extremely popular and widely used in microservice architectures.</p>
<h2 id="heading-how-to-create-jwts-in-different-languages">How to Create JWTs in Different Languages</h2>
<p>How you create a JWT depends on the programming language you’re using. For example, in Node.js, there are specialized libraries available, like <a target="_blank" href="https://www.npmjs.com/package/jsonwebtoken">jsonwebtoken</a>, so it’s straightforward. And in PHP, there are easy-to-use options for creating JWTs as well. So, JWTs are a universal tool, not limited to any specific programming language. Many people think they’re only for JavaScript, but that’s not true.</p>
<p>And remember that JWTs aren’t just used for authentication purposes. You can use them to represent any kind of identity. For example, if you’re going to a concert, access could be granted using a JWT instead of a regular ticket. When your client uses that JWT, the gateway or server can read the token, provide access to the information, and verify it using the signature.</p>
<h2 id="heading-practical-implementation-jwt-authentication-with-express-mongodb">Practical Implementation: JWT Authentication with Express + MongoDB</h2>
<p>In this section, we will put into practice all the concepts we have learned so far. Using <a target="_blank" href="https://www.freecodecamp.org/news/the-express-handbook/"><strong>Express.js</strong></a> and <a target="_blank" href="https://www.freecodecamp.org/news/how-to-start-using-mongodb/"><strong>MongoDB</strong></a>, we will build a complete JWT authentication system step by step.</p>
<p>Don’t worry if it feels overwhelming at first. We will go carefully, one step at a time, and by the end, you will have a fully working project. Think of it as entering a building floor by floor: we’ll explore each section thoroughly and come out with a solid understanding.</p>
<h3 id="heading-1-project-setup-amp-dependencies">1. Project Setup &amp; Dependencies</h3>
<p>Before writing any code, we need to set up our Node.js project and install the required dependencies.</p>
<h4 id="heading-initialize-the-nodejs-project">Initialize the Node.js Project</h4>
<p>Open your terminal and run:</p>
<pre><code class="lang-javascript">mkdir jwt-auth-demo
cd jwt-auth-demo
npm init -y
</code></pre>
<p>This will create a <code>package.json</code> file with default settings.</p>
<h4 id="heading-install-dependencies">Install Dependencies</h4>
<p>We need some packages to build our JWT authentication system:</p>
<pre><code class="lang-javascript">npm install express mongoose bcryptjs jsonwebtoken dotenv
</code></pre>
<ul>
<li><p><code>express</code>: Fast and minimal Node.js web framework to create API routes.</p>
</li>
<li><p><code>mongoose</code>: ODM (Object Data Modeling) library to interact with MongoDB easily.</p>
</li>
<li><p><code>bcryptjs</code>: Library to hash and compare passwords securely.</p>
</li>
<li><p><code>jsonwebtoken</code>: Library to generate and verify JWT tokens.</p>
</li>
<li><p><code>dotenv</code>: Loads environment variables from a <code>.env</code> file to keep secrets secure.</p>
</li>
</ul>
<h4 id="heading-install-dev-dependencies-optional">Install Dev Dependencies (Optional)</h4>
<p>For development convenience, install <strong>nodemon</strong> to auto-restart the server on file changes:</p>
<pre><code class="lang-javascript">npm install --save-dev nodemon
</code></pre>
<p>Update <code>package.json</code> scripts:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"scripts"</span>: {
  <span class="hljs-string">"start"</span>: <span class="hljs-string">"node server.js"</span>,
  <span class="hljs-string">"dev"</span>: <span class="hljs-string">"nodemon server.js"</span>
}
</code></pre>
<ul>
<li><p><code>npm start</code> runs the server normally.</p>
</li>
<li><p><code>npm run dev</code> runs the server with auto-restart using <strong>nodemon</strong>.</p>
</li>
</ul>
<h3 id="heading-2-project-folder-structure">2. Project Folder Structure</h3>
<pre><code class="lang-javascript">jwt-auth-demo/
│
├── config/
│   └── db.js
│
├── controllers/
│   └── authController.js
│
├── middlewares/
│   └── authMiddleware.js
│
├── models/
│   └── User.js
│
├── routes/
│   └── auth.js
│
├── services/
│   ├── hashService.js
│   └── jwtService.js
│
├── .env
├── server.js
├── package.json
</code></pre>
<p><strong>What goes where?</strong></p>
<ul>
<li><p><code>config/</code>: Database connection and environment config.</p>
</li>
<li><p><code>controllers/</code>: Main logic for each endpoint.</p>
</li>
<li><p><code>middlewares/</code>: Functions that run before controllers (for example, auth checks).</p>
</li>
<li><p><code>models/</code>: Mongoose schemas.</p>
</li>
<li><p><code>routes/</code>: API endpoint definitions.</p>
</li>
<li><p><code>services/</code>: Reusable logic (hashing, JWT).</p>
</li>
<li><p><code>.env</code>: Secrets and config variables.</p>
</li>
<li><p><code>server.js</code>: Entry point of the app.</p>
</li>
</ul>
<h3 id="heading-3-step-by-step-implementation">3. Step-by-Step Implementation</h3>
<h4 id="heading-initialize-the-express-server">Initialize the Express Server</h4>
<p>Before doing anything complex, we need to set up a simple server using Express. Think of this as the heart of our application. This server will be responsible for listening to incoming requests (like user login or register) and sending back responses.</p>
<p><strong>File: server.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// server.js</span>

<span class="hljs-comment">// Import the express library to build our server</span>
<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);

<span class="hljs-comment">// Create an instance of express</span>
<span class="hljs-keyword">const</span> app = express();

<span class="hljs-comment">// Middleware to parse JSON request bodies (important for APIs)</span>
app.use(express.json());

<span class="hljs-comment">// Default route to test server</span>
app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  res.send(<span class="hljs-string">"Hello World! Your server is working 🚀"</span>);
});

<span class="hljs-comment">// Start the server on port 5000</span>
<span class="hljs-keyword">const</span> PORT = process.env.PORT || <span class="hljs-number">5000</span>;
app.listen(PORT, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Server running on http://localhost:<span class="hljs-subst">${PORT}</span>`</span>);
});
</code></pre>
<ul>
<li><p>We import Express and create an app instance.</p>
</li>
<li><p>We use middleware to parse JSON requests (important for APIs).</p>
</li>
<li><p>We define a simple route <code>/</code> to test if our server works.</p>
</li>
<li><p>We start the server on port 5000 and log a message when it's running.</p>
</li>
</ul>
<p>Now, let’s test it:</p>
<ul>
<li><p>Run <code>node server.js</code> or <code>npm run dev</code>.</p>
</li>
<li><p>Open your browser at <code>http://localhost:5000</code>.</p>
</li>
<li><p>You should see: <code>Hello World! Your server is working 🚀</code></p>
</li>
</ul>
<h4 id="heading-connect-mongodb-with-mongoose">Connect MongoDB with Mongoose</h4>
<p>In this step, we want to store users in a database. For that, we will use MongoDB. To interact with MongoDB in Node.js easily, we use Mongoose, which is an ODM library.</p>
<p><strong>File: config/db.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// config/db.js</span>

<span class="hljs-comment">// Import mongoose</span>
<span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">"mongoose"</span>);

<span class="hljs-comment">// Connect to MongoDB using environment variable</span>
<span class="hljs-keyword">const</span> connectDB = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> mongoose.connect(process.env.MONGO_URI, {
      <span class="hljs-attr">useNewUrlParser</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">useUnifiedTopology</span>: <span class="hljs-literal">true</span>,
    });
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"✅ MongoDB Connected"</span>);
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"❌ MongoDB Connection Error:"</span>, err.message);
    process.exit(<span class="hljs-number">1</span>); <span class="hljs-comment">// Stop server if DB fails</span>
  }
};

<span class="hljs-built_in">module</span>.exports = connectDB;
</code></pre>
<p>Now our server is connected to MongoDB. Whenever we insert, update, or query data, it will go into this database.</p>
<p><strong>File: .env</strong></p>
<pre><code class="lang-javascript">PORT=<span class="hljs-number">5000</span>
MONGO_URI=mongodb:<span class="hljs-comment">//127.0.0.1:27017/jwt-auth-demo</span>
JWT_SECRET=your_super_secret_key
</code></pre>
<p>The .env file stores sensitive information like your database URI, JWT secret, and server port. By using environment variables, you can keep secrets out of your code and easily change configuration without modifying your source files. Never commit .env to public repositories to protect your credentials.</p>
<h4 id="heading-create-user-model">Create User Model</h4>
<p>In this step, we need to define how a User looks in our database. Each user will have a <strong>name, email, and password</strong>.</p>
<p><strong>File: models/User.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// models/User.js</span>
<span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">"mongoose"</span>);

<span class="hljs-comment">// Define a schema (blueprint of user data)</span>
<span class="hljs-keyword">const</span> userSchema = <span class="hljs-keyword">new</span> mongoose.Schema({
  <span class="hljs-attr">name</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-attr">email</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-attr">password</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span> },
});

<span class="hljs-comment">// Create and export the model</span>
<span class="hljs-built_in">module</span>.exports = mongoose.model(<span class="hljs-string">"User"</span>, userSchema);
</code></pre>
<p>As you can see, each user now has a name, email, and hashed password. This ensures that every user we save has these three fields.</p>
<h4 id="heading-hashing-amp-jwt-services">Hashing &amp; JWT Services</h4>
<p>In this step, we will handle password hashing and JWT management using separate services. This keeps our code organized and reusable.</p>
<p><strong>File: services/hashService.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">//services/hashService.js</span>

<span class="hljs-keyword">const</span> bcrypt = <span class="hljs-built_in">require</span>(<span class="hljs-string">"bcryptjs"</span>);

<span class="hljs-comment">// Function to hash a plain password</span>
<span class="hljs-built_in">exports</span>.hashPassword = <span class="hljs-keyword">async</span> (plainPassword) =&gt; {
  <span class="hljs-comment">// bcrypt.hash generates a hashed version of the password</span>
  <span class="hljs-comment">// The number 10 is the salt rounds, which affects the hashing complexity</span>
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> bcrypt.hash(plainPassword, <span class="hljs-number">10</span>);
};

<span class="hljs-comment">// Function to compare a plain password with a hashed password</span>
<span class="hljs-built_in">exports</span>.comparePassword = <span class="hljs-keyword">async</span> (plainPassword, hashedPassword) =&gt; {
  <span class="hljs-comment">// bcrypt.compare checks if the plain password matches the hashed one</span>
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> bcrypt.compare(plainPassword, hashedPassword);
};
</code></pre>
<ul>
<li><p><code>hashPassword(plainPassword)</code>: Takes a plain text password and returns a hashed version using bcrypt. Never store plain passwords directly.</p>
</li>
<li><p><code>comparePassword(plainPassword, hashedPassword)</code>: Compares a user-entered password with the hashed password stored in the database. Returns <code>true</code> if they match.</p>
</li>
</ul>
<p><strong>File: services/jwtService.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// services/jwtService.js</span>

<span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">"jsonwebtoken"</span>);

<span class="hljs-comment">// Function to generate a JWT</span>
<span class="hljs-built_in">exports</span>.generateToken = <span class="hljs-function">(<span class="hljs-params">payload</span>) =&gt;</span> {
  <span class="hljs-comment">// jwt.sign creates a signed token using our secret key from environment variables</span>
  <span class="hljs-comment">// expiresIn defines how long the token is valid (1 hour here)</span>
  <span class="hljs-keyword">return</span> jwt.sign(payload, process.env.JWT_SECRET, { <span class="hljs-attr">expiresIn</span>: <span class="hljs-string">"1h"</span> });
};

<span class="hljs-comment">// Function to verify a JWT</span>
<span class="hljs-built_in">exports</span>.verifyToken = <span class="hljs-function">(<span class="hljs-params">token</span>) =&gt;</span> {
  <span class="hljs-comment">// jwt.verify checks if the token is valid and not expired</span>
  <span class="hljs-keyword">return</span> jwt.verify(token, process.env.JWT_SECRET);
};
</code></pre>
<ul>
<li><p><code>generateToken(payload)</code>: Generates a JWT for a user. The <code>payload</code> typically contains user ID and email.</p>
</li>
<li><p><code>verifyToken(token)</code>: Verifies that the JWT is valid and returns the decoded payload if successful.</p>
</li>
<li><p>Using a separate JWT service keeps token logic centralized and easy to manage.</p>
</li>
</ul>
<h4 id="heading-auth-controller">Auth Controller</h4>
<p>In this step, we will handle all authentication-related logic in a separate controller. This keeps routes clean and separates business logic from endpoint definitions.</p>
<p><strong>File: controllers/authController.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// controllers/authController.js</span>

<span class="hljs-keyword">const</span> User = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../models/User"</span>);
<span class="hljs-keyword">const</span> { hashPassword, comparePassword } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../services/hashService"</span>);
<span class="hljs-keyword">const</span> { generateToken } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../services/jwtService"</span>);

<span class="hljs-comment">// Register new user</span>
<span class="hljs-built_in">exports</span>.register = <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { name, email, password } = req.body; <span class="hljs-comment">// Get user input</span>

    <span class="hljs-comment">// Step 1: Check if user already exists</span>
    <span class="hljs-keyword">const</span> existingUser = <span class="hljs-keyword">await</span> User.findOne({ email });
    <span class="hljs-keyword">if</span> (existingUser)
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"User already exists!"</span> });

    <span class="hljs-comment">// Step 2: Hash password using hashService</span>
    <span class="hljs-keyword">const</span> hashedPassword = <span class="hljs-keyword">await</span> hashPassword(password);

    <span class="hljs-comment">// Step 3: Save user to database</span>
    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">new</span> User({ name, email, <span class="hljs-attr">password</span>: hashedPassword });
    <span class="hljs-keyword">await</span> user.save();

    <span class="hljs-comment">// Step 4: Send success response</span>
    res.status(<span class="hljs-number">201</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"User registered successfully!"</span> });
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-comment">// Handle errors gracefully</span>
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">error</span>: err.message });
  }
};

<span class="hljs-comment">// Login user</span>
<span class="hljs-built_in">exports</span>.login = <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { email, password } = req.body; <span class="hljs-comment">// Get user input</span>

    <span class="hljs-comment">// Step 1: Find user by email</span>
    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findOne({ email });
    <span class="hljs-keyword">if</span> (!user)
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Invalid email or password"</span> });

    <span class="hljs-comment">// Step 2: Compare provided password with hashed password</span>
    <span class="hljs-keyword">const</span> isMatch = <span class="hljs-keyword">await</span> comparePassword(password, user.password);
    <span class="hljs-keyword">if</span> (!isMatch)
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Invalid email or password"</span> });

    <span class="hljs-comment">// Step 3: Generate JWT using jwtService</span>
    <span class="hljs-keyword">const</span> token = generateToken({ <span class="hljs-attr">id</span>: user._id, <span class="hljs-attr">email</span>: user.email });

    <span class="hljs-comment">// Step 4: Send success response with token</span>
    res.json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Login successful!"</span>, token });
  } <span class="hljs-keyword">catch</span> (err) {
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">error</span>: err.message });
  }
};

<span class="hljs-comment">// Protected profile route</span>
<span class="hljs-built_in">exports</span>.profile = <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-comment">// req.user is set by auth middleware after token verification</span>
  res.json({
    <span class="hljs-attr">message</span>: <span class="hljs-string">"Welcome to your profile!"</span>,
    <span class="hljs-attr">user</span>: req.user,
  });
};
</code></pre>
<ul>
<li><p><strong>File:</strong> <code>controllers/authController.js</code> – Contains all logic related to authentication.</p>
</li>
<li><p><code>exports.register</code> handles user registration:</p>
<ul>
<li><p>Checks if the user exists.</p>
</li>
<li><p>Hashes the password using <code>hashService</code>.</p>
</li>
<li><p>Saves the new user to MongoDB.</p>
</li>
<li><p>Returns a success message.</p>
</li>
</ul>
</li>
<li><p><code>exports.login</code> handles user login:</p>
<ul>
<li><p>Finds the user by email.</p>
</li>
<li><p>Compares passwords using <code>hashService.comparePassword</code>.</p>
</li>
<li><p>Generates a JWT token if valid.</p>
</li>
<li><p>Returns the token in the response.</p>
</li>
</ul>
</li>
<li><p><code>exports.profile</code> handles protected profile route:</p>
<ul>
<li>Returns user information from <code>req.user</code>, which is set by the auth middleware.</li>
</ul>
</li>
<li><p>Using a controller keeps route definitions clean and separates business logic from endpoint handling.</p>
</li>
</ul>
<h4 id="heading-auth-middleware">Auth Middleware</h4>
<p>In this step, we create a middleware to protect routes by verifying JWTs. Only authenticated users can access protected endpoints.</p>
<p><strong>File: middlewares/authMiddleware.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// middlewares/authMiddleware.js</span>

<span class="hljs-keyword">const</span> { verifyToken } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../services/jwtService"</span>);

<span class="hljs-comment">// Middleware to protect routes</span>
<span class="hljs-built_in">module</span>.exports = <span class="hljs-function">(<span class="hljs-params">req, res, next</span>) =&gt;</span> {
  <span class="hljs-comment">// Step 1: Get Authorization header</span>
  <span class="hljs-keyword">const</span> authHeader = req.headers[<span class="hljs-string">"authorization"</span>];
  <span class="hljs-keyword">if</span> (!authHeader)
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"No token provided"</span> });

  <span class="hljs-comment">// Step 2: Extract token from format 'Bearer &lt;token&gt;'</span>
  <span class="hljs-keyword">const</span> token = authHeader.split(<span class="hljs-string">" "</span>)[<span class="hljs-number">1</span>];
  <span class="hljs-keyword">if</span> (!token) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Malformed token"</span> });

  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Step 3: Verify token using jwtService</span>
    <span class="hljs-keyword">const</span> decoded = verifyToken(token);

    <span class="hljs-comment">// Step 4: Attach decoded user info to request object</span>
    req.user = decoded;

    <span class="hljs-comment">// Proceed to next middleware or route handler</span>
    next();
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-comment">// If token is invalid or expired</span>
    res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Invalid or expired token"</span> });
  }
};
</code></pre>
<ul>
<li><p><strong>File:</strong> <code>middlewares/authMiddleware.js</code> – Middleware for protecting routes.</p>
</li>
<li><p>Step 1: Checks if the <code>Authorization</code> header is present.</p>
</li>
<li><p>Step 2: Extracts the token from the <code>Bearer &lt;token&gt;</code> format.</p>
</li>
<li><p>Step 3: Verifies the token using <code>jwtService.verifyToken</code>.</p>
</li>
<li><p>Step 4: Attaches the decoded user info to <code>req.user</code> for use in subsequent route handlers.</p>
</li>
<li><p>If the token is missing, malformed, invalid, or expired, the middleware responds with <strong>401 Unauthorized</strong>. This ensures only authenticated users can access protected routes.</p>
</li>
</ul>
<h4 id="heading-auth-routes">Auth Routes</h4>
<p>In this step, we will define authentication-related routes and connect them with the controller and middleware.</p>
<p><strong>File: routes/auth.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// routes/auth.js</span>

<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> router = express.Router();
<span class="hljs-keyword">const</span> authController = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../controllers/authController"</span>);
<span class="hljs-keyword">const</span> authMiddleware = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../middlewares/authMiddleware"</span>);

<span class="hljs-comment">// Step 1: Register route</span>
<span class="hljs-comment">// Users send their name, email, and password to this endpoint</span>
router.post(<span class="hljs-string">"/register"</span>, authController.register);

<span class="hljs-comment">// Step 2: Login route</span>
<span class="hljs-comment">// Users send email and password to receive JWT</span>
router.post(<span class="hljs-string">"/login"</span>, authController.login);

<span class="hljs-comment">// Step 3: Protected profile route</span>
<span class="hljs-comment">// Only accessible to authenticated users with a valid JWT</span>
router.get(<span class="hljs-string">"/profile"</span>, authMiddleware, authController.profile);

<span class="hljs-built_in">module</span>.exports = router;
</code></pre>
<ul>
<li><p><strong>File:</strong> <code>routes/auth.js</code> – Central file to define authentication endpoints.</p>
</li>
<li><p><code>router.post("/register", authController.register)</code>: Handles user registration.</p>
</li>
<li><p><code>router.post("/login", authController.login)</code>: Handles user login and token generation.</p>
</li>
<li><p><code>router.get("/profile", authMiddleware, authController.profile)</code>: Protected route, requires JWT. The <code>authMiddleware</code> ensures only authenticated users can access it.</p>
</li>
<li><p>Using routes with controllers and middleware keeps the application organized and professional.</p>
</li>
</ul>
<h4 id="heading-main-server-file">Main Server File</h4>
<p>This is the main entry point of our application. It sets up the server, connects to the database, and mounts all routes.</p>
<p><strong>File: server.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// server.js</span>

<span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config(); <span class="hljs-comment">// Step 1: Load environment variables from .env</span>
<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> connectDB = <span class="hljs-built_in">require</span>(<span class="hljs-string">"./config/db"</span>);

<span class="hljs-keyword">const</span> app = express();

<span class="hljs-comment">// Step 2: Connect to MongoDB</span>
connectDB();

<span class="hljs-comment">// Step 3: Middleware to parse JSON request bodies</span>
app.use(express.json());

<span class="hljs-comment">// Step 4: Mount auth routes</span>
<span class="hljs-comment">// All auth-related routes will start with /api/auth</span>
app.use(<span class="hljs-string">"/api/auth"</span>, <span class="hljs-built_in">require</span>(<span class="hljs-string">"./routes/auth"</span>));

<span class="hljs-comment">// Step 5: Default route to test server</span>
app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  res.send(<span class="hljs-string">"Hello World! Your server is working 🚀"</span>);
});

<span class="hljs-comment">// Step 6: Start server on PORT from .env or default 5000</span>
<span class="hljs-keyword">const</span> PORT = process.env.PORT || <span class="hljs-number">5000</span>;
app.listen(PORT, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Server running on http://localhost:<span class="hljs-subst">${PORT}</span>`</span>);
});
</code></pre>
<ul>
<li><p><strong>Load environment variables:</strong> Using <code>dotenv</code> to keep secrets and configuration separate from code.</p>
</li>
<li><p><strong>Connect to MongoDB:</strong> Calls <code>connectDB()</code> from <code>config/db.js</code>.</p>
</li>
<li><p><strong>Middleware:</strong> <code>express.json()</code> allows Express to parse JSON request bodies.</p>
</li>
<li><p><strong>Mount routes:</strong> <code>app.use("/api/auth", ...)</code> registers all authentication routes.</p>
</li>
<li><p><strong>Default route:</strong> A simple GET endpoint to verify server is running.</p>
</li>
<li><p><strong>Start server:</strong> <code>app.listen</code> starts listening on the configured port.</p>
</li>
</ul>
<h3 id="heading-4-how-to-test-your-api">4. How to Test Your API</h3>
<p>In this section, you’ll learn how to test your JWT authentication API using tools like Postman or any HTTP client.</p>
<p>Before testing, make sure your server is running. If it’s not running, open a terminal and run:</p>
<pre><code class="lang-javascript">npm run dev
</code></pre>
<p>or</p>
<pre><code class="lang-javascript">node server.js
</code></pre>
<p>This will start your server on the port defined in <code>.env</code> (default <code>5000</code>).</p>
<p>Make sure your MongoDB is running. If using local MongoDB, start it with:</p>
<pre><code class="lang-javascript">mongod
</code></pre>
<p>or ensure your MongoDB service is active.</p>
<p>Always check the terminal for any errors. If the server or database fails to start, your API requests will not work.</p>
<h4 id="heading-register-a-user">Register a User</h4>
<p>Request:</p>
<pre><code class="lang-javascript">POST http:<span class="hljs-comment">//localhost:5000/api/auth/register</span>
Content-Type: application/json

{
  <span class="hljs-string">"name"</span>: <span class="hljs-string">"sumit"</span>,
  <span class="hljs-string">"email"</span>: <span class="hljs-string">"sumit@example.com"</span>,
  <span class="hljs-string">"password"</span>: <span class="hljs-string">"mypassword"</span>
}
</code></pre>
<p>Response:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"message"</span>: <span class="hljs-string">"User registered successfully!"</span>
}
</code></pre>
<p>This sends a POST request to <code>http://localhost:5000/api/auth/register</code> with user details. If successful, you get a confirmation message.</p>
<h4 id="heading-login">Login</h4>
<p>Request:</p>
<pre><code class="lang-javascript">POST http:<span class="hljs-comment">//localhost:5000/api/auth/login</span>
Content-Type: application/json

{
  <span class="hljs-string">"email"</span>: <span class="hljs-string">"sumit@example.com"</span>,
  <span class="hljs-string">"password"</span>: <span class="hljs-string">"mypassword"</span>
}
</code></pre>
<p>Response:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"message"</span>: <span class="hljs-string">"Login successful!"</span>,
  <span class="hljs-string">"token"</span>: <span class="hljs-string">"&lt;JWT_TOKEN&gt;"</span>
}
</code></pre>
<p>This sends a POST request to <code>http://localhost:5000/api/auth/login</code> with email and password. If the credentials are correct, you receive a JWT to access protected routes.</p>
<h4 id="heading-access-protected-route">Access Protected Route</h4>
<p>Request:</p>
<pre><code class="lang-javascript">GET http:<span class="hljs-comment">//localhost:5000/api/auth/profile</span>
Authorization: Bearer &lt;JWT_TOKEN&gt;
</code></pre>
<p>Response:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"message"</span>: <span class="hljs-string">"Welcome to your profile!"</span>,
  <span class="hljs-string">"user"</span>: {
    <span class="hljs-string">"id"</span>: <span class="hljs-string">"..."</span>,
    <span class="hljs-string">"email"</span>: <span class="hljs-string">"sumit@example.com"</span>,
    <span class="hljs-string">"iat"</span>: ...,
    <span class="hljs-string">"exp"</span>: ...
  }
}
</code></pre>
<p>This sends the JWT in the <code>Authorization</code> header using the <code>Bearer</code> scheme.</p>
<ul>
<li><p>Only valid tokens will allow access to this protected route.</p>
</li>
<li><p><code>iat</code> and <code>exp</code> indicate issued-at and expiry time of the token.</p>
</li>
</ul>
<p><strong>Note:</strong> Always include <code>Authorization: Bearer &lt;token&gt;</code> for protected routes.</p>
<h2 id="heading-summary">Summary</h2>
<p>This article gave you a comprehensive overview of JSON Web Tokens (JWTs) and their role in web authentication. It explained the stateless nature of HTTP, the need for tokens, and compares classic session tokens with JWTs.</p>
<p>We covered JWT structure, security mechanisms, and practical implementation using Node.js, Express, and MongoDB. We also discussed security considerations, token management, and how to test a JWT authentication API.</p>
<h3 id="heading-heres-a-summary-of-the-key-points">Here’s a Summary of the Key Points:</h3>
<ol>
<li><p><strong>What is JWT?</strong></p>
<ul>
<li><p>JWT is a JSON-based open standard for securely representing claims between two parties, defined by RFC 7519.</p>
</li>
<li><p>Widely used for authorization in modern web applications and microservice architectures.</p>
</li>
<li><p>Alternative to session tokens for maintaining user state.</p>
</li>
</ul>
</li>
<li><p><strong>Stateless Nature of HTTP</strong></p>
<ul>
<li><p>HTTP does not retain information between requests, requiring each request to carry necessary data.</p>
</li>
<li><p>Tokens (session or JWT) are used to maintain user sessions in dynamic web applications.</p>
</li>
</ul>
</li>
<li><p><strong>Session Tokens</strong></p>
<ul>
<li><p>Classic approach where the server creates and stores a session ID, typically in cookies.</p>
</li>
<li><p>Works well for single-server setups but requires shared storage (for example, Redis) in multi-server environments.</p>
</li>
<li><p>Vulnerable if the shared cache goes down.</p>
</li>
</ul>
</li>
<li><p><strong>JWT: The Modern Solution</strong></p>
<ul>
<li><p>Server sends a signed JSON token to the client, which stores and sends it with each request.</p>
</li>
<li><p>No server-side storage required – all user info is in the token.</p>
</li>
<li><p>Signature ensures validity and integrity.</p>
</li>
</ul>
</li>
<li><p><strong>JWT Structure</strong></p>
<ul>
<li><p>Three parts: Header, Payload, Signature (separated by dots).</p>
</li>
<li><p>Header and payload are Base64 encoded JSON objects. Signature is a hash using a secret key.</p>
</li>
<li><p>Base64 encoding is for convenience, not security.</p>
</li>
</ul>
</li>
<li><p><strong>Decoding JWTs</strong></p>
<ul>
<li><p>Tools like <a target="_blank" href="https://jwt.io/">jwt.io</a> can decode JWTs to show header, payload, and signature.</p>
</li>
<li><p>Sensitive data should not be stored in JWTs, as payload is publicly readable.</p>
</li>
</ul>
</li>
<li><p><strong>JWT Security</strong></p>
<ul>
<li><p>Signature is created using a secret key and cryptographic algorithm.</p>
</li>
<li><p>Server verifies token integrity using the secret key.</p>
</li>
<li><p>JWTs identify users but do not act as passwords.</p>
</li>
</ul>
</li>
<li><p><strong>Security Considerations &amp; Token Management</strong></p>
<ul>
<li><p>If a JWT is compromised, the attacker can impersonate the user until the token expires.</p>
</li>
<li><p>JWTs cannot be directly revoked; blacklisting is used to invalidate compromised tokens.</p>
</li>
<li><p>Session tokens can be invalidated by the server.</p>
</li>
</ul>
</li>
<li><p><strong>JWTs in Different Languages</strong></p>
<ul>
<li><p>JWTs are language-agnostic and can be implemented in Node.js, PHP, and other languages.</p>
</li>
<li><p>Useful for authentication and representing any kind of identity.</p>
</li>
</ul>
</li>
<li><p><strong>Practical Implementation: JWT Authentication with Express + MongoDB</strong></p>
<ul>
<li><p>Step-by-step guide to building a JWT authentication system:</p>
<ul>
<li><p>Project setup and dependencies</p>
</li>
<li><p>Folder structure</p>
</li>
<li><p>Express server initialization</p>
</li>
<li><p>MongoDB connection</p>
</li>
<li><p>User model creation</p>
</li>
<li><p>Password hashing and JWT services</p>
</li>
<li><p>Auth controller and middleware</p>
</li>
<li><p>Auth routes</p>
</li>
<li><p>Main server file</p>
</li>
<li><p>API testing instructions</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Testing the API</strong></p>
<ul>
<li><p>Instructions for registering users, logging in, and accessing protected routes using tools like Postman.</p>
</li>
<li><p>Example requests and responses provided.</p>
</li>
</ul>
</li>
<li><p><strong>Summary &amp; Final Words</strong></p>
<ul>
<li><p>JWTs are secure, stateless, and widely used for authorization.</p>
</li>
<li><p>Security depends on safe token storage and proper management.</p>
</li>
</ul>
</li>
</ol>
<h2 id="heading-final-words">Final Words</h2>
<p>You can find all the source code from this tutorial in <a target="_blank" href="https://github.com/logicbaselabs/jwt-auth-demo">this GitHub repository</a>. If it helped you in any way, consider giving it a star to show your support!</p>
<p>Also, if you found the information here valuable, feel free to share it with others who might benefit from it. I’d really appreciate your thoughts – mention me on X <a target="_blank" href="https://x.com/sumit_analyzen">@sumit_analyzen</a> or on Facebook <a target="_blank" href="https://facebook.com/sumit.analyzen">@sumit.analyzen</a>, <a target="_blank" href="https://youtube.com/@logicBaseLabs">watch my coding tutorials</a>, or simply <a target="_blank" href="https://www.linkedin.com/in/sumitanalyzen/">connect with me</a> on LinkedIn.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What Are JSON Web Tokens (JWT)? ]]>
                </title>
                <description>
                    <![CDATA[ When you’re working with any website, application, or API, you'll inevitably need to log in and authenticate your user base. One of the more commonly used methods of passing around authentication credentials from one system to another is using a JSON... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-are-json-web-tokens-jwt/</link>
                <guid isPermaLink="false">686c430b1a4ac707c0692874</guid>
                
                    <category>
                        <![CDATA[ JWT ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authorization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Tutorial ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Grant Riordan ]]>
                </dc:creator>
                <pubDate>Mon, 07 Jul 2025 21:58:35 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751819356361/352ef68a-fa20-4a69-b666-393f7a17fa40.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you’re working with any website, application, or API, you'll inevitably need to log in and authenticate your user base. One of the more commonly used methods of passing around authentication credentials from one system to another is using a JSON Web Token (JWT).</p>
<p>In this article, you'll learn about:</p>
<ul>
<li><p>What a JSON Web Token (JWT) is</p>
</li>
<li><p>How JWTs are structured and created</p>
</li>
<li><p>Different JWT signing techniques and algorithms (Symmetric vs. Asymmetric)</p>
</li>
<li><p>How JWTs are used in real-world authentication flows</p>
</li>
<li><p>Important security best practices for using JWTs</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-a-jwt">What is a JWT?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-json-web-tokens-are-made-of-three-elements">JSON Web Tokens Are Made Of Three Elements</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-asymmetric-signing-rs256-explained">Asymmetric Signing (RS256) Explained</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-analogy-the-lock-and-key-for-asymmetric-signatures">Analogy: The Lock and Key for Asymmetric Signatures</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-symmetric-signing-hs256-hmac-with-sha-256">Symmetric Signing: HS256 (HMAC with SHA-256)</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-how-hs256-verification-works">How HS256 Verification Works</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-jwts-in-action-a-typical-authentication-flow">JWTs in Action: A Typical Authentication Flow</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-jwt-security-best-practices-amp-considerations">JWT Security Best Practices &amp; Considerations</a></p>
</li>
</ul>
<h2 id="heading-what-is-a-jwt">What Is a JWT?</h2>
<blockquote>
<p>JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.<br>— Introduction to JWT by jwt.io</p>
</blockquote>
<p>While accurate, this definition can be a bit dense at first glance. Imagine you want to send someone a sealed, tamper-proof message. That's essentially what a JSON Web Token (JWT) is. It's a secure message, a special kind of message designed to be sent between two parties which can be assured it came from an expected sender.</p>
<p>Each JWT is digitally signed using either a <strong>secret code</strong> (for symmetric algorithms like HMAC) or a <strong>private key</strong> (for asymmetric algorithms like RSA or ECDSA).</p>
<p>This secret code or private key is known only to the system that issues the JWT (often called an <em>authentication provider</em>, like Auth0, AWS Cognito, or Firebase Auth, which handles user logins and identity).</p>
<p>This signature proves two things:</p>
<ol>
<li><p><strong>Authenticity:</strong> It proves the message really came from who it claims to be from.</p>
</li>
<li><p><strong>Integrity:</strong> It proves that the message hasn't been changed or tampered with since it was signed. If even one character is altered, the signature won't match, and you'll know something is wrong, meaning the contents of the JWT can't be trusted.</p>
</li>
</ol>
<h3 id="heading-json-web-tokens-are-made-of-three-elements">JSON Web Tokens Are Made of Three Elements</h3>
<p>JWTs are made up of 3 key parts:</p>
<ol>
<li><p>Header</p>
</li>
<li><p>Payload</p>
</li>
<li><p>Signature</p>
</li>
</ol>
<h4 id="heading-header">Header</h4>
<p>The header contains metadata information about the token. Think of it like a label on a package – it tells you what’s inside and how it was prepared.</p>
<p>Typically, the header contains:</p>
<p><code>alg</code>: This specifies the <strong>algorithm</strong> used to sign the JWT. Common algorithms are <code>HS256</code> (HMAC with SHA-256) or <code>RS256</code> (RSA with SHA-256).</p>
<p><code>typ</code>: This specifies the <strong>type</strong> of token, which is almost always <code>JWT</code> for standard JSON Web Tokens.</p>
<p><strong>Example (decoded):</strong></p>
<pre><code class="lang-json">{ 
  <span class="hljs-attr">"alg"</span>: <span class="hljs-string">"RS256"</span>,
  <span class="hljs-attr">"typ"</span>: <span class="hljs-string">"JWT"</span> 
}
</code></pre>
<h4 id="heading-payload">Payload</h4>
<p>This is the second part of the JWT, and it's where the real data or "claims" are stored. Claims are statements about an entity (usually a user) and any other additional data. Using the previous analogy of a package, think of it as the “contents” of the package.</p>
<p>There are three types of claims:</p>
<p><strong>1. Registered Claims:</strong> These are predefined claims that are recommended for common use cases. They are not mandatory but are very useful for interoperability. These include:</p>
<ul>
<li><p><code>iss</code> – issuer, who issued the token (for example, your application’s domain)</p>
</li>
<li><p><code>sub</code> – subject, the subject of the token (for example, a User’s ID)</p>
</li>
<li><p><code>aud</code> – audience, the audience of the token (that is, who the token is intended for – for example, a specific API)</p>
</li>
<li><p><code>exp</code> – <strong>expiration</strong>, the expiry date as a timestamp</p>
</li>
<li><p><code>iat</code> – issued at, when the token was issued as a timestamp</p>
</li>
<li><p><code>nbf</code> – not before, when the token becomes valid (that is, the token cannot be used or deemed valid before this timestamp)</p>
</li>
<li><p><code>jti</code> – JWT ID, a unique identifier for the token, useful for preventing replay attacks or blacklisting</p>
</li>
</ul>
<p><strong>2. Public Claims:</strong> These can be defined by anyone using JWTs. To avoid naming conflicts, it's a good practice to register them or define them using a unique identifier like a URI.</p>
<p><strong>3. Private Claims:</strong> These are custom claims created to share specific information between parties who agree on using them. They are entirely up to you and your application's needs.</p>
<p><strong>Example payload:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"sub"</span>: <span class="hljs-string">"1234567890"</span>, <span class="hljs-comment">//  subject</span>
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"John Doe"</span>, <span class="hljs-comment">// private claim</span>
  <span class="hljs-attr">"admin"</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">// private claim / role</span>
  <span class="hljs-attr">"iat"</span>: <span class="hljs-number">1678886400</span>, <span class="hljs-comment">// Issued at a specific timestamp</span>
  <span class="hljs-attr">"exp"</span>: <span class="hljs-number">1678890000</span>  <span class="hljs-comment">// Expires at a specific timestamp</span>
}
</code></pre>
<p>Like the header, this JSON object is also <strong>Base64Url encoded</strong> (a URL-safe variant of Base64 encoding) to form the second part of the JWT string.</p>
<p><strong>Important Note:</strong> <em>The payload is</em> <strong><em>encoded*</em></strong>, not encrypted.* This means that anyone can easily decode the JWT and read its contents. Never put sensitive information (like passwords) directly into the payload unless the entire JWT itself is encrypted (which is a separate process called JWE - JSON Web Encryption). The security of a standard JWT comes entirely from the signature, which prevents tampering.</p>
<h4 id="heading-signature">Signature</h4>
<p>The signature, as we've already discussed, is the most important part of the JWT. Without it, there's no protection applied to the JWT, meaning no way to validate the origin of the token or its integrity.</p>
<p>The signature is created by taking the <strong>encoded header</strong>, the <strong>encoded payload</strong>, and a <strong>secret key</strong> (or a private key if using asymmetric algorithms like RSA). These are then run through the cryptographic algorithm specified in the header (<code>alg</code> field). For HS256, a shared secret key is used. For RS256, a private key is used to sign, and a corresponding public key is used to verify. We’ll get on to verification soon.</p>
<p>Think of it like a tamper-proof seal on your package, or even better, a wax seal on a letter. If you receive your letter and the wax seal has been broken, you'd naturally believe the contents of the letter may not be original and therefore can't be trusted.</p>
<p>In pseudo-code it would look like this:</p>
<p><code>Signature = Algorithm( Base64Url(Header) + "." + Base64Url(Payload), SecretKey )</code></p>
<p>The result of this signing process is the signature, which is also Base64Url encoded to form the third part of the JWT string.</p>
<p>At the end of the whole process your JWT would look like this:</p>
<p><code>base64EncodedHeader.base64EncodedPayload.base64EncodedSignature</code></p>
<h3 id="heading-asymmetric-signing-rs256-explained">Asymmetric Signing (RS256) Explained</h3>
<p>When a JWT uses an algorithm like RS256 (RSA Signature with SHA-256), it employs an <strong>asymmetric cryptographic</strong> process involving a <strong>public</strong> and <strong>private</strong> key pair. This is where the core magic of proving authenticity and integrity happens without needing to share a secret.</p>
<h4 id="heading-the-signing-process-by-the-issuer">The Signing Process (by the Issuer)</h4>
<p>The <strong>sender</strong> (the server that issues the JWT, like Auth0) possesses the <strong>private key</strong>. This key is kept absolutely secret and secure. Here are the steps:</p>
<ol>
<li><p><strong>Prepare the data:</strong> The server takes the header (which includes the algorithm) and the payload. It Base64Url-encodes them, and then concatenates them with a dot: <code>Base64Url(Header) + "." + Base64Url(Payload)</code>.</p>
<p> For example, with this header:</p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"typ"</span>: <span class="hljs-string">"JWT"</span>,
   <span class="hljs-attr">"alg"</span>: <span class="hljs-string">"RS256"</span>
 }
</code></pre>
<p> And this payload:</p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"sub"</span>: <span class="hljs-string">"1234567890"</span>,
   <span class="hljs-attr">"name"</span>: <span class="hljs-string">"John Doe"</span>,
   <span class="hljs-attr">"admin"</span>: <span class="hljs-literal">true</span>,
   <span class="hljs-attr">"iat"</span>: <span class="hljs-number">1751494086</span>,
   <span class="hljs-attr">"exp"</span>: <span class="hljs-number">1751497686</span>
 }
</code></pre>
<p> This would create a Base64Url-encoded <code>header.payload</code> string like the animated example below:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751810671075/128fa652-fe2a-4413-a238-71531bfe67ae.gif" alt="Animated gif of the process converting header and payload to base64 encoded string" class="image--center mx-auto" width="800" height="587" loading="lazy"></p>
</li>
<li><p><strong>Calculate the hash:</strong> It then calculates a <strong>hash</strong> (using SHA-256 in this case) of this combined header and payload string.</p>
</li>
<li><p><strong>Sign the hash:</strong> Finally, it signs this hash using its private key. This cryptographically transformed hash is the signature part of the JWT.</p>
</li>
</ol>
<p>The JWT is then formed by concatenating the Base64Url-encoded header, the Base64Url-encoded payload, and the Base64Url-encoded signature, separated by dots: <code>header.payload.signature</code>.</p>
<p>The top segment below shows the full JWT token (header.payload.signature):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751830473890/31da21a0-50db-4a48-b4c3-378c2ac1616a.png" alt="Image displaying the fully formed JWT token along with original header and payload" class="image--center mx-auto" width="2630" height="1100" loading="lazy"></p>
<h3 id="heading-the-verification-process">The Verification Process</h3>
<p>This is where the magic happens, and it's often a point of confusion. The public key doesn't "decrypt" the original data like a symmetric key does. Instead, it performs a unique <strong>verification</strong> process.</p>
<p>The receiver (the client or another server that needs to verify the JWT) possesses the <strong>public key</strong>. This key does <strong>not</strong> need to be kept secret – it can be freely distributed.</p>
<p>Here's a step-by-step explanation:</p>
<ol>
<li><p><strong>Separate the parts:</strong> The first thing the receiver does is split the incoming JWT string into its three Base64Url-encoded components: the Header, the Payload, and the Signature.</p>
</li>
<li><p><strong>Obtain the public key:</strong> The verifier needs the <strong>public key</strong> that corresponds to the private key used by the issuer. Public keys are often available via a <strong>JWKS (JSON Web Key Set) endpoint</strong> (for example, <code>your-domain.com/.well-known/jwks.json</code>).</p>
</li>
<li><p><strong>Re-create the data to be hashed:</strong> The receiver takes the received, Base64Url-encoded Header and the received, Base64Url-encoded Payload. It then combines them exactly as the issuer did: <code>EncodedHeader.EncodedPayload</code>.</p>
</li>
<li><p><strong>Compute a local hash (Hash A):</strong> This combined string is then put through the same hashing algorithm (for example, SHA-256) that was specified in the JWT's header. This produces a new, locally computed hash (let's call this <strong>"Hash A"</strong>). This local hash represents what the content <em>should</em> look like if it hasn't been tampered with.</p>
</li>
<li><p><strong>"Unsign" the received signature with the public key to get the original signed hash (Hash B):</strong> This is the core cryptographic step. The verifier uses the public key (obtained in step 2) to perform a mathematical operation on the received signature. This operation does <em>not</em> create a new signature for comparison. Instead, it effectively "unsigns" or "decrypts" the signature to reveal the <strong>original hash ("Hash B")</strong> that was produced by the issuer's private key.</p>
<ul>
<li><strong>Crucial Point:</strong> This process is for <strong>verifying authenticity</strong>, not decrypting confidential data. The public key confirms that the signature was indeed created by the corresponding private key, and as part of that confirmation, it returns the original hash that <em>was signed</em>.</li>
</ul>
</li>
<li><p><strong>Compare the hashes:</strong> The verifier now has two hashes:</p>
<ul>
<li><p><strong>Hash A:</strong> The hash it <strong>computed locally</strong> from the received header and payload (from step 4).</p>
</li>
<li><p><strong>Hash B:</strong> The original hash that was extracted from the received Signature using the public key (from step 5)</p>
</li>
</ul>
</li>
<li><p><strong>If Hash A matches Hash B:</strong> It proves two critical things:</p>
<ol>
<li><p><strong>Authenticity:</strong> The token was indeed signed by the legitimate holder of the corresponding private key (for example, Auth0).</p>
</li>
<li><p><strong>Integrity:</strong> The content of the header and payload has <strong>not been tampered with</strong> since it was originally signed. If even a single character in the header or payload were changed, Hash A would be different, and it would not match Hash B. In this case, the JWT is considered valid and its contents can be trusted.</p>
</li>
</ol>
</li>
<li><p><strong>If the hashes do NOT match:</strong> The token is considered invalid and <strong>must be rejected</strong>. This indicates either that the JWT was signed by an unauthorised party (a forged token) or that its header or payload has been altered after it was signed.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751813812291/de32c7b0-1f3c-4f26-995e-b5c618b104b3.png" alt=" Flow diagram of asymmetric verification process" class="image--center mx-auto" width="1649" height="2947" loading="lazy"></p>
<h3 id="heading-analogy-the-lock-and-key-for-asymmetric-signatures">Analogy: The Lock and Key for Asymmetric Signatures</h3>
<p><strong>Private Key:</strong> A special, unique key that can <strong>lock</strong> a box (create a signature). Only the owner has this key.</p>
<p><strong>Public Key:</strong> A widely distributed key that can <strong>test</strong> if a box was locked by the corresponding private key. It can't lock a new box, but it can confirm if an existing lock is authentic.</p>
<p>You don't re-lock the box with the public key. You use the public key to check if the existing lock (the signature) is genuine and corresponds to the contents of the box.</p>
<h2 id="heading-symmetric-signing-hs256-hmac-with-sha-256">Symmetric Signing: HS256 (HMAC With SHA-256)</h2>
<p>While RS256 uses a pair of keys (private for signing, public for verifying), many JWTs you'll encounter are signed symmetrically, most commonly with the HS256 algorithm. HS256 stands for <strong>HMAC (Hash-based Message Authentication Code) with SHA-256</strong>.</p>
<p>The fundamental difference here is the use of a single, shared secret key for <em>both</em> signing and verification.</p>
<h3 id="heading-how-hs256-signing-works">How HS256 Signing Works</h3>
<ol>
<li><p><strong>Shared secret key:</strong> The issuer (for example, your authentication provider) possesses a single, confidential secret key. This key is known <em>only</em> to the issuer and any parties (like your API) that need to verify the token.</p>
</li>
<li><p><strong>Combine header and payload:</strong> Just like with asymmetric signing, the issuer takes the Base64Url-encoded Header (which specifies <code>"alg": "HS256"</code>) and the Base64Url-encoded Payload, and <strong>joins</strong> them with a dot.</p>
</li>
<li><p><strong>Apply HMAC-SHA256:</strong> This combined string is then fed into the HMAC-SHA256 algorithm along with the secret key. The HMAC algorithm uses the secret key to create a unique hash (the signature) of the data. In pseudo-code, it looks like this:</p>
<p> <code>Signature = HMAC-SHA256( Base64Url(Header) + "." + Base64Url(Payload), SecretKey )</code></p>
</li>
<li><p><strong>Form the JWT:</strong> The resulting signature (which is also Base64Url-encoded) is appended to the header and payload with a dot, forming the complete JWT: <code>base64EncodedHeader.base64EncodedPayload.base64EncodedSignature</code>.</p>
</li>
</ol>
<h3 id="heading-how-hs256-verification-works">How HS256 Verification Works</h3>
<p>When a receiver gets an HS256-signed JWT, it goes through a verification process.</p>
<p>First, it separates the parts. The JWT is split into its three Base64Url-encoded components: Header, Payload, and Signature, as we did with asymmetric JWTs.</p>
<p>Then, it obtains the shared secret key. The receiver must also possess the <strong>exact same secret key</strong> that the issuer used to sign the token. This key is <em>not</em> publicly distributed like a public key – it must be securely provisioned to any entity that needs to verify tokens.</p>
<p>Next, it re-calculates the signature. The receiver does this by taking the received Base64Url-encoded Header and Payload, combining them, and then re-applying the HMAC-SHA256 algorithm using the <em>same secret key</em>. This produces a new, locally computed signature.</p>
<p>Finally, the receiver compares the signature it just calculated locally with the signature it received as part of the JWT.</p>
<ul>
<li><p><strong>If the two signatures match:</strong> The token is considered valid. This confirms its authenticity (it came from someone who knows the secret) and integrity (it hasn't been tampered with).</p>
</li>
<li><p><strong>If the signatures do NOT match:</strong> The token is invalid and must be rejected. This indicates either tampering or that it was signed with a different, unknown secret key.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751814851136/a73b7af6-e92d-40f3-b1e3-c4bd2406ede9.png" alt="Flow diagram of symmetric verification process" class="image--center mx-auto" width="1715" height="2977" loading="lazy"></p>
<h3 id="heading-key-differences-and-considerations">Key Differences and Considerations:</h3>
<ul>
<li><p><strong>Key management:</strong> With HS256, the secret key must be securely shared and kept confidential by <em>all</em> parties involved in both signing and verifying. This can be more challenging to manage securely at scale compared to the public/private key model, where only the private key needs strict secrecy.</p>
</li>
<li><p><strong>Performance:</strong> HS256 is generally faster to compute than asymmetric algorithms like RS256, making it suitable for high-volume scenarios where the secret key can be securely distributed.</p>
</li>
</ul>
<h2 id="heading-jwts-in-action-a-typical-authentication-flow">JWTs in Action: A Typical Authentication Flow</h2>
<p>Now that you understand how JWTs are structured and signed, let's look at how they're typically used in a real-world web application. This authentication flow is a common pattern you'd encounter.</p>
<h3 id="heading-step-1-user-logs-in"><strong>Step 1: User Logs In:</strong></h3>
<p>A user opens a client application (for example, a web browser, mobile app) and enters their login credentials (username and password).</p>
<p>The client sends these credentials securely (always over HTTPS!) to an <strong>authentication server</strong> (like Auth0, AWS Cognito, or your own backend's authentication endpoint).</p>
<h3 id="heading-step-2-authentication-server-issues-jwt"><strong>Step 2: Authentication Server Issues JWT:</strong></h3>
<p>Then the authentication server verifies the user's credentials. If valid, it generates a new JWT. This JWT contains claims (like the user's ID, roles, expiration time) in its payload and is digitally signed by the server's <strong>private key</strong> (for asymmetric algorithms like RS256) or <strong>secret key</strong> (for symmetric algorithms like HS256).</p>
<p>The server then sends this signed JWT back to the client.</p>
<h3 id="heading-step-3-client-stores-jwt"><strong>Step 3: Client Stores JWT:</strong></h3>
<p>The client receives the JWT and typically stores it in a secure location, such as browser memory storage, session storage, or an HTTP-only cookie. The method of storage depends on the client type and security considerations.</p>
<h3 id="heading-step-4-client-makes-api-calls"><strong>Step 4: Client Makes API Calls:</strong></h3>
<p>When the user wants to access a protected resource on a backend API (for example, their profile data, a private feed), the client includes the JWT in the request.</p>
<p>The standard way to do this is by sending the token in the <code>Authorization</code> header of the HTTP request, prefixed with the word <code>Bearer</code>:</p>
<p><code>Authorization: Bearer &lt;your_jwt_here&gt;</code></p>
<h3 id="heading-step-5-api-verifies-jwt-amp-authorises-request"><strong>Step 5: API Verifies JWT &amp; Authorises Request:</strong></h3>
<p>Now, the backend API receives the request and extracts the JWT from the <code>Authorization</code> header. The API then performs the JWT verification process depending on the algorithm:</p>
<ul>
<li><p>It checks the token's claims, especially the <code>exp</code> (expiration) claim, to ensure it's still valid.</p>
</li>
<li><p>If the token is valid, the API trusts the claims within the payload (for example, the user's ID) and proceeds to fulfill the request, potentially using the user's roles to determine if they have permission to access the requested resource.</p>
</li>
<li><p>If the token is invalid (bad signature, expired, and so on), the API rejects the request, typically with an HTTP 401 Unauthorised status.</p>
</li>
</ul>
<p>This flow is powerful because JWTs are <strong>stateless</strong>: once issued, the authentication server doesn't need to keep a record of active sessions. The API can verify the token independently, which simplifies scaling and reduces server load.</p>
<h2 id="heading-jwt-security-best-practices-and-considerations">JWT Security Best Practices and Considerations</h2>
<p>While JWTs offer powerful authentication capabilities, using them securely requires careful attention to best practices. Misconfigurations or oversight can lead to significant vulnerabilities.</p>
<h3 id="heading-always-use-httpstls"><strong>Always Use HTTPS/TLS:</strong></h3>
<p><strong>Crucial:</strong> JWTs are <strong>encoded, not encrypted, by default</strong>. This means anyone who intercepts the token during transmission can easily read its payload. Therefore, JWTs (and all authentication traffic) <strong>must always be transmitted over HTTPS (TLS)</strong> to encrypt the communication channel itself and prevent eavesdropping.</p>
<h3 id="heading-protect-your-signing-keys"><strong>Protect Your Signing Keys:</strong></h3>
<p>Whether it's a private key (for RS256) or a shared secret key (for HS256), these keys are paramount. If an attacker gains access to your signing key, they can forge valid JWTs, impersonate users, and compromise your system. Store these keys securely, preferably in dedicated key management services.</p>
<h3 id="heading-keep-access-tokens-short-lived-exp-claim"><strong>Keep Access Tokens Short-Lived (</strong><code>exp</code> claim):</h3>
<p>You should always set short expiration times (for example, 5-15 minutes) for your JWTs used as access tokens. This minimises the window of opportunity for an attacker if a token is compromised.</p>
<p>Since JWTs are stateless, they are hard to revoke immediately once issued. A short lifespan is your primary defense against compromised tokens.</p>
<h3 id="heading-implement-refresh-tokens-for-longer-sessions"><strong>Implement Refresh Tokens (for Longer Sessions):</strong></h3>
<p>To maintain user experience with short-lived access tokens, use <strong>refresh tokens</strong>. A refresh token is a separate, longer-lived token (usually stored more securely) that can be exchanged for a new, short-lived access token when the current one expires, without requiring the user to re-authenticate. Refresh tokens <em>can</em> be revoked by the server, offering better control.</p>
<h3 id="heading-never-put-sensitive-data-in-the-payload"><strong>Never Put Sensitive Data in the Payload:</strong></h3>
<p>Reiterating this crucial point: the JWT payload is Base64Url encoded, which is easily reversible. Do not put passwords, highly sensitive PII (Personally Identifiable Information), or confidential business data directly into the JWT payload. Only include non-sensitive or publicly available information, or data that's already encrypted by other means.</p>
<h3 id="heading-validate-all-claims-on-verification"><strong>Validate ALL Claims on Verification:</strong></h3>
<p>When verifying a JWT, don't just check the signature. Always validate all relevant claims, including:</p>
<ul>
<li><p><code>exp</code> (Expiration): Ensure the token hasn't expired.</p>
</li>
<li><p><code>iss</code> (Issuer): Verify the token came from the expected authentication server.</p>
</li>
<li><p><code>aud</code> (Audience): Ensure the token is intended for your specific API/application.</p>
</li>
<li><p><code>nbf</code> (Not Before): Check if the token is active yet.</p>
</li>
</ul>
<h3 id="heading-consider-token-revocation-for-critical-cases"><strong>Consider Token Revocation (for critical cases):</strong></h3>
<p>For situations requiring immediate revocation (for example, user password change, account deactivation), typical stateless JWTs are challenging. Strategies include:</p>
<ul>
<li><p>Short expiration times (as above).</p>
</li>
<li><p>A blacklist/revocation list: Store the <code>jti</code> (JWT ID) of revoked tokens in a database, checking this list on every request. This adds a stateful lookup but provides immediate revocation.</p>
</li>
</ul>
<h2 id="heading-thanks-for-reading">Thanks for reading!</h2>
<p>I hope you’ve found this tutorial useful, and as always if you want to ask any questions or hear about upcoming articles, you can always follow me on ‘X’, my handle is @grantdotdev and follow by clicking <a target="_blank" href="https://x.com/grantdotdev">here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add JWT-Based Authentication in NestJS ]]>
                </title>
                <description>
                    <![CDATA[ Authentication is a very important aspect of software development. It is the process of verifying a user’s identity. Authentication ensures that only authorized individuals access specific resources or perform certain actions within a system. It prov... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-jwt-based-authentication-in-nest-js/</link>
                <guid isPermaLink="false">66c720b8e8452c66efc4c6f7</guid>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JWT ]]>
                    </category>
                
                    <category>
                        <![CDATA[ nestjs ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Abimbola Adedotun Samuel ]]>
                </dc:creator>
                <pubDate>Wed, 31 Jul 2024 14:33:47 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/nest-auth-coverimage-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Authentication is a very important aspect of software development. It is the process of verifying a user’s identity.</p>
<p>Authentication ensures that only authorized individuals access specific resources or perform certain actions within a system. It provides accountability by enabling the tracking of user actions and holding individuals responsible for their activities.</p>
<p>It also gives companies data on the number of people using their products. Without proper authentication of your software, you may face security risks. Proper implementation prevents unauthorized access and protects sensitive data. </p>
<p>This tutorial will guide you through building a JWT-based user authentication in NestJS and MongoDb.</p>
<p>NestJS is a powerful Node.js framework for building server-side
applications. MongoDB is popular NoSQL database and we’ll use it to build the basic authentication endpoints.</p>
<p>In this tutorial, we'll cover the following topics:</p>
<ul>
<li>How to creating a new NestJS project and install the necessary dependencies.</li>
<li>How to create user models and schemas.</li>
<li>How to implementing login and signup with JWT token.</li>
<li>How to test the endpoints with postman.</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>This tutorial is a hands-on demo. To follow along, you must have the
following:</p>
<ul>
<li><p><a target="_blank" href="https://nodejs.org/en/download/package-manager"><u>Node.js</u></a> v14
and above</p>
</li>
<li><p>Node package manager</p>
</li>
<li><p><a target="_blank" href="https://www.mongodb.com/docs/compass/current/install/"><u>MongoDB
compass</u></a></p>
</li>
<li><p>Basic understanding of Node.js and preferably ExpressJs</p>
</li>
<li><p>A code editor (for example: VS Code) </p>
</li>
</ul>
<h2 id="heading-how-to-set-up-the-project"><strong>How to Set Up the Project.</strong></h2>
<p>In this section, we’ll set up the project to build our REST API with
NestJS and MongoDB. We’ll start by installing the NestJS CLI and use it to generate new projects.</p>
<p>Install <a target="_blank" href="https://docs.nestjs.com/cli/overview"><u>Nest CLI</u></a>:</p>
<p><code>$ npm i -g @nestjs/cli</code></p>
<p>Then create a new NestJS project with this command:</p>
<p><code>$ nest new project-name</code></p>
<p>Let’s call the project authentication:</p>
<p><code>$ nest new authentication</code></p>
<p>You will see options about which package manager you prefer to install. I
used npm.</p>
<p>After successful installation, move into the created directory and open
the project with your preferred code editor.</p>
<p>Before we go into creating resources and configuring the project, let’s
take a quick look at the <strong>src</strong> directory and its files:</p>
<ul>
<li><p><code>src</code>: The root directory for the source code.</p>
</li>
<li><p><code>src/app.module.ts</code>: The application's main module for configuring and
integrating other modules.</p>
</li>
<li><p><code>src/app.controller.ts</code>: Contains a default controller with a single
route.</p>
</li>
<li><p><code>src/app.service.ts</code>: This includes a basic service using a single
method.</p>
</li>
<li><p><code>src/main.ts</code>: The entry point of the application.</p>
</li>
</ul>
<p>Next, install dependencies to set up and connect the database. You will have to install the <code>mongoose</code> package, <code>bcrypt</code>:</p>
<p><code>$ npm i -save @nestjs/mongoose @types/bcrypt mongoose bcrypt</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image3.png" alt="dependencies succefully installed" width="600" height="400" loading="lazy"></p>
<p>Next, set up your database. The <code>MongooseModule</code> from the <code>@nestjs/mongoose</code> dependency will be used to set up the database.</p>
<p>Go to <code>src/app.module.ts</code> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { AppController } <span class="hljs-keyword">from</span> <span class="hljs-string">'./app.controller'</span>;
<span class="hljs-keyword">import</span> { AppService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./app.service'</span>;
<span class="hljs-keyword">import</span> { MongooseModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/mongoose'</span>;
<span class="hljs-keyword">import</span> { UsersModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users/users.module'</span>;
<span class="hljs-keyword">import</span> { AuthModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'./auth/auth.module'</span>;
<span class="hljs-keyword">import</span> { ConfigModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/config'</span>;

@Module({
<span class="hljs-attr">imports</span>: [
MongooseModule.forRoot(<span class="hljs-string">'mongodb://localhost:27017/auth-workshop'</span>),
UsersModule,
AuthModule,
ConfigModule.forRoot({
<span class="hljs-attr">envFilePath</span>: <span class="hljs-string">'.env'</span>,
<span class="hljs-attr">isGlobal</span>: <span class="hljs-literal">true</span>,
}),
],
<span class="hljs-attr">controllers</span>: [AppController],
<span class="hljs-attr">providers</span>: [AppService],
})
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppModule</span> </span>{}
</code></pre>
<p>Let's breakdown the code above.
The <code>app.module.ts</code> is the root module of the nestjs application and it is responsible for importing dependecies and other modules required by the application, configuring the application such as database connections and environment variables.</p>
<p>We first specified the <code>app.module.ts</code> file as a module by using the <code>@Module({})</code> decorator:</p>
<pre><code class="lang-js">@Module({})
</code></pre>
<p>The <code>imports</code> array specifies the module that this module depends on. We have the <code>MongooseModule.forRoot('')</code> for database connection using mongoose, <code>ConfigModule.forRoot</code> import sets up the configuration module to read from a <code>.env</code> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { MongooseModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/mongoose'</span>;
<span class="hljs-keyword">import</span> { UsersModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users/users.module'</span>;
<span class="hljs-keyword">import</span> { AuthModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'./auth/auth.module'</span>;
<span class="hljs-keyword">import</span> { ConfigModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/config'</span>;

imports: [
MongooseModule.forRoot(<span class="hljs-string">'mongodb://localhost:27017/auth-workshop'</span>),
UsersModule,
AuthModule,
ConfigModule.forRoot({
<span class="hljs-attr">envFilePath</span>: <span class="hljs-string">'.env'</span>,
<span class="hljs-attr">isGlobal</span>: <span class="hljs-literal">true</span>,
}),
]
</code></pre>
<p>You can replace the <code>MongooseModule.forRoot()</code> URI string with your own database
string.</p>
<p>The <code>controllers</code> array specifies the controller that belongs to this module:</p>
<pre><code class="lang-js">controllers: [AppController]
</code></pre>
<p>The <code>providers</code> array specifies the services that belongs to this module:</p>
<pre><code class="lang-js">providers: [AppService]
</code></pre>
<p>With these configurations, you can start your application by using the
<code>npm run start:dev</code>.</p>
<h2 id="heading-user-models-and-schemas"><strong>User models and schemas</strong></h2>
<p>In this section, we'll define the <code>User</code> model and schema using
<code>mongoose</code>. The <code>User</code> model will represent the users of the application,
and the schema will define the structure of the data stored in MongoDB.
Let’s start by creating a resource module for the users API:</p>
<p>First, create a <code>users</code> resource with the nest CLI:</p>
<p><code>$ nest generate res users</code> </p>
<p>This command will create a new <code>users</code> resource in the <strong>src/users</strong>
directory with a basic structure of controllers and services.</p>
<p>Then define the schema for the <code>Users</code> in <strong>src/users/entities/users.entity.ts</strong>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Prop, Schema, SchemaFactory }
<span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/mongoose'</span>;
@Schema()
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
@Prop()
<span class="hljs-attr">name</span>: string;
@Prop({ <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span> })
<span class="hljs-attr">email</span>: string;

@Prop()
<span class="hljs-attr">password</span>: string;
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> UserSchema = SchemaFactory.createForClass(User);
</code></pre>
<p>The <code>@Schema</code> decorator is what makes the class a schema. This schema defines three fields for the users: <code>name</code>, <code>email</code>, and <code>password</code>. They are all typed string.</p>
<p>Next, register the schema in the <code>users.module.ts</code> file located in <strong>src/users/users.module.ts</strong>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { UsersService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users.service'</span>;
<span class="hljs-keyword">import</span> { UsersController } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users.controller'</span>;
<span class="hljs-keyword">import</span> { MongooseModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/mongoose'</span>;
<span class="hljs-keyword">import</span> { UserSchema, User } <span class="hljs-keyword">from</span> <span class="hljs-string">'./entities/user.entity'</span>;

@Module({
<span class="hljs-attr">imports</span>: [MongooseModule.forFeature([{ <span class="hljs-attr">name</span>: User.name, <span class="hljs-attr">schema</span>:
UserSchema }])],
<span class="hljs-attr">controllers</span>: [UsersController],
<span class="hljs-attr">providers</span>: [UsersService],
})
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UsersModule</span> </span>{}
</code></pre>
<p>By importing the <code>MongooseModule.forFeature([{}])</code>, this configures mongoose to use the <code>UserSchema</code> for the <code>User</code> model.</p>
<p>By registering the schema with Mongoose, we created a model that's ready to use in our application. This sets the stage for building services and controllers that can interact with our data and handle incoming requests.</p>
<p>Lastly, define the DTO (data transfer object). This object transfers data between systems. It is a simple object that contains only data and has no behaviour.</p>
<p>Create your <code>CreateUserDto</code> in the <strong>src/users/dto/create-user.dto.ts</strong> directory:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreateUserDto</span> </span>{
<span class="hljs-attr">username</span>: string;
email: string;
password: string;
}
</code></pre>
<h2 id="heading-user-services-and-controllers"><strong>User Services and Controllers</strong></h2>
<p>We have connected to the database and created the schema and model of <code>Users</code>. Let’s write the basic CRUD methods for the users.</p>
<p>Update your <strong>users.service.ts</strong> located in <strong>src/users/users.service.ts</strong>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Injectable, NotFoundException
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { CreateUserDto } <span class="hljs-keyword">from</span> <span class="hljs-string">'./dto/create-user.dto'</span>;
<span class="hljs-keyword">import</span> { UpdateUserDto } <span class="hljs-keyword">from</span> <span class="hljs-string">'./dto/update-user.dto'</span>;
<span class="hljs-keyword">import</span> { InjectModel } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/mongoose'</span>;
<span class="hljs-keyword">import</span> { User } <span class="hljs-keyword">from</span> <span class="hljs-string">'./entities/user.entity'</span>;
<span class="hljs-keyword">import</span> { Model } <span class="hljs-keyword">from</span> <span class="hljs-string">'mongoose'</span>;

@Injectable()
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UsersService</span> </span>{
<span class="hljs-keyword">constructor</span>(@InjectModel(User.name) private userModel:
Model&amp;lt;User&amp;gt;) {}
<span class="hljs-keyword">async</span> createUsers(createUserDto: CreateUserDto) {
<span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.userModel.create(createUserDto);
<span class="hljs-keyword">return</span> user.save();
}
<span class="hljs-keyword">async</span> findAllUsers() {
<span class="hljs-keyword">const</span> users = <span class="hljs-built_in">this</span>.userModel.find();
<span class="hljs-keyword">return</span> users;
}
<span class="hljs-keyword">async</span> findUser(id: number) {
<span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.userModel.findById(id);
<span class="hljs-keyword">if</span> (!user) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> NotFoundException(<span class="hljs-string">'could not find the user'</span>);
<span class="hljs-keyword">return</span> user;
}
updateUser(id: number, <span class="hljs-attr">updateUserDto</span>: UpdateUserDto) {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.userModel.findByIdAndUpdate(id, updateUserDto, { <span class="hljs-attr">new</span>: <span class="hljs-literal">true</span>
});
}
removeUser(id: number) {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.userModel.findByIdAndDelete(id);
};
}
</code></pre>
<p>Update your <strong>users.controller.ts</strong> located in <strong>src/users/users.controller.ts</strong>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Controller, Get, Post, Body, Patch, Param, Delete, } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { UsersService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./users.service'</span>;
<span class="hljs-keyword">import</span> { CreateUserDto } <span class="hljs-keyword">from</span> <span class="hljs-string">'./dto/create-user.dto'</span>;
<span class="hljs-keyword">import</span> { UpdateUserDto } <span class="hljs-keyword">from</span> <span class="hljs-string">'./dto/update-user.dto'</span>;

@Controller(<span class="hljs-string">'users'</span>)
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UsersController</span> </span>{
<span class="hljs-keyword">constructor</span>(private readonly usersService: UsersService) {}

@Post()
<span class="hljs-keyword">async</span> create(@Body() createUserDto: CreateUserDto) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.usersService.createUsers(createUserDto);
}

@Get()
<span class="hljs-keyword">async</span> findAll() {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.usersService.findAllUsers();
}

@Get(<span class="hljs-string">':id'</span>)
<span class="hljs-keyword">async</span> findOne(@Param(<span class="hljs-string">'id'</span>) id: string) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.usersService.findOneUser(+id);
}

@Patch(<span class="hljs-string">':id'</span>)
<span class="hljs-keyword">async</span> update(@Param(<span class="hljs-string">'id'</span>) id: string, @Body() updateUserDto:
UpdateUserDto) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.usersService.updateUser(+id, updateUserDto);
}

@Delete(<span class="hljs-string">':id'</span>)
<span class="hljs-keyword">async</span> remove(@Param(<span class="hljs-string">'id'</span>) id: string) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.usersService.removeUser(+id);
}
}
</code></pre>
<p>We created RESTful APIs using <code>mongoose</code>. The methods include:</p>
<ul>
<li><p><code>findAllUsers</code>: Retrieves all user documents from the collection.</p>
</li>
<li><p><code>getUserById</code>: Finds a single user document by ID.</p>
</li>
<li><p><code>createUsers</code>: Adds a new user document to the collection.</p>
</li>
<li><p><code>updateUser</code>: Updates details of existing user in the collection.</p>
</li>
<li><p><code>removeUser</code>: Removes user document by ID.</p>
</li>
</ul>
<h2 id="heading-how-to-implement-sign-up-and-log-in"><strong>How to Implement Sign-up and Log-in</strong></h2>
<p>In this section, we'll create an authentication service that generates JSON Web Tokens (JWTs).</p>
<p>This service will have two methods: <code>signup</code> and <code>login</code>. The <code>signup</code>
method will take a signup request object containing <code>name</code>, <code>email</code>, and
<code>password</code>),and the <code>login</code> method will take a login request object
containing <code>email</code> and <code>password</code>. Both methods will return a JWT. </p>
<p>Let’s start by creating a resource module for the authentication APIs.</p>
<p>Create <code>auth</code> resource with Nest CLI:</p>
<p><code>$ nest generate res auth</code></p>
<p>Then define the DTO for both signup and login. Go to the <strong>dto</strong> folder in the <strong>src/auth/dto</strong> folder:</p>
<p><strong>signup.dto.ts</strong>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SignUpDto</span> </span>{
<span class="hljs-attr">name</span>: string;
email: string;
password: string;
}
</code></pre>
<p><strong>login.dto.ts</strong>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Login</span> </span>{
<span class="hljs-attr">email</span>: string;
password: string;
}
</code></pre>
<p>Next, create a <strong>.env</strong> file in the root directory:</p>
<pre><code class="lang-env">JWT_SECRET=secret
JWT_EXPIRES=3d
</code></pre>
<p>Then add the <code>PassportModule</code>, <code>JwtModule</code> and <code>JwtStrategy</code> to <code>AuthModule</code>. We'll start by installing these packages:</p>
<p><code>$ npm i @nestjs/passport @nestjs/jwt passport passport-jwt bcryptjs</code></p>
<p>Go to <strong>src/auth/auth.module.ts</strong> and import these packages:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { AuthService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./auth.service'</span>;
<span class="hljs-keyword">import</span> { AuthController } <span class="hljs-keyword">from</span> <span class="hljs-string">'./auth.controller'</span>;
<span class="hljs-keyword">import</span> { PassportModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/passport'</span>;
<span class="hljs-keyword">import</span> { JwtModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/jwt'</span>;
<span class="hljs-keyword">import</span> { ConfigModule, ConfigService } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/config'</span>;
<span class="hljs-keyword">import</span> { MongooseModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/mongoose'</span>;
<span class="hljs-keyword">import</span> { UserSchema } <span class="hljs-keyword">from</span> <span class="hljs-string">'src/users/entities/user.entity'</span>;


@Module({
<span class="hljs-attr">imports</span>: [
PassportModule.register({ <span class="hljs-attr">defaultStrategy</span>: <span class="hljs-string">'jwt'</span> }),
JwtModule.registerAsync({
<span class="hljs-attr">imports</span>: [ConfigModule],
<span class="hljs-attr">inject</span>: [ConfigService],
<span class="hljs-attr">useFactory</span>: (config: ConfigService) =&amp;gt; {
<span class="hljs-keyword">return</span> {
<span class="hljs-attr">secret</span>: config.get&amp;lt;string&amp;gt;(<span class="hljs-string">'JWT_SECRET'</span>),
<span class="hljs-attr">signOptions</span>: {
<span class="hljs-attr">expiresIn</span>: config.get&amp;lt;string | number&amp;gt;(<span class="hljs-string">'JWT_EXPIRES'</span>),
},
};
},
}),
MongooseModule.forFeature([{ <span class="hljs-attr">name</span>: <span class="hljs-string">'User'</span>, <span class="hljs-attr">schema</span>: UserSchema }]),
],
<span class="hljs-attr">controllers</span>: [AuthController],
<span class="hljs-attr">providers</span>: [AuthService],
})
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthModule</span> </span>{}
</code></pre>
<p>The <code>PassportModule.register</code> configures the Passport module to use the JWT strategy as the authentication mechanism.</p>
<p>The <code>JwtModule.registerAsync</code> configures the JWT module using asynchronous registration process, such a the token expiration time.</p>
<p>The <code>MongooseModule.forFeature()</code> configures mongoose to us the <code>UserSchema</code> for the <code>User</code> model</p>
<p>These imports enable the authentication module to manage user authentication, JWT generation, and database interaction.</p>
<p>Next, create the <code>AuthServices</code> for signup and login in the <strong>src/auth/auth.service.ts</strong> directory:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Injectable, UnauthorizedException} <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { JwtService } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/jwt'</span>;
<span class="hljs-keyword">import</span> { InjectModel } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/mongoose'</span>;
<span class="hljs-keyword">import</span> { Model } <span class="hljs-keyword">from</span> <span class="hljs-string">'mongoose'</span>;
<span class="hljs-keyword">import</span> { User } <span class="hljs-keyword">from</span> <span class="hljs-string">'src/users/entities/user.entity'</span>;
<span class="hljs-keyword">import</span> { SignUpDto } <span class="hljs-keyword">from</span> <span class="hljs-string">'./dto/signup.dto'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> bcrypt <span class="hljs-keyword">from</span> <span class="hljs-string">'bcryptjs'</span>;
<span class="hljs-keyword">import</span> { LoginDto } <span class="hljs-keyword">from</span> <span class="hljs-string">'./dto/login.dto'</span>;
<span class="hljs-keyword">import</span> { ConfigService } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/config'</span>;

@Injectable()
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthService</span> </span>{
<span class="hljs-keyword">constructor</span>(
@InjectModel(User.name) private userModel: Model&amp;lt;User&amp;gt;,
private jwtService: JwtService,
private configService: ConfigService,
) {}

<span class="hljs-keyword">async</span> signUp(signupDto: SignUpDto) {
<span class="hljs-keyword">const</span> { name, email, password } = signupDto;

<span class="hljs-keyword">const</span> hashedPassword = <span class="hljs-keyword">await</span> bcrypt.hash(password, <span class="hljs-number">10</span>);
<span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.userModel.create({
name,
email,
<span class="hljs-attr">password</span>: hashedPassword,
});

<span class="hljs-keyword">await</span> user.save();

<span class="hljs-keyword">const</span> token = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.jwtService.sign(
{ <span class="hljs-attr">id</span>: user.id },
{
<span class="hljs-attr">secret</span>: <span class="hljs-built_in">this</span>.configService.get(<span class="hljs-string">'JWT_SECRET'</span>),
<span class="hljs-attr">expiresIn</span>: <span class="hljs-built_in">this</span>.configService.get(<span class="hljs-string">'JWT_EXPIRES'</span>),
},
);
<span class="hljs-keyword">return</span> { token };
}

<span class="hljs-keyword">async</span> login(loginDto: LoginDto) {
<span class="hljs-keyword">const</span> { email, password } = loginDto;
<span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.userModel.findOne({
email,
});

<span class="hljs-keyword">if</span> (!user) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(<span class="hljs-string">'invalid email or
password'</span>);
<span class="hljs-keyword">const</span> passwordMatch = <span class="hljs-keyword">await</span> bcrypt.compare(password,
user.password);
<span class="hljs-keyword">if</span> (!passwordMatch)
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(<span class="hljs-string">'invalid email or password'</span>);
<span class="hljs-keyword">const</span> token = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.jwtService.sign(
{ <span class="hljs-attr">id</span>: user.id },
{
<span class="hljs-attr">secret</span>: <span class="hljs-built_in">this</span>.configService.get(<span class="hljs-string">'JWT_SECRET'</span>),
},
);
<span class="hljs-keyword">return</span> { token };
}
}
</code></pre>
<p>In the <code>AuthService</code>, the <code>signUp</code> method facilitates user registration by:</p>
<ul>
<li>Destructuring the <code>SignupDto</code> object to extract user credentials.</li>
<li>Hashing the password using <code>bcrypt</code> for secure storage.</li>
<li>Creating a new user document in the database via the <code>userModel</code>.</li>
<li>Saving the user document to the database.</li>
<li>Generating a JWT token using <code>jwtService</code> upon successful registration.</li>
<li>Returning the JWT token to the client.</li>
</ul>
<p>The <code>login</code> method authenticates users by:</p>
<ul>
<li>Destructuring the <code>LoginDto</code> object to verify user credentials.</li>
<li>Comparing the input password with the stored hash to ensure a match.</li>
<li>Throwing an <code>UnauthorizedException</code> error if the passwords do not match.</li>
<li>Utilizing the <code>jwtService</code> to sign the user and generate a JWT token upon successful authentication.</li>
<li>Returning the JWT token to the client.</li>
</ul>
<p>Update the <code>AuthController</code> for signup and login in the <strong>src/auth/auth.controller.ts</strong> directory:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Controller, Post, Body } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { AuthService } <span class="hljs-keyword">from</span> <span class="hljs-string">'./auth.service'</span>;
<span class="hljs-keyword">import</span> { SignUpDto } <span class="hljs-keyword">from</span> <span class="hljs-string">'./dto/signup.dto'</span>;
<span class="hljs-keyword">import</span> { LoginDto } <span class="hljs-keyword">from</span> <span class="hljs-string">'./dto/login.dto'</span>;

@Controller(<span class="hljs-string">'auth'</span>)
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthController</span> </span>{
<span class="hljs-keyword">constructor</span>(private readonly authService: AuthService) {}

@Post(<span class="hljs-string">'signup'</span>)
signUp(@Body() signupDto: SignUpDto) {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.authService.signUp(signupDto);
}

@Post(<span class="hljs-string">'login'</span>)
signin(@Body() loginDto: LoginDto) {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.authService.login(loginDto);
}
}
</code></pre>
<p>With these steps, you’ve implemented a basic user login and signup in your application. In the next sections, we’ll test the <code>login</code> and <code>signup</code> routes.</p>
<h2 id="heading-testing-in-postman"><strong>Testing in Postman</strong></h2>
<p>Now that we've set up our endpoints, it's time to put them to the test.
For this example, I'll be using Postman as my API client, but feel free
to use any tool or client that suits your needs. Let's see our API in
action!</p>
<h3 id="heading-how-to-create-a-user-with-the-signup-endpoint"><strong>How to Create a User With the <code>/signup</code> Endpoint:</strong></h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image4-1.png" alt="postman signup test" width="600" height="400" loading="lazy"></p>
<p>After sending a POST request to the /signup endpoint using Postman, we
received a response containing the accessToken. You can verify that a new
user has been successfully created by checking the database.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image1.png" alt="mongodb compass signup verification" width="600" height="400" loading="lazy"></p>
<h3 id="heading-login-as-an-existing-user-with-the-login-endpoint"><strong>Login as an existing user with the <code>/login</code> endpoint:</strong></h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image2-1.png" alt="postman signin test" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Congratulations, you've successfully implemented comprehensive
authentication using NestJS, Mongoose, and Passport. We designed a secure
signup and login process, and generated JSON Web Tokens (JWTs).</p>
<p>To further improve and expand your knowledge on authentication, look
into authorization, protecting routes with authentication middleware,
and implementing email verification and password reset functionality.</p>
<p>This foundation provides a solid starting point for building a robust
and scalable authentication system. This project was a pleasure to work
on, and I hope you found it equally enjoyable. </p>
<p>For your convenience, the project <a target="_blank" href="https://github.com/dotun2203/basic-nest-authentication"><u>repository is available on Github</u></a>.</p>
<p>Please don't hesitate to connect with me on Twitter at <a target="_blank" href="https://x.com/Adedot1Abimbola?t=2A7m7RbbIzJei3rrjxsVuA&amp;s=09"><u>@Adedot1Abimbola</u></a>.
I'd love to hear from you</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use JSON Web Tokens for Secure Authentication in Flask Applications ]]>
                </title>
                <description>
                    <![CDATA[ Passwords, credit card information, personal identification numbers (PINs) – these are all critical assets used for authorization and authentication. This means they need to be protected from unauthorized users. As developers, we are tasked with safe... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/jwt-authentication-in-flask/</link>
                <guid isPermaLink="false">66c37432ad70110156766fe4</guid>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Flask Framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JSON Web Tokens ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JWT ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yemi Ojedapo ]]>
                </dc:creator>
                <pubDate>Wed, 17 Apr 2024 16:29:02 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/pexels-soumil-kumar-735911--1-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Passwords, credit card information, personal identification numbers (PINs) – these are all critical assets used for authorization and authentication. This means they need to be protected from unauthorized users.</p>
<p>As developers, we are tasked with safeguarding these sensitive bits of info, and it's important to implement strong secure measures in our applications. </p>
<p>Now, there are many authentication mechanisms available for securing data, like OAuth, OpenID Connect, and JSON Web Tokens (JWTs).</p>
<p>In this article, I'll show you how to use JWTs when securing information in APIs by integrating JWT-based authentication in a Flask application. </p>
<p>Here's what this article will cover:</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-a-json-web-token">What is a JSON Web Token?</a></li>
<li><a class="post-section-overview" href="#heading-how-do-jwts-work">How Do JWTs Work?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-json-web-tokens-to-authenticate-flask-applications">How to Use JSON Web Tokens to Authenticate Flask Applications</a>  </li>
<li><a class="post-section-overview" href="#heading-1-install-the-dependencies">Install dependencies</a>  </li>
<li><a class="post-section-overview" href="#heading-2-create-a-database-and-user-model">Create a database and user model</a>  </li>
<li><a class="post-section-overview" href="#3-configure-the-application-for-jwt-authorization">Configure the application for JWT authentication</a>  </li>
<li><a class="post-section-overview" href="#heading-4-create-protected-routes">Create protected routes</a>  </li>
<li><a class="post-section-overview" href="#heading-5-create-a-login-page">Create a Login Function</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along with this tutorial you will need:</p>
<ul>
<li>An understanding of HTTP Methods</li>
<li>An understanding of how to create APIs in Flask</li>
<li>VS Code (or other similar) editor</li>
<li>A terminal</li>
</ul>
<h2 id="heading-what-is-a-json-web-token">What is a JSON Web Token?</h2>
<p>JSON Web Tokens, or JWTs, are an authentication mechanism used to securely transmit information between a client and a server in JSON format. </p>
<p>This information can be verified and trusted because it is digitally signed with the <a target="_blank" href="https://xilinx.github.io/Vitis_Libraries/security/2020.1/guide_L1/internals/hmac.html">HMAC algorithm</a> or a public/private key pair using <a target="_blank" href="https://en.wikipedia.org/wiki/RSA_(cryptosystem)">RSA</a> or <a target="_blank" href="https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm">ECDSA</a>. </p>
<p>The tokens are encoded into three parts, each divided by a period, like this:</p>
<pre><code>Header.Payload.Signature
</code></pre><ul>
<li><strong>Header:</strong> This defines the type of token (JWT) and the signing algorithm used.</li>
<li><strong>Payload:</strong> This carries user-specific data like user ID, username, roles, and any additional claims you want to include. This payload is encoded in Base64 for maximum security.</li>
<li><strong>Signature:</strong> This is a hashed combination of the header, the payload, and the server's secret key. It ensures the token's integrity and that any modifications to the token will be detected.</li>
</ul>
<h2 id="heading-how-do-jwts-work">How Do JWTs Work?</h2>
<p>To understand how JWTs work, you need to know what the tokens are meant to do. JWTs are not created to hide data but to ensure that the data being sent is authenticated. This is why the JWT is signed and encoded, not encrypted.</p>
<p>A JWT acts as a stateless means of transmitting data from a client to a server. This means that it doesn't store any session object in the browser, so the browser doesn't maintain a session state between requests. </p>
<p>Instead, JWTs use a token that is sent in a request header each time a request is made. This token confirms that the token sent is authenticated and is allowed access to make that request.  </p>
<p>Let's look at how this happens:</p>
<ol>
<li>A user attempts to log in and sends a username and password to be verified by the server.</li>
<li>The verification function carries out a check to see if there's a match in the database.</li>
<li>A JWT is then generated by the server once the user is successfully authenticated (logged in) using their information (payload), such as user ID or username, and signs it using a secret key.</li>
<li>The generated JWT is sent along as a bearer token with every request header to check if the user is authenticated to make that request.</li>
</ol>
<h2 id="heading-how-to-use-json-web-tokens-to-authenticate-flask-applications">How to Use JSON Web Tokens to Authenticate Flask Applications</h2>
<p>To demonstrate how you can implement JWT authentication in Flask, we'll create a simple application that uses JWT for handling login functions and accessing protected routes.</p>
<h3 id="heading-1-install-the-dependencies">1. Install the dependencies</h3>
<p>Run this command to install the dependencies we'll need</p>
<pre><code>pip install flask flask-bcrypt Flask-JWT-Extended
</code></pre><p>Next, make sure you import the dependencies and initialize your Flask application with this code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, jsonify, session, request, redirect, url_for
<span class="hljs-keyword">from</span> flask_jwt_extended <span class="hljs-keyword">import</span> JWTManager, create_access_token, jwt_required, get_jwt_identity, get_jwt


app = Flask(__name__)

////WRITE MAIN CODE HERE


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-keyword">with</span> app.app_context():
        app.run(debug=<span class="hljs-literal">True</span>)
</code></pre>
<h3 id="heading-2-create-a-database-and-user-model">2. Create a database and User Model</h3>
<p>To do this, we'll use SQL-Alchemy, which is a Python SQL toolkit that makes it less complex to use SQL in Python scripts. </p>
<p>To set up SQL Alchemy in your application, follow these steps:</p>
<p>First, open your terminal or command prompt and enter the following command:</p>
<pre><code>pip install sqlalchemy
</code></pre><p>This command installs SQLAlchemy in your Python environment, making it available in your project directory.</p>
<p>Next, configure your application to make use of your preferred Database Management System (DBMS). This tutorial will use the SQlite3 DBMS as it doesn't require a separate server:</p>
<pre><code>app.config[<span class="hljs-string">'SQLALCHEMY_DATABASE_URI'</span>] = <span class="hljs-string">'sqlite:///site.db'</span>
</code></pre><p>This code snippet instructs Flask-SQLAlchemy to create and use the <code>site.db</code> file in your project directory as the SQLite database for the application.</p>
<p>Then initialize the database in your application:</p>
<pre><code>db = SQLAlchemy(app)
</code></pre><p>This instance of the database acts as a bridge between the application and the database.</p>
<p>Now create the User Model where we'll store the user's details in this tutorial:</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>(<span class="hljs-title">db</span>.<span class="hljs-title">Model</span>, <span class="hljs-title">UserMixin</span>):
    <span class="hljs-title">id</span> </span>= db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(<span class="hljs-number">20</span>), unique=True, nullable=False)
    password = db.Column(db.String(<span class="hljs-number">80</span>), nullable=False)
    is_active = db.Column(db.Boolean(), <span class="hljs-keyword">default</span>=True)
    cart = db.Column(<span class="hljs-built_in">JSON</span>, nullable=True, <span class="hljs-keyword">default</span>=list)  # Make cart nullable

    # Define the relationship between User and CartProducts
    cart_products = relationship(<span class="hljs-string">'CartProducts'</span>, backref=<span class="hljs-string">"user"</span>, lazy=<span class="hljs-string">"dynamic"</span>)
    # Define the relationship between User and Wishlists
    wishlists = db.relationship(<span class="hljs-string">'Wishlists'</span>, backref=<span class="hljs-string">'user'</span>, lazy=True)

    def __repr__(self):
        <span class="hljs-keyword">return</span> f<span class="hljs-string">'&lt;User {self.username}&gt;'</span>
</code></pre><p> <strong>Note:</strong> You can create other models using the same syntax to represent different data entities in your application.</p>
<h3 id="heading-3-configure-the-application-for-jwt-authentication">3. Configure the application for JWT Authentication</h3>
<p>To implement JWT authentication in your Flask application, import the necessary libraries and set up the appropriate configurations with this code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, jsonify, request
<span class="hljs-keyword">from</span> flask_sqlalchemy <span class="hljs-keyword">import</span> SQLAlchemy
<span class="hljs-keyword">from</span> flask_jwt_extended <span class="hljs-keyword">import</span> JWTManager, create_access_token, jwt_required

app = Flask(__name__)

<span class="hljs-comment"># Configuration</span>
app.config[<span class="hljs-string">'SECRET_KEY'</span>] = <span class="hljs-string">'your_strong_secret_key'</span>
app.config[<span class="hljs-string">"JWT_SECRET_KEY"</span>] = <span class="hljs-string">'your_jwt_secret_key'</span>
app.config[<span class="hljs-string">'JWT_TOKEN_LOCATION'</span>] = [<span class="hljs-string">'headers'</span>]

<span class="hljs-comment"># Database Initialization</span>
db = SQLAlchemy(app)

<span class="hljs-comment"># JWT Initialization</span>
jwt = JWTManager(app)

<span class="hljs-comment"># Rest of the application code (routes, etc.)</span>
</code></pre>
<p>This code snippet imports the following components needed for our application:</p>
<ul>
<li><strong>app.config['SECRET_KEY']</strong> sets the Flask application's secret key which is used to securely sign session cookies and other security-related needs.</li>
<li><strong>app.config['JWT_SECRET_KEY']</strong> sets the secret key used to encode and decode JWTs in for Flask-JWT operations.</li>
<li><strong>app.config['JWT_TOKEN_LOCATION']</strong> specifies where the application should look for the JWT. Here it's set to look in the HTTP headers.</li>
</ul>
<p>Once we've set this up, we can create the endpoints and routes that we intend to protect.</p>
<h3 id="heading-4-create-protected-routes">4. Create protected routes</h3>
<p>Protected routes are the pages that we intend to keep hidden from unauthorized users. </p>
<p>For example, let's assume we are trying to get into a venue that's exclusive to members of a society. But a guard is securing the venue from "unauthorized users" like us. In this situation, we are the application's users, the venue is the URL we are protecting, and the guard protecting the venue is a <strong><code>@jwt_required</code></strong> decorator.</p>
<p>The <strong><code>@jwt_required</code></strong> decorator is used to protect specific routes that require authentication. This decorator will confirm that there's a JWT access token in the request headers before allowing access to the page:</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.route('/get_name', methods=['GET'])</span>
<span class="hljs-meta">@jwt_required()</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_name</span>():</span>
    <span class="hljs-comment"># Extract the user ID from the JWT</span>
    user_id = get_jwt_identity()
    user = User.query.filter_by(id=user_id).first()

    <span class="hljs-comment"># Check if user exists</span>
    <span class="hljs-keyword">if</span> user:
        <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'User found'</span>, <span class="hljs-string">'name'</span>: user.name})
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'User not found'</span>}), <span class="hljs-number">404</span>
</code></pre>
<p>In this code snippet, we created a function that returns the name of the user after authentication. If the token is missing, invalid, or expired, the request will be denied, and typically, the server will return an HTTP <strong>401</strong> Unauthorized status.</p>
<h3 id="heading-5-create-a-login-page">5. Create a Login Page</h3>
<p>In this endpoint, we'll create a function that accepts username and password credentials from the client request (for example, form data) and compares the credentials gotten from the user with the user data in the database. If there's a match, a JWT access token will be generated containing the user's information.</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.route('/login', methods=['POST'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">login</span>():</span>
    data = request.get_json()
    username = data[<span class="hljs-string">'username'</span>]
    password = data[<span class="hljs-string">'password'</span>]
    print(<span class="hljs-string">'Received data:'</span>, username , password)

    user = User.query.filter_by(username=username).first()

    <span class="hljs-keyword">if</span> user <span class="hljs-keyword">and</span> bcrypt.check_password_hash(user.password, password):
        access_token = create_access_token(identity=user.id)
        <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Login Success'</span>, <span class="hljs-string">'access_token'</span>: access_token})
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'message'</span>: <span class="hljs-string">'Login Failed'</span>}), <span class="hljs-number">401</span>
</code></pre>
<p>In this example, the function checks the user's credentials against the database using bcrypt for secure password verification when a POST request is received. If the credentials are valid, the server generates a JWT for the user, allowing them to access protected routes.</p>
<p>Here's an example of a React form sending a POST request to the login endpoint:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;
<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> Footer <span class="hljs-keyword">from</span> <span class="hljs-string">"./Footer"</span>;
<span class="hljs-comment">// import "./Login.css";</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Login</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [password, setPassword] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [username, setUsername] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">const</span> handleLogin = <span class="hljs-keyword">async</span> (event) =&gt; {
    event.preventDefault();
    <span class="hljs-keyword">const</span> data = {
      <span class="hljs-attr">username</span>: username,
      <span class="hljs-attr">Password</span>: password,
    };

    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.post(<span class="hljs-string">"http://localhost:5000/login"</span>, {
        username,
        password,
      });
      <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">"access_token"</span>, response.data.access_token);
      <span class="hljs-comment">// Redirect to protected route</span>
      alert(<span class="hljs-string">"Login successful"</span>);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.error(error);
      <span class="hljs-comment">// Display error message to user</span>
    }
  };

  <span class="hljs-keyword">const</span> handleUsernameChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    setUsername(event.target.value);
  };

  <span class="hljs-keyword">const</span> handlePasswordChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    setPassword(event.target.value);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> &gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span> &gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
                <span class="hljs-attr">id</span>=<span class="hljs-string">""</span>
                <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Username"</span>
                <span class="hljs-attr">name</span>=<span class="hljs-string">"username"</span>
                <span class="hljs-attr">required</span>
                <span class="hljs-attr">value</span>=<span class="hljs-string">{username}</span>
                <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleUsernameChange}</span>
              /&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
                <span class="hljs-attr">id</span>=<span class="hljs-string">""</span>
                <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Your email"</span>
              /&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
                <span class="hljs-attr">required</span>
                <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Your Password"</span>
                <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span>
                <span class="hljs-attr">value</span>=<span class="hljs-string">{password}</span>
                <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handlePasswordChange}</span>
              /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleLogin}</span>&gt;</span>
            Log In
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );

}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Login;
</code></pre>
<p>In this React component, we provided a login form that uses Axios to send a POST request to the login endpoint. It manages username and password inputs using React's <code>useState</code> hook and submits these values once the form is submitted. </p>
<p>If the login is successful, it stores a JWT in local Storage. This allows the client-side application to retrieve the token easily when making authenticated requests to the server.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/jwtDemo-1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we've learned how to secure APIs with JSON Web Tokens in Flask. We covered the basics of JWTs, how they work, and provided a step-by-step process for implementing this method of authentication. This included everything from installing necessary dependencies to creating user models and protecting routes. </p>
<p>You can build upon this foundation, such as by adding refresh tokens, integrating with third-party OAuth providers, or handling more complex user permissions.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Implement Tokenization using JWT and Django Rest Framework ]]>
                </title>
                <description>
                    <![CDATA[ When I was a young girl, we used to have sports competitions like running a hundred meters, relays, swimming, and basketball games.  My strengths were swimming and basketball. I went home with many gifts or, as my school's game master said, a token o... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-jwt-and-django-rest-framework-to-get-tokens/</link>
                <guid isPermaLink="false">66ba555237218559f94f2076</guid>
                
                    <category>
                        <![CDATA[ Django ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JSON Web Tokens ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JWT ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Tokenization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Velda Kiara ]]>
                </dc:creator>
                <pubDate>Thu, 23 Feb 2023 15:53:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/01/Purple-Colorful-Tech-22-YouTube-Channel-Art.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When I was a young girl, we used to have sports competitions like running a hundred meters, relays, swimming, and basketball games. </p>
<p>My strengths were swimming and basketball. I went home with many gifts or, as my school's game master said, a <strong>token of appreciation</strong>.</p>
<p>A token is a secure form used to transmit data between two parties. The medals I got from the competitions hold a lot of value for me, and if I gave them to someone else, they would merely be trinkets.</p>
<p>JavaScript Object Notation (JSON) is a format used to present structured data based on JavaScript syntax. We use it to transmit data in web applications by sending the data from the server to the client's display.</p>
<p>JWT (JSON Web Token) is a form of transmitting a JSON object as information between parties. Let's learn more about what JWTs are and how they work.</p>
<h2 id="heading-the-importance-of-jwts">The Importance of JWTs</h2>
<p>JWTs are important for two main reasons:</p>
<p><strong>Authorization</strong>: in our competitions, we had to present our school identification cards for verification before getting our medals. </p>
<p>Our school IDs acted like log in requests in applications. These requests, in apps, contain a JWT that allows users to get permission to access any resources that are accessible with that token.</p>
<p><strong>Information exchange</strong>: my medals were a badge of honor and a way to get a certificate signed and stamped by our games master for legitimacy. </p>
<p>We use JWTs to exchange information in cases where they are signed – for example using public-private key pairs to make sure that the integrity of the information is not compromised since the payload and header are used to compute signatures.</p>
<h2 id="heading-how-do-jwts-work">How Do JWTs Work?</h2>
<p>A JWT is an authorization token that is included in requests. Here's an example of what one looks like:</p>
<pre><code class="lang-python">eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjczNTI3ODMzLCJpYXQiOjE2NzM1Mjc0MzAsImp0aSI6IjNkMGRkMGZiZjA5ZjRmZWU4MTZmMGQyOTQ5OWU3ZmFmIiwidXNlcl9pZCI6IjFmYTBiMGJkLWY4MmMtNDQzNy1iMmViLTMwOTYzMGZkNzQ2NiJ9.-swqFh4MCecycmodQfO8ZmfsDJ3DqoZBsdNzEWhfzhA
</code></pre>
<p>You can get a JWT through logging in with a username and password. In exchange the server returns an access and refresh token in the form of a JWT. The tokens access resources on the server.</p>
<p>The lifetimes of the access and refresh tokens vary since access tokens last for five minutes or less while the refresh tokens can last for 24 hours. But you can customize the timelines of both types of tokens.</p>
<p>If the access token expires, the client uses the refresh token to summon a new access token from the server. Once the refresh token expires, the user must log in again with their username and password to get a new pair of tokens. </p>
<p>It works this way to prevent damage that can occur when a token is compromised and to prevent unauthorized access.</p>
<h3 id="heading-different-parts-of-a-jwt">Different parts of a JWT</h3>
<p>JWTs hold information in three parts, as you can see in the following code blocks:</p>
<pre><code class="lang-python">header.payload.signature
</code></pre>
<pre><code class="lang-python">header = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9F5
payload = eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTQzODI4NDMxLCJqdGkiOiI3ZjU5OTdiNzE1MGQ0NjU3OWRjMmI0OTE2NzA5N2U3YiIsInVsztZXJfaWQiOjF9
signature = Ju70kdcaHKn1Qaz8H42zrOYk0Jx9kIciuhkTn9Xx7vhikY
</code></pre>
<p>The above JWT is encoded using <a target="_blank" href="https://en.wikipedia.org/wiki/Base64">Base64</a>. Once decoded, the information will include something similar to the following parts:</p>
<h4 id="heading-header">Header</h4>
<p>The header contains:</p>
<ul>
<li>type: the specification that the token is a JWT</li>
<li>algorithm: the signing algorithm used to sign said token</li>
</ul>
<p>Algorithms that are used to sign include <a target="_blank" href="https://www.geeksforgeeks.org/rsa-algorithm-cryptography/">RSA</a>, <a target="_blank" href="https://www.geeksforgeeks.org/hmac-algorithm-in-computer-network/">HMAC</a>, or <a target="_blank" href="https://www.n-able.com/blog/sha-256-encryption#:~:text=The%20SHA%2D256%20algorithm%20is,that%20is%20256%20bits%20long.">SHA256</a>. The signatures for the tokens serve two purposes – integrity and authenticity.</p>
<p>An example of a header with the algorithm and type is as shown below:</p>
<pre><code class="lang-python">{
  <span class="hljs-string">"alg"</span>: <span class="hljs-string">"HS256"</span>,
  <span class="hljs-string">"typ"</span>: <span class="hljs-string">"JWT"</span>
}
</code></pre>
<h4 id="heading-payload">Payload</h4>
<p>The payload contains the intended messages which are commonly known as claims and metadata, as well as any other information.</p>
<p>There are three types of claims:</p>
<ol>
<li>Registered claims: they include exp (expiration time), iss (issuer), sub (subject) and aud (audience). They are highly recommended since they provide information on the use and condition of use of the token.</li>
<li>Public claims: these are claims that are unique to avoid collisions with other services that use JWT. </li>
<li>Private claims: these are claims that are used specifically between two parties that understand the meaning and use. Like the example of my medals, my games master and I understood the value.</li>
</ol>
<p>Below is an example of what a payload looks like.</p>
<pre><code class="lang-python">{
  <span class="hljs-string">"token_type"</span>: <span class="hljs-string">"access"</span>,
  <span class="hljs-string">"exp"</span>: <span class="hljs-number">1543828431</span>,
  <span class="hljs-string">"jti"</span>: <span class="hljs-string">"7f5997b7150d46579dc2b49167097e7b"</span>,
  <span class="hljs-string">"user_id"</span>: <span class="hljs-number">4</span>
}
</code></pre>
<ul>
<li><code>token_type</code> is a label that shows what kind of token this is. Case in point, it's an <code>access token</code>.</li>
<li><code>exp</code> stands for expiration. It's the time the token will stop working – in this case the number represents date and time in Unix time.</li>
<li><code>jti</code> stands for <code>JWT ID</code>. It's a unique identifier for this specific token. The ID is used to keep track of which tokens have been used, to prevent use of the same token more than once.</li>
<li><code>user_id</code>:  is an identifier of the user this token belongs to. In this case, the number 4 is the user identification.</li>
</ul>
<h4 id="heading-signature">Signature</h4>
<p>The signature verifies that information is only accessed by authorized people. It is issued by the JWT backend using base64 + payload +SECRET_KEY. </p>
<p>The signature is verified for each request. To validate the signature, you use the SECRET_KEY. Remember the purpose of having it called SECRET_KEY is so that it is secret. </p>
<p>Now let's see how JWTs work in practice with an example.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>To illustrate how JWTs work, I will use the <a target="_blank" href="https://django-rest-framework-simplejwt.readthedocs.io/en/latest/">simple JWT</a>, which is a JSON Web Token authentication plugin for Django Rest Framework (DRF). </p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>To follow along, you should have some prior knowledge of HTML files and how to set up a Django project. You should also be familiar with what an API (Application Programming Interface) is. </p>
<p>You will also need to have a Django project already setup. You could name it <code>tokenization</code> also add an app called <code>access</code>. </p>
<p>Once your app and project are set up, you are good to go. </p>
<h3 id="heading-simple-jwt-installation">Simple JWT Installation</h3>
<p>As mentioned, I will be using the <code>simple JWT</code> which provides JWT authentication for the Django Rest Framework (DRF).  </p>
<p>DRF is a third-party package for Django used as a toolkit for building Web API's. It provides a seamless experience while you build, test, debug and maintain RESTful APIs using in Django. </p>
<p>RESTful APIs (Representational State Transfer APIs) are a type of web API that allow communication between different applications over the internet in a fast, reliable, and scalable way.</p>
<p>RESTful APIs are stateless. This means that requests contain information to finalize the request, and the server does not need to remember the history of previous requests.</p>
<p>To install <code>simple JWT</code>, use the command below in your terminal:</p>
<pre><code class="lang-python">pip install djangorestframework_simplejwt
</code></pre>
<h3 id="heading-how-to-set-authentication-to-simple-jwt">How to Set Authentication to Simple JWT</h3>
<p>Go to your project (tokenization), and in the <code>settings.py</code> file, add the following code to configure the REST framework to use simple JWT for authentication:</p>
<pre><code class="lang-python">REST_FRAMEWORK = {
    <span class="hljs-string">'DEFAULT_AUTHENTICATION_CLASSES'</span>: [
        <span class="hljs-string">'rest_framework_simplejwt.authentication.JWTAuthentication'</span>,
    ],
}
</code></pre>
<p>The code above specifies the default authentication class to be used for all API views in the application.</p>
<p><code>DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework_simplejwt.authentication.JWTAuthentication', ]</code> sets the default authentication class to be  <code>JWTAuthentication</code> from the <code>rest_framework_simplejwt</code> package. This means that all API views in the project will use JWT authentication by default.</p>
<h3 id="heading-how-to-define-uniform-resource-locator-patterns">How to Define Uniform Resource Locator Patterns</h3>
<p>In your project (tokenization), create a file (if you have not created one yet) named<br><code>urls.py</code> . Then add the following code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path
<span class="hljs-keyword">from</span> rest_framework_simplejwt <span class="hljs-keyword">import</span> views <span class="hljs-keyword">as</span> jwt_views

urlpatterns = [
    path(<span class="hljs-string">'api/token/'</span>, jwt_views.TokenObtainPairView.as_view(), name=<span class="hljs-string">'token_obtain_pair'</span>),
    path(<span class="hljs-string">'api/token/refresh/'</span>, jwt_views.TokenRefreshView.as_view(), name=<span class="hljs-string">'token_refresh'</span>),
]
</code></pre>
<p>The <code>path</code> function creates a new URL pattern and maps it to the specified view.</p>
<p>The URL (Uniform Resource Locator) path <code>/api/token/</code> is mapped to the view <code>jwt_views.TokenObtainPairView.as_view()</code>. The <code>as_view()</code>method converts the class-based view to a function-based view used in routing. The <code>name</code> parameter makes it easy to refer to the URL pattern in other parts of your code. </p>
<p>We have now created an endpoint for obtaining JWT tokens. If a request is made to the endpoint, <code>TokenObtainPairView</code>, <code>view</code> handles the request and returns a JWT token in the response for authentication.</p>
<h3 id="heading-how-to-customize-the-token-timelines">How to Customize the Token Timelines</h3>
<p>To customize the timeline of the tokens, first add the <code>rest_framework_simplejwt</code> in your installed apps section in the project (tokenization) under the <code>settings.py</code> file. The purpose for adding the <code>rest_framework_simplejwt</code> is for configuration. </p>
<p>To add the timeline we want, we will first create a dictionary called <code>SIMPLE_JWT</code>. Then we'll create variables to hold timelines for the access and refresh token. </p>
<p>The code snippet below shows how to set up the timelines for the tokens:</p>
<pre><code class="lang-python">INSTALLED_APPS = [
    <span class="hljs-comment">#other files</span>
    <span class="hljs-string">'rest_framework_simplejwt'</span>,
]

SIMPLE_JWT = {
    <span class="hljs-string">'ACCESS_TOKEN_LIFETIME'</span>: timedelta(minutes=<span class="hljs-number">5</span>),
    <span class="hljs-string">'REFRESH_TOKEN_LIFETIME'</span>: timedelta(days=<span class="hljs-number">1</span>),
}
</code></pre>
<p>Before you use the <code>timedelta</code> you will need to import it like this: <code>python from datetime import timedelta</code>.</p>
<h3 id="heading-visual-interaction-of-the-api">Visual Interaction of the API</h3>
<p>In this section, we will use the Django Rest Framework web interface to access the endpoints.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/Screenshot-2023-01-13-at-10.55.14.png" alt="Image" width="600" height="400" loading="lazy">
<em>Testing tokenization</em></p>
<p>The access and refresh tokens are highlighted in red, as shown above. To get the tokens for a user, you need to input the correct password and username for an existing user.</p>
<p> Use a refresh token through this endpoint for an access token: <code>/api/token/refresh/</code> </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/Screenshot-2023-01-13-at-10.55.53.png" alt="Image" width="600" height="400" loading="lazy">
<em>Refresh token</em></p>
<p>A refresh token gets an access token without the user using their login credentials to extend the user's session. This provides a seamless user experience and improves security by reducing the number of times a user has to key in their credentials.</p>
<h3 id="heading-how-to-add-a-homepage">How to Add a Homepage</h3>
<p>If you want to create a visually appealing interface, you can build a custom homepage to replace the current display of the API endpoints and error messages.</p>
<p>To add a homepage to your Django project, follow these steps:</p>
<ol>
<li>Create a <code>templates</code> folder in your application (access). Then, add a <code>index.html</code> file inside.</li>
<li>Create a <code>static</code> folder in your application (access) and add a <code>img</code> folder inside.</li>
<li>In this case, I wanted to display an image, so I added the <code>me.png</code> in the img folder.</li>
<li>Add the code below to your <code>html</code> file:</li>
</ol>
<pre><code class="lang-html">{% load static %}
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
        <span class="hljs-selector-tag">body</span> {
            <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">url</span>(<span class="hljs-string">"{% static 'img/me.png' %}"</span>);
            <span class="hljs-attribute">background-size</span>: cover;
        }
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>You will notice that we needed to add <code>{% load static %}</code> at the top of the file for proper styling and functioning of the site. <code>{% load static %}</code> serves files like stylesheets(CSS), scripts(JS), and images to your HTML templates to provide the user with a seamless experience while viewing your site.</p>
<h3 id="heading-how-to-define-the-url-patterns-for-your-home-page">How to Define the URL Patterns For Your Home Page</h3>
<p>In your app's (access) <code>urls.py</code> file (create one if you do not have it) add this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path
<span class="hljs-keyword">from</span> django.views.generic <span class="hljs-keyword">import</span> TemplateView

app_name=<span class="hljs-string">'access'</span>

urlpatterns=[
path(<span class="hljs-string">''</span>, TemplateView.as_view(template_name=<span class="hljs-string">'home.html'</span>), name=<span class="hljs-string">'home'</span>),

]
</code></pre>
<p>In your project's (tokenization) <code>settings.py</code> file, add the following code so that the static files are served:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Static files settings</span>
STATIC_ROOT = os.path.join(BASE_DIR, <span class="hljs-string">'static'</span>)
STATIC_URL = <span class="hljs-string">'/static/'</span>
STATICFILES_DIRS = [os.path.join(BASE_DIR, <span class="hljs-string">'access/static'</span>)]
</code></pre>
<p>Once you run the server, your home page should be like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/Screenshot-2023-01-13-at-10.54.54.png" alt="Image" width="600" height="400" loading="lazy">
<em>home page</em></p>
<h2 id="heading-bugs-and-solutions">Bugs and Solutions</h2>
<p>At some point, I may have deleted the <code>migrations</code> file which deleted some of the data I had. This caused the following error <code>django.db.utils.OperationalError: no such table: customUser</code>. </p>
<p>I was able to solve this through running the command <code>python manage.py migrate --run-syncdb</code> . The command syncs tables by looking into tables not created and then creating them.</p>
<p>I also had an issue of using a port that was already being used by a program I had left running and forgotten about. </p>
<p>To close a port you should identify the process using it by running the command <code>lsof -i :&lt;port_number&gt;</code>. This will show you the user using it and PID. To stop the process use <code>kill &lt;PID&gt;</code>. Additionally, you can use <code>sudo kill -9 -u &lt;username&gt; &lt;pid&gt;</code> .</p>
<p>It's good to know that to kill the port you will need administrator permissions. Also, stopping a process can cause data loss or unusual behavior so ensure your data is backed up before doing this.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this tutorial, you have learned how JWTs work, the structure of different tokens, how to use JWT and DRF to get tokens, how to create and serve static files in Django, and how to handle deleting migration files and kill a port.</p>
<p>There is so much you can learn about <a target="_blank" href="https://www.djangoproject.com/">Django</a> and the <a target="_blank" href="https://www.django-rest-framework.org/">Django Rest Framework.</a></p>
<p>The code for this article can be found <a target="_blank" href="https://github.com/VeldaKiara/tokenization">here</a>.</p>
<p>May your keyboard be swift, your bugs be few, and your fun meter be off the charts as you code away!</p>
<p>Thanks for reading my article on how to implement tokenization using JWT and Django Rest Framework. I'm always up for a good chat about coding and tech, so give me a follow on <a target="_blank" href="https://twitter.com/VeldaKiara">Twitter</a> and let's continue the conversation there.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Sign and Validate JSON Web Tokens – JWT Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ A JSON Web Token, or JWT, is an open standard for securely creating and sending data between two parties, usually a client and a server. If you've ever signed in to a site like freeCodeCamp with your Google or GitHub account, there's a good chance th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-sign-and-validate-json-web-tokens/</link>
                <guid isPermaLink="false">66ac880a2dd2c39dc134e0bf</guid>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authorization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JWT ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kristofer Koishigawa ]]>
                </dc:creator>
                <pubDate>Fri, 09 Dec 2022 10:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/01/shubham-dhage-gC_aoAjQl2Q-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A JSON Web Token, or JWT, is an open standard for securely creating and sending data between two parties, usually a client and a server.</p>
<p>If you've ever signed in to a site like freeCodeCamp with your Google or GitHub account, there's a good chance that you're already using a JWT.</p>
<p>In this article, we'll go over how JWTs are used, then dig into what JWTs are, and how they can securely transmit data through the signature and validation process.</p>
<h2 id="heading-how-jwts-are-used">How JWTs Are Used</h2>
<p>JWTs are usually used to manage user sessions on a website. While they're an important part of the token based authentication process, JWTs themselves are used for authorization, not authentication.</p>
<p>Here's a good overview of how token based authentication works:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/token-based-authentication.jpg" alt="A diagram showing the flow for token based authentication with JWT." width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://hackernoon.com/using-session-cookies-vs-jwt-for-authentication-sd2v3vci">Source</a></em></p>
<p>When you sign in to a site with a username and password, or with a third party method like Google, you're proving who you are with those sensitive details or access. This process is called <strong>authentication</strong>.</p>
<p>Once you're signed in, the site's server sends back a JWT that allows you access to things like your settings page, shopping cart, and so on. This process is called <strong>authorization</strong>.</p>
<p>You send your JWT to the server with each request. When the server receives it, it generates a signature using some data from your JWT, verifies it, and if your JWT is valid, it sends back a response.</p>
<h2 id="heading-what-are-jwts">What are JWTs?</h2>
<p>At their core, JWTs are just bits of encoded JSON data with a cryptographic signature at the end.</p>
<p>Here's an example of a JWT:</p>
<pre><code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlF1aW5jeSBMYXJzb24iLCJpYXQiOjE1MTYyMzkwMjJ9.WcPGXClpKD7Bc1C0CCDA1060E2GGlTfamrd8-W0ghBE
</code></pre><p>Each JWT is made up of three segments, each separated by a dot (<code>.</code>). These three segments are the header, payload, and signature.</p>
<p>If you copy and paste that JWT into the <a target="_blank" href="https://jwt.io/">JWT.io Debugger</a>, you can see the decoded versions of those three segments.</p>
<h3 id="heading-header-segment">Header Segment</h3>
<p>The header segment of a JWT contains information about the algorithm and token type.</p>
<p>Here's the header segment of the example JWT token above:</p>
<pre><code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
</code></pre><p>The header segment is base 64 URL encoded, and decodes to the following JSON object:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"alg"</span>: <span class="hljs-string">"HS256"</span>,
  <span class="hljs-attr">"typ"</span>: <span class="hljs-string">"JWT"</span>
}
</code></pre>
<p><code>"alg"</code> is the type of algorithm used in the last segment, the cryptographic signature. In this case, the HMAC SHA256 algorithm is used, though RSA is also common.</p>
<p><code>"typ"</code> is the type of token the segmented string is, which in this case is JWT.</p>
<h3 id="heading-payload-segment">Payload Segment</h3>
<p>The payload segment of a JWT contains registered claims or identifying information, usually for a user.</p>
<p>Here's the payload segment of the example JWT token above:</p>
<pre><code>eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlF1aW5jeSBMYXJzb24iLCJpYXQiOjE1MTYyMzkwMjJ9
</code></pre><p>The payload segment is also base 64 URL encoded, and decodes to the following JSON object:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"sub"</span>: <span class="hljs-string">"1234567890"</span>,
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Quincy Larson"</span>,
  <span class="hljs-attr">"iat"</span>: <span class="hljs-number">1516239022</span>
}
</code></pre>
<p>Since JWTs are usually used as part of the authentication method for sites, the payload segment usually contains identifying information for a user. These claims fall into three categories: registered, public, and private.</p>
<p>Registered claims are a set of predefined claims defined <a target="_blank" href="https://www.rfc-editor.org/rfc/rfc7519#section-4.1">here</a> that are optional, but recommended when using JWTs.</p>
<p>Public claims are optional claims, usually from the <a target="_blank" href="https://www.iana.org/assignments/jwt/jwt.xhtml">IANA JSON Web Token Registry</a>.</p>
<p>Private claims are optional, and are any claims that don't fall under the registered or public claims categories.</p>
<p><code>"sub"</code> is the subject of the JWT, and is usually a unique identifying string for a user in an application, usually an email address, username, or id. Subjects are registered claims.</p>
<p><code>"name"</code> is the full name of the user who was issued the JWT, and is a public claim.</p>
<p><code>"iat"</code> is the "issued at" date for the token, and is a registered claim.</p>
<h3 id="heading-signature-segment">Signature Segment</h3>
<p>The signature segment of a JWT contains the cryptographic signature of the token.</p>
<p>Here's the signature segment of the example JWT token above:</p>
<pre><code>WcPGXClpKD7Bc1C0CCDA1060E2GGlTfamrd8-W0ghBE
</code></pre><p>The signature segment is made up of the base 64 URL encoded header and payload segments, a secret (usually the contents of a key in a signing algorithm), and hashed using the algorithm defined in the header segment:</p>
<pre><code>HMACSHA256(
  base64UrlEncode(header) + <span class="hljs-string">"."</span> +
  base64UrlEncode(payload),
  your<span class="hljs-number">-256</span>-bit-secret
)
</code></pre><p>The signature helps ensure that the data in the header and payload segments haven't been tampered with, and the JWT can be trusted.</p>
<p>However, it's important to note that the cryptographic signature at the end of the JWT is just for validation. It doesn't encrypt any data in the header or payload segments of the token. So you should never send sensitive information like a user's password in a JWT – everything in the header and payload can and should be public.</p>
<h4 id="heading-how-to-validate-jwt-signatures">How to Validate JWT Signatures</h4>
<p>The exact method for validating a signature depends on the algorithm defined in the header segment and used to generate the signature itself.</p>
<p>For the HS256 signing algorithm, a private key is shared between two entities, say your application's server and an authentication server. This private key is used both to generate signatures for outgoing JWTs, and to validate signatures from incoming JWTs.</p>
<p>When your authentication server receives an incoming JWT, it uses the incoming JWT's header and payload segments and the shared private key to generate a signature.</p>
<p>If the signature matches, then your application knows that the incoming JWT can be trusted.</p>
<p>Another popular signing algorithm is RS256, which uses public and private key pairs to validate signatures. This is similar to the system used for SSH and SSL.</p>
<p>If you'd like to read more about how RS256 works, check out this article:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.freecodecamp.org/news/understanding-encryption-algorithms/#rsa">https://www.freecodecamp.org/news/understanding-encryption-algorithms/#rsa</a></div>
<h2 id="heading-other-helpful-tutorials">Other Helpful Tutorials</h2>
<p>If you'd like to learn more about JWTs and how to use them in applications, check out these tutorials:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.freecodecamp.org/news/what-are-json-web-tokens-jwt-auth-tutorial/">https://www.freecodecamp.org/news/what-are-json-web-tokens-jwt-auth-tutorial/</a></div>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.freecodecamp.org/news/learn-to-implement-user-authentication-in-node-apps-using-passport-js/">https://www.freecodecamp.org/news/learn-to-implement-user-authentication-in-node-apps-using-passport-js/</a></div>
<h2 id="heading-thanks-for-reading">Thanks for Reading</h2>
<p>If you found this article on JWTs helpful, consider sharing it so more people can benefit from it.</p>
<p>Also, feel free to reach out on <a target="_blank" href="https://twitter.com/kriskoishigawa">Twitter</a> and let me know what you think.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Add JWT Authentication in FastAPI – A Practical Guide ]]>
                </title>
                <description>
                    <![CDATA[ By Abdullah Adeel FastAPI is a modern, fast, battle tested and light-weight web development framework written in Python. Other popular options in the space are Django, Flask and Bottle. And since it's new, FastAPI comes with both advantages and disad... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-jwt-authentication-in-fastapi/</link>
                <guid isPermaLink="false">66d45d59246e57ac83a2c6f7</guid>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ FastAPI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JWT ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 07 Jun 2022 23:28:25 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/06/fcc-fastapi-jwt-auth.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Abdullah Adeel</p>
<p><a target="_blank" href="https://fastapi.tiangolo.com/">FastAPI</a> is a modern, fast, battle tested and light-weight web development framework written in Python. Other popular options in the space are <a target="_blank" href="https://www.djangoproject.com/">Django</a>, <a target="_blank" href="https://flask.palletsprojects.com/en/2.1.x/">Flask</a> and <a target="_blank" href="https://bottlepy.org/docs/dev/">Bottle</a>.</p>
<p>And since it's new, FastAPI comes with both advantages and disadvantages.</p>
<p>On the positive side, FastAPI implements all the modern standards, taking full advantage of the features supported by the latest Python versions. It has async support and type hinting. And it's also fast (hence the name FastAPI), unopinionated, robust, and easy to use.</p>
<p>On the negative side, FastAPI lacks some complex features like out of the box user management and admin panel that come baked in with Django. The community support for FastAPI is good but not as great as other frameworks that have been out there for years and have hundreds if not thousands of open-source projects for different use cases.</p>
<p>That was a very brief introduction to FastAPI. In this article, you'll learn how to implement JWT (JSON Web Token) authentication in FastAPI with a practical example.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>In this example, I am going to use <a target="_blank" href="https://replit.com"><strong>replit</strong></a> (a great web-based IDE). Alternatively, you can simply setup your FastAPI project locally by <a target="_blank" href="https://fastapi.tiangolo.com/tutorial/">following the docs</a> or use this <a target="_blank" href="https://replit.com/@abdadeel/FastAPIstarter">replit starter template</a> by forking it. This template has all the required dependencies already installed.</p>
<p>If you have the project setup on your local environment, here are the dependencies that you need to install for JWT authentication (assuming that you have a FastAPI project running):</p>
<pre><code class="lang-shell">pip install "python-jose[cryptography]" "passlib[bcrypt]" python-multipart
</code></pre>
<p><strong>NOTE:</strong> In order to store users, I am going to use replit's built-in database. But you can apply similar operations if you are using any standard database like PostgreSQL, MongoDB, and so on. </p>
<p>If you want to see the complete implementation, I have <a target="_blank" href="https://www.youtube.com/watch?v=G8MsHbCzyZ4&amp;">this full video tutorial</a> that includes everything a production ready FastAPI application might have.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://replit.com/@abdadeel/FastAPIwithJWTauth">https://replit.com/@abdadeel/FastAPIwithJWTauth</a></div>
<h2 id="heading-authentication-with-fastapi">Authentication with FastAPI</h2>
<p>Authentication in general can have a lot of moving parts, from handling password hashing and assigning tokens to validating tokens on each request. </p>
<p>FastAPI leverages <a target="_blank" href="https://en.wikipedia.org/wiki/Dependency_injection#:~:text=In%20software%20engineering%2C%20dependency%20injection,leading%20to%20loosely%20coupled%20programs.">dependency injection</a> (a software engineering design pattern) to handle authentication schemes. Here is the list of some general steps in the process:</p>
<ul>
<li>Password hashing</li>
<li>Creating and assigning JWT tokens</li>
<li>User creation</li>
<li>Validating tokens on each request to ensure authentication</li>
</ul>
<h2 id="heading-password-hashing">Password Hashing</h2>
<p>When creating a user with a username and password, you need to hash passwords before storing them in the database. Let's see how to easily hash passwords.</p>
<p>Create a file named <code>utils.py</code> in the <code>app</code> directory and add the following function to hash user passwords.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> passlib.context <span class="hljs-keyword">import</span> CryptContext

password_context = CryptContext(schemes=[<span class="hljs-string">"bcrypt"</span>], deprecated=<span class="hljs-string">"auto"</span>)


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_hashed_password</span>(<span class="hljs-params">password: str</span>) -&gt; str:</span>
    <span class="hljs-keyword">return</span> password_context.hash(password)


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">verify_password</span>(<span class="hljs-params">password: str, hashed_pass: str</span>) -&gt; bool:</span>
    <span class="hljs-keyword">return</span> password_context.verify(password, hashed_pass)
</code></pre>
<p>We're using <code>passlib</code> to create the configuration context for password hashing. Here we are configuring it to use <code>bcrypt</code> . </p>
<p>The <code>get_hashed_password</code> function takes a plain password and returns the hash for it that can be safely stored in the database. The <code>verify_password</code> function takes the plain and hashed passwords and return a boolean representing whether the passwords match or not.</p>
<h2 id="heading-how-to-generate-jwt-tokens">How to Generate JWT Tokens</h2>
<p>In this section, we will write two helper functions to generate access and refresh tokens with a particular payload. Later we can use these functions to generate tokens for a particular user by passing the user-related payload.</p>
<p>Inside the <code>app/utils.py</code> file that you created earlier, add the following import statements:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime, timedelta
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Union, Any
<span class="hljs-keyword">from</span> jose <span class="hljs-keyword">import</span> jwt
</code></pre>
<p>Add the following constants that will be passed when creating JWTs:</p>
<pre><code class="lang-python">ACCESS_TOKEN_EXPIRE_MINUTES = <span class="hljs-number">30</span>  <span class="hljs-comment"># 30 minutes</span>
REFRESH_TOKEN_EXPIRE_MINUTES = <span class="hljs-number">60</span> * <span class="hljs-number">24</span> * <span class="hljs-number">7</span> <span class="hljs-comment"># 7 days</span>
ALGORITHM = <span class="hljs-string">"HS256"</span>
JWT_SECRET_KEY = os.environ[<span class="hljs-string">'JWT_SECRET_KEY'</span>]   <span class="hljs-comment"># should be kept secret</span>
JWT_REFRESH_SECRET_KEY = os.environ[<span class="hljs-string">'JWT_REFRESH_SECRET_KEY'</span>]    <span class="hljs-comment"># should be kept secret</span>
</code></pre>
<p><code>JWT_SECRET_KEY</code> and <code>JWT_REFRESH_SECRET_KEY</code> can be any strings, but make sure to keep them secret and set them as environment variables. </p>
<p>If you are following along on replit.com, you can set these environment variables from the <code>Secrets</code> tab on the left menu bar.</p>
<p>Add the following functions at the end of the <code>app/utils.py</code> file:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_access_token</span>(<span class="hljs-params">subject: Union[str, Any], expires_delta: int = None</span>) -&gt; str:</span>
    <span class="hljs-keyword">if</span> expires_delta <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        expires_delta = datetime.utcnow() + expires_delta
    <span class="hljs-keyword">else</span>:
        expires_delta = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)

    to_encode = {<span class="hljs-string">"exp"</span>: expires_delta, <span class="hljs-string">"sub"</span>: str(subject)}
    encoded_jwt = jwt.encode(to_encode, JWT_SECRET_KEY, ALGORITHM)
    <span class="hljs-keyword">return</span> encoded_jwt

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_refresh_token</span>(<span class="hljs-params">subject: Union[str, Any], expires_delta: int = None</span>) -&gt; str:</span>
    <span class="hljs-keyword">if</span> expires_delta <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        expires_delta = datetime.utcnow() + expires_delta
    <span class="hljs-keyword">else</span>:
        expires_delta = datetime.utcnow() + timedelta(minutes=REFRESH_TOKEN_EXPIRE_MINUTES)

    to_encode = {<span class="hljs-string">"exp"</span>: expires_delta, <span class="hljs-string">"sub"</span>: str(subject)}
    encoded_jwt = jwt.encode(to_encode, JWT_REFRESH_SECRET_KEY, ALGORITHM)
    <span class="hljs-keyword">return</span> encoded_jwt
</code></pre>
<p>The only difference between these two functions is that the expiration time for refresh tokens is longer than for access tokens.</p>
<p>The functions simply take the payload to include inside the JWT, which can be anything. Usually you would want to store information like USER_ID here, but this can be anything from strings to objects/dictionaries. The functions return tokens as strings.</p>
<p>In the end your <code>app/utils.py</code> file should look something like this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> passlib.context <span class="hljs-keyword">import</span> CryptContext
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime, timedelta
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Union, Any
<span class="hljs-keyword">from</span> jose <span class="hljs-keyword">import</span> jwt

ACCESS_TOKEN_EXPIRE_MINUTES = <span class="hljs-number">30</span>  <span class="hljs-comment"># 30 minutes</span>
REFRESH_TOKEN_EXPIRE_MINUTES = <span class="hljs-number">60</span> * <span class="hljs-number">24</span> * <span class="hljs-number">7</span> <span class="hljs-comment"># 7 days</span>
ALGORITHM = <span class="hljs-string">"HS256"</span>
JWT_SECRET_KEY = os.environ[<span class="hljs-string">'JWT_SECRET_KEY'</span>]     <span class="hljs-comment"># should be kept secret</span>
JWT_REFRESH_SECRET_KEY = os.environ[<span class="hljs-string">'JWT_REFRESH_SECRET_KEY'</span>]      <span class="hljs-comment"># should be kept secret</span>

password_context = CryptContext(schemes=[<span class="hljs-string">"bcrypt"</span>], deprecated=<span class="hljs-string">"auto"</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_hashed_password</span>(<span class="hljs-params">password: str</span>) -&gt; str:</span>
    <span class="hljs-keyword">return</span> password_context.hash(password)


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">verify_password</span>(<span class="hljs-params">password: str, hashed_pass: str</span>) -&gt; bool:</span>
    <span class="hljs-keyword">return</span> password_context.verify(password, hashed_pass)


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_access_token</span>(<span class="hljs-params">subject: Union[str, Any], expires_delta: int = None</span>) -&gt; str:</span>
    <span class="hljs-keyword">if</span> expires_delta <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        expires_delta = datetime.utcnow() + expires_delta
    <span class="hljs-keyword">else</span>:
        expires_delta = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)

    to_encode = {<span class="hljs-string">"exp"</span>: expires_delta, <span class="hljs-string">"sub"</span>: str(subject)}
    encoded_jwt = jwt.encode(to_encode, JWT_SECRET_KEY, ALGORITHM)
    <span class="hljs-keyword">return</span> encoded_jwt

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_refresh_token</span>(<span class="hljs-params">subject: Union[str, Any], expires_delta: int = None</span>) -&gt; str:</span>
    <span class="hljs-keyword">if</span> expires_delta <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        expires_delta = datetime.utcnow() + expires_delta
    <span class="hljs-keyword">else</span>:
        expires_delta = datetime.utcnow() + timedelta(minutes=REFRESH_TOKEN_EXPIRE_MINUTES)

    to_encode = {<span class="hljs-string">"exp"</span>: expires_delta, <span class="hljs-string">"sub"</span>: str(subject)}
    encoded_jwt = jwt.encode(to_encode, JWT_REFRESH_SECRET_KEY, ALGORITHM)
    <span class="hljs-keyword">return</span> encoded_jwt
</code></pre>
<h2 id="heading-how-to-handle-user-signups">How to Handle User Signups</h2>
<p>Inside the <code>app/app.py</code> file, create another endpoint for handling user signups. The endpoint should take the username/email and password as data. It then checks to make sure another account with the email/username does not exist. Then it creates the user and saves it to the database.</p>
<p>In <code>app/app.py</code>, add the following handler function:</p>
<pre><code><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, status, HTTPException
<span class="hljs-keyword">from</span> fastapi.responses <span class="hljs-keyword">import</span> RedirectResponse
<span class="hljs-keyword">from</span> app.schemas <span class="hljs-keyword">import</span> UserOut, UserAuth
<span class="hljs-keyword">from</span> replit <span class="hljs-keyword">import</span> db
<span class="hljs-keyword">from</span> app.utils <span class="hljs-keyword">import</span> get_hashed_password
<span class="hljs-keyword">from</span> uuid <span class="hljs-keyword">import</span> uuid4

@app.post(<span class="hljs-string">'/signup'</span>, summary=<span class="hljs-string">"Create new user"</span>, response_model=UserOut)
<span class="hljs-keyword">async</span> def create_user(data: UserAuth):
    # querying database to check <span class="hljs-keyword">if</span> user already exist
    user = db.get(data.email, None)
    <span class="hljs-keyword">if</span> user is not None:
            raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=<span class="hljs-string">"User with this email already exist"</span>
        )
    user = {
        <span class="hljs-string">'email'</span>: data.email,
        <span class="hljs-string">'password'</span>: get_hashed_password(data.password),
        <span class="hljs-string">'id'</span>: str(uuid4())
    }
    db[data.email] = user    # saving user to database
    <span class="hljs-keyword">return</span> user
</code></pre><h2 id="heading-how-to-handle-logins">How to Handle Logins</h2>
<p>FastAPI has a standard way of handling logins to comply with OpenAPI standards. This automatically adds authentication in the swagger docs without any extra configurations.</p>
<p>Add the following handler function for user logins and assign each user access and refresh tokens. Don't forget to include imports.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, status, HTTPException, Depends
<span class="hljs-keyword">from</span> fastapi.security <span class="hljs-keyword">import</span> OAuth2PasswordRequestForm
<span class="hljs-keyword">from</span> fastapi.responses <span class="hljs-keyword">import</span> RedirectResponse
<span class="hljs-keyword">from</span> app.schemas <span class="hljs-keyword">import</span> UserOut, UserAuth, TokenSchema
<span class="hljs-keyword">from</span> replit <span class="hljs-keyword">import</span> db
<span class="hljs-keyword">from</span> app.utils <span class="hljs-keyword">import</span> (
    get_hashed_password,
    create_access_token,
    create_refresh_token,
    verify_password
)
<span class="hljs-keyword">from</span> uuid <span class="hljs-keyword">import</span> uuid4

<span class="hljs-meta">@app.post('/login', summary="Create access and refresh tokens for user", response_model=TokenSchema)</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">login</span>(<span class="hljs-params">form_data: OAuth2PasswordRequestForm = Depends(<span class="hljs-params"></span>)</span>):</span>
    user = db.get(form_data.username, <span class="hljs-literal">None</span>)
    <span class="hljs-keyword">if</span> user <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:
        <span class="hljs-keyword">raise</span> HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=<span class="hljs-string">"Incorrect email or password"</span>
        )

    hashed_pass = user[<span class="hljs-string">'password'</span>]
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> verify_password(form_data.password, hashed_pass):
        <span class="hljs-keyword">raise</span> HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=<span class="hljs-string">"Incorrect email or password"</span>
        )

    <span class="hljs-keyword">return</span> {
        <span class="hljs-string">"access_token"</span>: create_access_token(user[<span class="hljs-string">'email'</span>]),
        <span class="hljs-string">"refresh_token"</span>: create_refresh_token(user[<span class="hljs-string">'email'</span>]),
    }
</code></pre>
<p>This endpoint is a bit different from the other post endpoints where you defined the schema for filtering incoming data. </p>
<p>For login endpoints, we use <code>OAuth2PasswordRequestForm</code> as a dependency. This will make sure to extract data from the request and pass is as a <code>form_data</code> argument to the the <code>login</code> handler function. <code>python-multipart</code> is used to extract form data. So make sure that you have installed it.</p>
<p>The endpoint will reflect in the swagger docs with inputs for username and password. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/image-49.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>On successful response, you will get tokens as shown here:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/image-50.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-add-protected-routes">How to Add Protected Routes</h2>
<p>Now since we have added support for login and signup, we can add protected endpoints. In FastAPI, protected endpoints are handled using dependency injection and FastAPI can infer this from the OpenAPI schema and reflect it in the swagger docs. </p>
<p>Let's see the power of dependency injection. At this point, there is no way we can authenticate from the docs. This is because currently we don't have any protected endpoint, so the OpenAPI schema does not have enough information about the login strategy we are using.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/image-51.png" alt="Image" width="600" height="400" loading="lazy">
<em>No button in swagger docs to login.</em></p>
<p>Let's create our custom dependency. It's nothing but a function that is run before the actual handler function to get arguments passed to the hander function. Let's see with a practical example.</p>
<p>Create another file <code>app/deps.py</code>  and add include the following function in it:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Union, Any
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> Depends, HTTPException, status
<span class="hljs-keyword">from</span> fastapi.security <span class="hljs-keyword">import</span> OAuth2PasswordBearer
<span class="hljs-keyword">from</span> .utils <span class="hljs-keyword">import</span> (
    ALGORITHM,
    JWT_SECRET_KEY
)

<span class="hljs-keyword">from</span> jose <span class="hljs-keyword">import</span> jwt
<span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> ValidationError
<span class="hljs-keyword">from</span> app.schemas <span class="hljs-keyword">import</span> TokenPayload, SystemUser
<span class="hljs-keyword">from</span> replit <span class="hljs-keyword">import</span> db

reuseable_oauth = OAuth2PasswordBearer(
    tokenUrl=<span class="hljs-string">"/login"</span>,
    scheme_name=<span class="hljs-string">"JWT"</span>
)


<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_current_user</span>(<span class="hljs-params">token: str = Depends(<span class="hljs-params">reuseable_oauth</span>)</span>) -&gt; SystemUser:</span>
    <span class="hljs-keyword">try</span>:
        payload = jwt.decode(
            token, JWT_SECRET_KEY, algorithms=[ALGORITHM]
        )
        token_data = TokenPayload(**payload)

        <span class="hljs-keyword">if</span> datetime.fromtimestamp(token_data.exp) &lt; datetime.now():
            <span class="hljs-keyword">raise</span> HTTPException(
                status_code = status.HTTP_401_UNAUTHORIZED,
                detail=<span class="hljs-string">"Token expired"</span>,
                headers={<span class="hljs-string">"WWW-Authenticate"</span>: <span class="hljs-string">"Bearer"</span>},
            )
    <span class="hljs-keyword">except</span>(jwt.JWTError, ValidationError):
        <span class="hljs-keyword">raise</span> HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail=<span class="hljs-string">"Could not validate credentials"</span>,
            headers={<span class="hljs-string">"WWW-Authenticate"</span>: <span class="hljs-string">"Bearer"</span>},
        )

    user: Union[dict[str, Any], <span class="hljs-literal">None</span>] = db.get(token_data.sub, <span class="hljs-literal">None</span>)


    <span class="hljs-keyword">if</span> user <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:
        <span class="hljs-keyword">raise</span> HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=<span class="hljs-string">"Could not find user"</span>,
        )

    <span class="hljs-keyword">return</span> SystemUser(**user)
</code></pre>
<p>Here we are defining the <code>get_current_user</code> function as a dependency which in turn takes an instance of <code>OAuth2PasswordBearer</code> as a dependency.</p>
<pre><code class="lang-python">reuseable_oauth = OAuth2PasswordBearer(
    tokenUrl=<span class="hljs-string">"/login"</span>,
    scheme_name=<span class="hljs-string">"JWT"</span>
)
</code></pre>
<p><code>OAuth2PasswordBearer</code> takes two required parameters. <code>tokenUrl</code> is the URL in your application that handles user login and return tokens. <code>scheme_name</code> set to <code>JWT</code> will allow the frontend swagger docs to call <code>tokenUrl</code> from the frontend and save tokens in memory. Then each subsequent request to the protected endpoints will have the token sent as <code>Authorization</code> headers so <code>OAuth2PasswordBearer</code> can parse it.</p>
<p>Now let's add a protected endpoint that returns user account information as the response. For this, a user has to be logged in and the endpoint will respond with information for the currently logged-in user.</p>
<p>In <code>app/app.py</code> create another handler function. Make sure to include imports as well.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> app.deps <span class="hljs-keyword">import</span> get_current_user

<span class="hljs-meta">@app.get('/me', summary='Get details of currently logged in user', response_model=UserOut)</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_me</span>(<span class="hljs-params">user: User = Depends(<span class="hljs-params">get_current_user</span>)</span>):</span>
    <span class="hljs-keyword">return</span> user
</code></pre>
<p>As soon as you add this endpoint, you will be able to see the <code>Authorize</code> button in the swagger docs and a 🔒 icon in front of the protected endpoint <code>/me</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/image-56.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This is power of dependency injection and FastAPI's ability to generate an automatic OpenAPI schema. </p>
<p>Clicking the <code>Authorize</code> button will open the authorization form with the required fields for login. On a successful response, tokens will be saved and sent to subsequent request in the headers.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/image-57.png" alt="Image" width="600" height="400" loading="lazy">
<em>Swagger integrated login form</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/image-58.png" alt="Image" width="600" height="400" loading="lazy">
<em>successfully logged in</em></p>
<p>At this point, you can access all the protected endpoints. To make an endpoint protected, you just need to add the <code>get_current_user</code> function as a dependency. That's all you need to do!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>If you followed along, you should have a working FastAPI application with JWT authentication. If not, you can always run <a target="_blank" href="https://replit.com/@abdadeel/FastAPI-with-JWT-authentication">this repl</a> and play around with it or visit <a target="_blank" href="https://fastapi-with-jwt-authentication.abdadeel.repl.co/docs">this deployed version</a>. You can find the GitHub code for this project <a target="_blank" href="https://github.com/mabdullahadeel/fcc-fastapi-jwt">here</a>.</p>
<p>If you found this article helpful, give me a follow at <a target="_blank" href="https://twitter.com/abdadeel_">twitter</a> <a target="_blank" href="https://twitter.com/abdadeel_">@abdadeel_</a>. And don't forget that you can always watch <a target="_blank" href="https://www.youtube.com/watch?v=G8MsHbCzyZ4&amp;ab_channel=ABDLogs">this video</a> for detail explanation with a practical example.</p>
<p>Thanks ;)</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up Java Spring Boot JWT Authorization and Authentication ]]>
                </title>
                <description>
                    <![CDATA[ By Yiğit Kemal Erinç In the past month, I had a chance to implement JWT auth for a side project. I have previously worked with JWT in Ruby on Rails, but this was my first time in Spring.  In this post, I will try to explain what I have ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-setup-jwt-authorization-and-authentication-in-spring/</link>
                <guid isPermaLink="false">66d45e44182810487e0ce155</guid>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authorization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JSON Web Tokens ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JWT ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 12 Aug 2020 20:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/08/jwt.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Yiğit Kemal Erinç</p>
<p>In the past month, I had a chance to implement JWT auth for a side project. I have previously worked with JWT in Ruby on Rails, but this was my first time in Spring. </p>
<p>In this post, I will try to explain what I have learned and applied in my project to share my experience and hopefully help some people. </p>
<p>We will start by taking a quick look at the theory behind JWT and how it works. Then we will look at how to implement it in a Spring Boot application.</p>
<h2 id="heading-jwt-basics">JWT Basics</h2>
<p>JWT, or JSON Web Tokens (<a target="_blank" href="https://tools.ietf.org/html/rfc7519">RFC 7519</a>), is a standard that is mostly used for securing REST APIs. Despite being a relatively new technology, it is gaining rapid popularity.</p>
<p>In the JWT auth process, the front end (client) firstly sends some credentials to authenticate itself (username and password in our case, since we're working on a web application). </p>
<p>The server (the Spring app in our case) then checks those credentials, and if they are valid, it generates a JWT and returns it. </p>
<p>After this step client has to provide this token in the request’s <strong>Authorization</strong> header in the “Bearer TOKEN” form. The back end will check the validity of this token and authorize or reject requests. The token may also store user roles and authorize the requests based on the given authorities.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/1.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-implementation">Implementation</h2>
<p>Now let’s see how we can implement the JWT login and save mechanism in a real Spring application.</p>
<h3 id="heading-dependencies">Dependencies</h3>
<p>You can see the list of Maven dependencies that our example code uses below. Note that the core dependencies like Spring Boot and Hibernate are not included in this screenshot.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/2-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-saving-users">Saving Users</h3>
<p>We will start by creating controllers to save users securely and authenticate them based on username and password.</p>
<p>We have a model entity called User. It is a simple entity class that maps to the <strong>USER</strong> table. You can use whatever properties you need depending on your application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/3-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We also have a simple <strong>UserRepository</strong> class to save users. We need to override the <strong>findByUsername</strong> method since we will use it in authentication.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">UserRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">JpaRepository</span>&lt;<span class="hljs-title">User</span>, <span class="hljs-title">String</span>&gt;</span>{ 
    <span class="hljs-function">User <span class="hljs-title">findByUsername</span><span class="hljs-params">(String username)</span></span>; 
}
</code></pre>
<p>We should never store plaintext passwords in the database because many users tend to use the same password for multiple sites. </p>
<p>There are many different hashing algorithms, but the most commonly used one is <strong>BCrypt</strong> and it is a recommended method of secure hashing. You can check out <a target="_blank" href="https://security.blogoverflow.com/2013/09/about-secure-password-hashing/#:~:text=Passwords%20should%20be%20hashed%20with,providing%20most%20security%20is%20bcrypt.">this</a> article for more information on the topic.</p>
<p>To hash the password, we will define a <strong>BCrypt</strong> bean in <strong>@SpringBootApplication</strong> and annotate the main class as follows:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Bean</span> <span class="hljs-function"><span class="hljs-keyword">public</span> BCryptPasswordEncoder <span class="hljs-title">bCryptPasswordEncoder</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> BCryptPasswordEncoder(); 
}
</code></pre>
<p>We will call the methods on this bean when we need to hash a password.</p>
<p>We also need a UserController to save users. We create the controller, annotate it with <strong>@RestController,</strong> and define the corresponding mapping. </p>
<p>In our application, we save the user based on a DTO object that is passed from the front end. You can also pass a User object in <strong>@RequestBody</strong>.</p>
<p>After we pass the DTO object, we encrypt the password field using the <strong>BCrypt</strong> bean we created earlier. You could also do this in the controller, but it is a better practice to put this logic in the service class.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Transactional(rollbackFor = Exception.class)</span> 
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">saveDto</span><span class="hljs-params">(UserDto userDto)</span> </span>{ 
    userDto.setPassword(bCryptPasswordEncoder
           .encode(userDto.getPassword())); 
    <span class="hljs-keyword">return</span> save(<span class="hljs-keyword">new</span> User(userDto)).getId(); 
}
</code></pre>
<h3 id="heading-authentication-filter">Authentication Filter</h3>
<p>We need authentication to make sure that the user is really who they claim to be. We will be using the classic username/password pair to accomplish this.</p>
<p>Here are the steps to implement authentication:</p>
<ol>
<li>Create our Authentication Filter that extends <strong>UsernamePasswordAuthenticationFilter</strong></li>
<li>Create a security configuration class that extends <strong>WebSecurityConfigurerAdapter</strong> and apply the filter</li>
</ol>
<p>Here is the code for our Authentication Filter – as you might know, filters are the backbone of Spring Security.</p>


<p>Let’s go over this code step by step.</p>
<p>This class extends <strong>UsernamePasswordAuthenticationFilter</strong> which is the default class for password authentication in Spring Security. We extend it to define our custom authentication logic.</p>
<p>We make a call to the <strong>setFilterProcessesUrl</strong> method in our constructor. This method sets the default login URL to the provided parameter. </p>
<p>If you remove this line, Spring Security creates the <strong>“/login”</strong> endpoint by default. It defines the login endpoint for us, which is why we will not define a login endpoint in our controller explicitly. </p>
<p>After this line our login endpoint will be <strong>/api/services/controller/user/login</strong>. You can use this function to stay consistent with your endpoints.</p>
<p>We override the <strong>attemptAuthentication</strong> and <strong>successfulAuthentication</strong> methods of the <strong>UsernameAuthenticationFilter</strong> class.</p>
<p>The <strong>attemptAuthentication</strong> function runs when the user tries to log in to our application. It reads the credentials, creates a user POJO from them, and then checks the credentials to authenticate. </p>
<p>We pass the username, password, and an empty list. The empty list represents the authorities (roles), and we leave it as is since we do not have any roles in our application yet.</p>
<p>If the authentication is successful, the <strong>successfulAuthentication</strong> method runs. The parameters of this method are passed by Spring Security behind the scenes. </p>
<p>The <strong>attemptAuthentication</strong> method returns an <strong>Authentication</strong> object that contains the authorities we passed while attempting. </p>
<p>We want to return a token to user after authentication is successful, so we create the token using username, secret, and expiration date. We need to define the <strong>SECRET</strong> and <strong>EXPIRATION_DATE</strong> now.</p>


<p>We create a class to be a container for our constants. You can set the secret to whatever you want, but the best practice is making the secret key as long as your hash. We use the <strong>HS256</strong> algorithm in this example, so our secret key is 256 bits/32 chars.</p>
<p>The expiration time is set to 15 minutes, because it is the best practice against secret key brute-forcing attacks. The time is in milliseconds.</p>
<p>We have prepared our Authentication filter, but it is not active yet. We also need an Authorization filter, and then we will apply them both through a configuration class. </p>
<p>This filter will check the existence and validity of the access token on the Authorization header. We will specify which endpoints will be subject to this filter in our configuration class.</p>
<h3 id="heading-authorization-filter">Authorization Filter</h3>


<p>The <strong>doFilterInternal</strong> method intercepts the requests then checks the Authorization header. If the header is not present or doesn’t start with “BEARER”, it proceeds to the filter chain. </p>
<p>If the header is present, the <strong>getAuthentication</strong> method is invoked. <strong>getAuthentication</strong> verifies the JWT, and if the token is valid, it returns an access token which Spring will use internally. </p>
<p>This new token is then saved to SecurityContext. You can also pass in Authorities to this token if you need for role-based authorization.</p>
<p>Our filters are ready, and now we need to put them into action with the help of a configuration class.</p>
<h3 id="heading-configuration">Configuration</h3>


<p>We annotate this class with <strong>@EnableWebSecurity</strong> and extend <strong>WebSecurityConfigureAdapter</strong> to implement our custom security logic. </p>
<p>We autowire the BCrypt bean that we defined earlier. We also autowire the <strong>UserDetailsService</strong> to find the user’s account. </p>
<p>The most important method is the one which accepts an <strong>HttpSecurity</strong> object. Here we specify the secure endpoints and filters that we want to apply. We configure CORS, and then we permit all post requests to our sign up URL that we defined in the constants class. </p>
<p>You can add other ant matchers to filter based on URL patterns and roles, and you can <a target="_blank" href="https://stackoverflow.com/questions/44067650/spring-security-role-based-access">check</a> this StackOverflow question for examples regarding that. The other method configures the <strong>AuthenticationManager</strong> to use our encoder object as its password encoder while checking the credentials.</p>
<h3 id="heading-testing">Testing</h3>
<p>Let’s send a few requests to test if it works properly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/4.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here we send a GET request to access a protected resource. Our server responds with a 403 code. This is the expected behavior because we haven’t provided a token in the header. Now let’s create a user:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/5.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>To create a user, we send a post request with our User DTO data. We will use this user to login and get an access token.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/6.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Great! We got the token. After this point, we will use this token to access protected resources.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/7.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We provide the token in the Authorization header and we are now allowed access to our protected endpoint.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial I have walked you through the steps I took when implementing JWT authorization and password authentication in Spring. We also learned how to save a user securely. </p>
<p>Thank you for reading – I hope it was helpful to you. If you are interested in reading more content like this, feel free to subscribe to my blog at <a target="_blank" href="https://erinc.io">https://erinc.io</a>. :)</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
