Handling Authentication and Authorization

Tutorial 3 of 5

Handling Authentication and Authorization: A Comprehensive Guide

1. Introduction

In this tutorial, our goal is to understand the concepts of Authentication and Authorization, and to implement them in a web application.

You will learn how to authenticate users, manage sessions, restrict access to certain parts of your application based on user roles, and handle user permissions.

Prerequisites:
- Basic knowledge of a server-side language (This tutorial uses Node.js)
- Familiarity with Express.js
- Understanding of HTTP and RESTful APIs.

2. Step-by-Step Guide

Authentication is the process of verifying who the user is, while Authorization is the process of verifying what they have access to.

We will create an Express application and use JWT (JSON Web Tokens) for authentication.

Best Practices and Tips

  1. Never store passwords in plain text. Always hash passwords.
  2. Use HTTPS to prevent password interception.
  3. Use a secure and trusted library for handling JWTs.

3. Code Examples

User Registration

To authenticate a user, we first need them to register. We'll use bcrypt to hash the password.

const express = require('express');
const bcrypt = require('bcrypt');
let users = [];

const app = express();
app.use(express.json());

app.post('/register', async (req, res) => {
    try {
        const hashedPassword = await bcrypt.hash(req.body.password, 10);
        const user = { name: req.body.name, password: hashedPassword };
        users.push(user);
        res.status(201).send();
    } catch {
        res.status(500).send();
    }
});

In this code, we're creating a new user with a hashed password and storing it in the users array.

User Login

Now, let's authenticate users during login and issue a JWT.

const jwt = require('jsonwebtoken');
let refreshTokens = [];

app.post('/login', async (req, res) => {
    const user = users.find(user => user.name == req.body.name)
    if (user == null) {
        return res.status(400).send('Cannot find user')
    }
    try {
        if(await bcrypt.compare(req.body.password, user.password)) {
            const accessToken = jwt.sign(user, process.env.ACCESS_TOKEN_SECRET);
            const refreshToken = jwt.sign(user, process.env.REFRESH_TOKEN_SECRET);
            refreshTokens.push(refreshToken);
            res.json({ accessToken: accessToken, refreshToken: refreshToken });
        } else {
            res.send('Not Allowed');
        }
    } catch {
        res.status(500).send();
    }
});

Here, if the user is found and the password matches, we're creating an access token and a refresh token using JWT and sending them to the client.

4. Summary

In this tutorial, we've learned how to handle user registration and login, hash passwords, generate and manage JWTs. For authorization, you can use the jsonwebtoken library's verify method to ensure only authenticated users can access certain routes.

Next steps include learning how to handle password resets, multi-factor authentication, and OAuth.

Some additional resources:
- jsonwebtoken GitHub
- bcrypt GitHub

5. Practice Exercises

  1. Implement a route for logging out that removes the user's refresh token.
  2. Add a middleware function that checks for a valid JWT before allowing access to a route.
  3. Implement role-based authorization. Add roles to users and restrict access to certain routes based on these roles.

Solutions:

  1. Logout Route:
app.delete('/logout', (req, res) => {
    refreshTokens = refreshTokens.filter(token => token !== req.body.token);
    res.sendStatus(204);
});
  1. JWT Middleware:
function authenticateToken(req, res, next) {
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1];

    if (token == null) return res.sendStatus(401);

    jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
        if (err) return res.sendStatus(403);
        req.user = user;
        next();
    });
}
  1. Role-Based Authorization: This is a more advanced topic. A basic solution would involve adding a role field to your users and checking that role in your protected routes.

Keep practicing and building different features to get a solid understanding of Authentication and Authorization.