Part 122: Securing User Authentication with JSON Web Tokens
[App] Authentication Overview

In our web application, we've taken a significant step forward in securing user authentication by using JSON Web Tokens (JWTs). JWTs provide a robust method for encoding user information, ensuring that any tampering attempts are easily detectable. In this blog post, we'll explore how to decode JWTs and utilize them to maintain user sessions in our application.
The Importance of JWTs
JWTs are a secure way to encode information between the client and the server. They consist of three parts:
Header: Specifies the algorithm used for signing the token.
Payload: Contains the claims, such as user information.
Signature: Validates the authenticity of the token, ensuring it hasn't been altered.
In our application, we encode user details as a JWT and set it as a cookie upon successful login. This token is signed with a server-side secret key, preventing unauthorized modifications.
Decoding JWTs in the NavBar
To display user information in the NavBar, we need to decode the JWT stored in the cookie. Here's how we can achieve that:
Step 1: Define a Function to Decode the JWT
First, we create a function called getUserFromSession to extract user details from the session token.
// File path: components/NavBar.jsx
mport { jwtVerify } from 'jose';
import { cookies } from 'next/headers';
import NavLink from './NavLink';
const JWT_SECRET = new TextEncoder().encode('some-random-string');
async function getUserFromSession() {
const sessionTokenCookie = cookies().get('sessionToken');
if (sessionTokenCookie) {
try {
const { payload } = await jwtVerify(sessionTokenCookie.value, JWT_SECRET);
return payload;
} catch (error) {
console.warn('Invalid JWT', error);
}
}
}Step 2: Update the NavBar Component
Next, we modify the NavBar component to use the getUserFromSession function. This allows us to determine whether the user is logged in based on the decoded JWT.
// File path: components/NavBar.jsx
export default async function NavBar() {
const user = await getUserFromSession();
return (
<nav>
<ul className="flex gap-2">
<li className="font-bold font-orbitron">
<NavLink href="/">
Indie Gamer
</NavLink>
</li>
<li className="ml-auto">
<NavLink href="/reviews">
Reviews
</NavLink>
</li>
<li>
<NavLink href="/about" prefetch={false}>
About
</NavLink>
</li>
{user ? (
<li>
{user.email}
</li>
) : (
<li>
<NavLink href="/sign-in">
Sign in
</NavLink>
</li>
)}
</ul>
</nav>
);
}Step 3: Handling Errors
If the JWT is invalid or has been tampered with, the jwtVerify function will throw an error. We handle this by wrapping the call in a try-catch block, logging a warning if verification fails.
Testing the Implementation
Logged-In User: When a user logs in, their email should appear in the NavBar.
No Cookie: If there's no session token, the NavBar should display the "Sign in" link.
Tampered Token: If the token is modified, an error is logged, and the user is treated as not authenticated.
Conclusion
By using JWTs, we enhance the security of our application, ensuring that user data stored in cookies cannot be manipulated by malicious users. This approach allows us to trust the data retrieved from cookies, as long as we verify the token using our server's secret key. This method secures user authentication, providing a reliable way to manage user sessions in a web application.
Last updated