Authentication Best Practices: Building a Robust Authentication System
Published: 2024-02-05 07:16:37

Adding authentication to an application is one of the most challenging but also a very important part for developers. Today, I will teach you how to create an authentication page in just 10 minutes.

First, let's initialize npm and install all the necessary packages that we are going to use. Open your terminal and run the following commands:

```bash
npm init -y
npm i express bcryptjs body-parser dotenv ejs jsonwebtoken mongoose cookie-parser
```

Next, create two directories named "views" and "public". Inside the "views" directory, create three files: "signin.ejs", "signup.ejs", and "home.ejs". Your folder structure should look like this:

```
- views
  - signin.ejs
  - signup.ejs
  - home.ejs
- public
- server.js
```

Now, let's include the necessary packages and configure our express server in the "server.js" file:

```javascript
const express = require('express');
const bodyparser = require("body-parser");
const mongoose = require('mongoose');
const jwt = require('jsonwebtoken');
const cookieParser = require('cookie-parser');
const port = process.env.PORT || 3000;
const app = express();
require('dotenv').config();
const bcrypt = require('bcryptjs');
const salt = 10;

app.set('view engine', 'ejs');
app.use(bodyparser.urlencoded({ extended: true }));
app.use(express.json());
app.use(cookieParser());
app.use(express.static("public"));

app.listen(port, () => {
  console.log(`Running on port ${port}`);
});
```

Next, let's create our user schema for authentication and implement the signup functionality:

```javascript
const userSchema = new mongoose.Schema({
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true }
}, { collection: 'users' });

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

app.post('/signup', async (req, res) => {
  const { email, password: plainTextPassword } = req.body;
  const password = await bcrypt.hash(plainTextPassword, salt);
  
  try {
    const response = await User.create({
      email,
      password
    });
    
    return res.redirect('/');
  } catch (error) {
    console.log(JSON.stringify(error));
    
    if (error.code === 11000) {
      return res.send({ status: 'error', error: 'email already exists' });
    }
    
    throw error;
  }
});
```

Now, let's implement the login functionality using JWT to create an authentication token:

```javascript
const verifyUserLogin = async (email, password) => {
  try {
    const user = await User.findOne({ email }).lean();
    
    if (!user) {
      return { status: 'error', error: 'user not found' };
    }
    
    if (await bcrypt.compare(password, user.password)) {
      const token = jwt.sign({ id: user._id, username: user.email, type: 'user' }, process.env.JWT_SECRET, { expiresIn: '2h' });
      return { status: 'ok', data: token };
    }
    
    return { status: 'error', error: 'invalid password' };
  } catch (error) {
    console.log(error);
    return { status: 'error', error: 'timed out' };
  }
};

app.post('/login', async (req, res) => {
  const { email, password } = req.body;
  
  const response = await verifyUserLogin(email, password);
  
  if (response.status === 'ok') {
    res.cookie('token', response.data, { maxAge: 2 * 60 * 60 * 1000, httpOnly: true });
    res.redirect('/');
  } else {
    res.json(response);
  }
});
```

Finally, let's create a route for the protected page and check for authentication before accessing it:

```javascript
const verifyToken = (token) => {
  try {
    const verify = jwt.verify(token, process.env.JWT_SECRET);
    
    if (verify.type === 'user') {
      return true;
    } else {
      return false;
    }
  } catch (error) {
    console.log(JSON.stringify(error), "error");
    return false;
  }
};

app.get('/', (req, res) => {
  const { token } = req.cookies;
  
  if (verifyToken(token)) {
    return res.render('home');
  } else {
    res.redirect('/login');
  }
});

app.get('/login', (req, res) => {
  res.render('signin');
});

app.get('/signup', (req, res) => {
  res.render('signup');
});
```

That's it! You have successfully added authentication to your application. Now you can create a login and signup page, and protect your routes using JWT authentication.

Don't forget to create a .env file to store your secret key for JWT and MongoDB connection URL.

I hope this tutorial was helpful. Happy coding!

**Connect With Me**

I hope you found this guide helpful. If you have any questions, feedback, or just want to connect and discuss more about web development and security, feel free to reach out.

- **LinkedIn**: [Vartika Sharma](https://www.linkedin.com/in/vartika-sharma-436104230/)
- **Email**: `vrtikaaa1811@gmail.com`

Looking forward to connecting with fellow tech enthusiasts and professionals!