MERN Stack Application For User Registration And Sign In Using JWT Authentication

MERN Stack Application For User Registration And Sign In Using JWT Authentication

I'll help you create a basic MERN (MongoDB, Express.js, React.js, Node.js) stack app for user registration and sign-in. We'll set up a simple authentication system using JWT (JSON Web Tokens) on the backend.

Backend (Node.js/Express):

  1. Create a new directory for your backend:
mkdir mern-auth-backend
cd mern-auth-backend
npm init -y
npm install express mongoose cors bcrypt jsonwebtoken
  1. Create a file named server.js:
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');

const app = express();
const PORT = process.env.PORT || 5000;
const JWT_SECRET = 'your-secret-key'; // Change this to a long, random string in production

app.use(cors());
app.use(express.json());

mongoose.connect('mongodb://localhost:27017/mern-auth', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

const userSchema = new mongoose.Schema({
  username: String,
  password: String,
});

const User = mongoose.model('User', userSchema);

app.post('/api/register', async (req, res) => {
  try {
    const { username, password } = req.body;
    const hashedPassword = await bcrypt.hash(password, 10);
    const user = new User({ username, password: hashedPassword });
    await user.save();
    res.status(201).json({ message: 'User registered successfully' });
  } catch (error) {
    res.status(500).json({ error: 'Internal Server Error' });
  }
});

app.post('/api/login', async (req, res) => {
  try {
    const { username, password } = req.body;
    const user = await User.findOne({ username });

    if (!user) {
      return res.status(401).json({ error: 'Invalid credentials' });
    }

    const passwordMatch = await bcrypt.compare(password, user.password);

    if (!passwordMatch) {
      return res.status(401).json({ error: 'Invalid credentials' });
    }

    const token = jwt.sign({ username: user.username }, JWT_SECRET);
    res.json({ token });
  } catch (error) {
    res.status(500).json({ error: 'Internal Server Error' });
  }
});

app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

The backend code has user registration and login routes, using password hashing and JWT for authentication. Change 'your-secret-key' to a safe, random string.

Frontend (React):

  1. Create a new React app:
npx create-react-app mern-auth-client
cd mern-auth-client
npm install react-router-dom
  1. Update the src/App.js file:
import React, { useState, useEffect } from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';

const App = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [token, setToken] = useState('');

  const handleRegister = () => {
    fetch('/api/register', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ username, password }),
    })
      .then((res) => res.json())
      .then((data) => alert(data.message))
      .catch((error) => console.error('Error registering:', error));
  };

  const handleLogin = () => {
    fetch('/api/login', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ username, password }),
    })
      .then((res) => res.json())
      .then((data) => {
        if (data.token) {
          setToken(data.token);
          alert('Login successful');
        } else {
          alert('Invalid credentials');
        }
      })
      .catch((error) => console.error('Error logging in:', error));
  };

  const handleLogout = () => {
    setToken('');
  };

  useEffect(() => {
    // You can use the token for authenticated requests here
    // For simplicity, let's just log it to the console
    console.log('Token:', token);
  }, [token]);

  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/register">Register</Link>
            </li>
            <li>
              <Link to="/login">Login</Link>
            </li>
          </ul>
        </nav>

        <hr />

        <Route path="/" exact>
          <h2>Home</h2>
          {token ? (
            <button onClick={handleLogout}>Logout</button>
          ) : (
            <p>Please register or log in.</p>
          )}
        </Route>

        <Route path="/register">
          <h2>Register</h2>
          <input
            type="text"
            placeholder="Username"
            value={username}
            onChange={(e) => setUsername(e.target.value)}
          />
          <input
            type="password"
            placeholder="Password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
          />
          <button onClick={handleRegister}>Register</button>
        </Route>

        <Route path="/login">
          <h2>Login</h2>
          <input
            type="text"
            placeholder="Username"
            value={username}
            onChange={(e) => setUsername(e.target.value)}
          />
          <input
            type="password"
            placeholder="Password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
          />
          <button onClick={handleLogin}>Login</button>
        </Route>
      </div>
    </Router>
  );
};

export default App;

This React code has a basic navigation system using react-router-dom. It sets up routes for the home page, sign-up, and sign-in. The useEffect hook shows the token in the console as an example.

Running the App:

  1. Start the backend server:
cd mern-auth-backend
node server.js
  1. In a new terminal, start the React app:
cd mern-auth-client
npm start

Go to http://localhost:3000 in your browser, and you'll see a basic authentication app with registration, login, and home pages. The app uses JWT tokens for simple authentication.

Remember, this is just a basic example. In a real-world situation, you'd need more security features, error handling, user feedback, and safe token management (like securely storing tokens, dealing with token expiration, and refreshing tokens). Also, always use HTTPS in production for safe communication.

Did you find this article valuable?

Support LingarajTechhub All About Programming by becoming a sponsor. Any amount is appreciated!