Introduction to OAuth 2.0 and JWT Authorization in JavaScript
Modern web applications require a reliable authentication and authorization system. The two most popular standards — OAuth 2.0 (delegated access protocol) and JWT (JSON Web Tokens) — are often used together to create secure APIs. In this article, we will break down how to implement OAuth 2.0 and JWT authorization in JavaScript (Node.js) from scratch.
You will learn:
- What OAuth 2.0 is and why it is needed
- How JWT tokens work
- How to set up an authorization server on Express
- How to protect routes using middleware
OAuth 2.0 Basics: Flows and Roles
OAuth 2.0 defines four roles: Resource Owner (user), Client (application), Authorization Server (server issuing tokens), and Resource Server (server providing data). The most common flow is the Authorization Code Grant, which is used in web applications.
In this article, we will focus on implementing the Resource Server and Authorization Server using JWT, rather than external providers (Google, GitHub). This will give you full control over the process.
Installing Dependencies
To start, create a new Node.js project and install the necessary packages:
npm init -ynpm install express jsonwebtoken bcrypt dotenv corsPackage descriptions:
express— framework for creating a serverjsonwebtoken— creating and verifying JWTbcrypt— password hashingdotenv— working with environment variablescors— configuring CORS for the API
Implementing JWT Authorization in Node.js
JWT is a compact token consisting of three parts: header, payload, and signature. We will use it for user authentication after a successful login.
Setting Up the Server and User Model
Create a file server.js and define the basic structure:
require('dotenv').config();const express = require('express');const jwt = require('jsonwebtoken');const bcrypt = require('bcrypt');const cors = require('cors');
const app = express();app.use(express.json());app.use(cors());
const PORT = process.env.PORT || 3000;const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
// Temporary user storage (use a database in production)const users = [];Registration and Password Hashing
During registration, the password must be hashed using bcrypt:
app.post('/api/register', async (req, res) => { try { const { email, password } = req.body; // Check for existing user const existingUser = users.find(u => u.email === email); if (existingUser) { return res.status(400).json({ message: 'User already exists' }); }
// Hash the password const hashedPassword = await bcrypt.hash(password, 10); const newUser = { id: users.length + 1, email, password: hashedPassword }; users.push(newUser);
res.status(201).json({ message: 'User created' }); } catch (error) { res.status(500).json({ message: 'Server error' }); }});Login and JWT Token Generation
After verifying credentials, generate a token using jsonwebtoken:
app.post('/api/login', async (req, res) => { try { const { email, password } = req.body; // Find user const user = users.find(u => u.email === email); if (!user) {