jwt authentication

·

3 min read

Certainly! Let's build a fully functioning JWT authentication system in a Next.js application. This guide will provide a comprehensive overview of each step.

  1. Set Up Your Next.js Project: Create a new Next.js project or use an existing one.

  2. Install Dependencies: Install the required packages using npm or yarn:

     npm install jsonwebtoken axios js-cookie
    

    or

     yarn add jsonwebtoken axios js-cookie
    
  3. Create API Routes: In your pages/api directory, create API routes for handling authentication actions.

    • pages/api/login.js for handling user login:
    import jwt from 'jsonwebtoken';

    export default function handler(req, res) {
      if (req.method !== 'POST') {
        return res.status(405).end(); // Method Not Allowed
      }

      const { username, password } = req.body;

      // Perform user authentication here (check username and password)
      if (authenticated) {
        const token = jwt.sign({ username }, 'secret_key', { expiresIn: '1h' });
        res.status(200).json({ token });
      } else {
        res.status(401).json({ error: 'Authentication failed' });
      }
    }
  • pages/api/logout.js for handling user logout:
    export default function handler(req, res) {
      if (req.method !== 'POST') {
        return res.status(405).end(); // Method Not Allowed
      }

      // Clear token from cookies
      res.clearCookie('token').status(200).json({ message: 'Logout successful' });
    }
  1. Create Components:

    • components/Layout.js for consistent layout:
    import React from 'react';

    export default function Layout({ children }) {
      return (
        <div>
          <header>Header</header>
          {children}
          <footer>Footer</footer>
        </div>
      );
    }
  • components/LoginForm.js for the login form:
    import { useState } from 'react';
    import axios from 'axios';
    import Cookies from 'js-cookie';

    export default function LoginForm() {
      const [username, setUsername] = useState('');
      const [password, setPassword] = useState('');

      const handleLogin = async () => {
        try {
          const response = await axios.post('/api/login', { username, password });
          const token = response.data.token;
          Cookies.set('token', token);
          window.location.href = '/protected'; // Redirect to protected route
        } catch (error) {
          console.error('Login failed:', error);
        }
      };

      return (
        <div>
          <input type="text" value={username} onChange={(e) => setUsername(e.target.value)} />
          <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
          <button onClick={handleLogin}>Login</button>
        </div>
      );
    }
  1. Protected Route: Create a protected route using getServerSideProps to check if the user has a valid token before accessing the content.

    • pages/protected.js:
    import Layout from '../components/Layout';
    import jwt from 'jsonwebtoken';
    import Cookies from 'js-cookie';
    import { useRouter } from 'next/router';

    export default function ProtectedPage() {
      const router = useRouter();

      return (
        <Layout>
          <h1>Protected Content</h1>
          <button onClick={handleLogout}>Logout</button>
        </Layout>
      );
    }

    export async function getServerSideProps(context) {
      const token = Cookies.get('token');

      if (!token) {
        return {
          redirect: {
            destination: '/login',
            permanent: false,
          },
        };
      }

      try {
        jwt.verify(token, 'secret_key');
        return {
          props: {},
        };
      } catch (error) {
        return {
          redirect: {
            destination: '/login',
            permanent: false,
          },
        };
      }
    }
  1. Logout Functionality: Implement the logout functionality.

    In pages/protected.js:

     function ProtectedPage() {
       const router = useRouter();
    
       const handleLogout = async () => {
         try {
           await axios.post('/api/logout');
           Cookies.remove('token');
           router.push('/login');
         } catch (error) {
           console.error('Logout failed:', error);
         }
       }
    
       return (
         <Layout>
           <h1>Protected Content</h1>
           <button onClick={handleLogout}>Logout</button>
         </Layout>
       );
     }
    
  2. Final Steps:

    • Set up your CSS and styling according to your design.

    • Add links and navigation to your components as needed.

    • Make sure to handle errors and edge cases appropriately.

    • Consider token expiration and refresh logic for a production application.

    • Secure your JWT secret key and follow security best practices.

Remember that this example provides a basic JWT authentication system. In real-world applications, you should implement more advanced features such as token refresh, password hashing, error handling, and a more organized project structure.

Did you find this article valuable?

Support kumar by becoming a sponsor. Any amount is appreciated!