OAuth 2.0 и JWT авторизация на JavaScript: полное руководство для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в OAuth 2.0 и JWT: что это и зачем нужно?

Современные веб-приложения редко обходятся без системы авторизации. Будь то вход через Google, доступ к API или защита маршрутов в вашем Node.js приложении — вам понадобятся OAuth 2.0 и JWT (JSON Web Tokens). Эти технологии стали стандартом де-факто для безопасного обмена данными между клиентом и сервером.

В этой статье мы разберём, как работают OAuth 2.0 и JWT, и напишем простую систему авторизации на JavaScript (Node.js). Материал рассчитан на начинающих разработчиков, поэтому мы будем двигаться от теории к практике с подробными примерами кода.

Часть 1: Что такое OAuth 2.0 и как он работает?

OAuth 2.0 — это протокол авторизации, который позволяет приложениям получать ограниченный доступ к ресурсам пользователя без передачи пароля. Представьте, что вы хотите войти на сайт через свой аккаунт Google. OAuth 2.0 как раз отвечает за этот процесс.

Основные роли в OAuth 2.0

  • Resource Owner — пользователь, владеющий данными.
  • Client — ваше приложение (например, Node.js сервер).
  • Authorization Server — сервер, выдающий токены (например, Google, GitHub).
  • Resource Server — сервер, хранящий данные пользователя.

Типичный поток OAuth 2.0 (Authorization Code Grant)

  1. Пользователь нажимает «Войти через Google».
  2. Приложение перенаправляет его на сервер авторизации Google.
  3. Пользователь даёт согласие.
  4. Google возвращает authorization code на сервер приложения.
  5. Сервер обменивает этот код на access token.
  6. Сервер использует access token для доступа к данным пользователя.

На практике, для простых приложений часто используют JWT как формат токена доступа.

Часть 2: JWT — структура и принцип работы

JWT (JSON Web Token) — это компактный и самодостаточный способ передачи информации между сторонами в виде JSON-объекта. Токен подписывается, поэтому его можно верифицировать без обращения к базе данных.

Структура JWT

JWT состоит из трёх частей, разделённых точками (.):

header.payload.signature
  • Header — содержит тип токена и алгоритм подписи (например, HS256).
  • Payload — данные (claims), например, ID пользователя, роль, время жизни.
  • Signature — подпись, созданная с помощью секретного ключа.

Пример декодированного JWT

{
  "alg": "HS256",
  "typ": "JWT"
}
.
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1516242622
}
.
[signature]

Важно: payload не зашифрован, только подписан. Никогда не храните конфиденциальные данные (пароли) в JWT!

Часть 3: Реализация JWT авторизации на Node.js

Теперь перейдём к практике. Мы создадим простой REST API на Express.js с JWT-авторизацией. Для этого нам понадобятся библиотеки jsonwebtoken и bcryptjs.

Шаг 1: Установка зависимостей

npm init -y
npm install express jsonwebtoken bcryptjs dotenv
npm install --save-dev nodemon

Шаг 2: Базовая настройка сервера

// server.js
require('dotenv').config();
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');

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

const users = []; // В реальном проекте — база данных

const PORT = process.env.PORT || 3000;
const JWT_SECRET = process.env.JWT_SECRET || 'mysecretkey123';

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

Шаг 3: Регистрация пользователя

app.post('/register', async (req, res) => {
  try {
    const { username, password } = req.body;
    
    // Проверяем, существует ли пользователь
    const existingUser = users.find(u => u.username === username);
    if (existingUser) {
      return res.status(400).json({ message: 'Пользователь уже существует' });
    }

    // Хэшируем пароль
    const hashedPassword = await bcrypt.hash(password, 10);
    
    // Сохраняем пользователя
    const newUser = { id: users.length + 1, username, password: hashedPassword };
    users.push(newUser);

    res.status(201).json({ message: 'Пользователь создан' });
  } catch (error) {
    res.status(500).json({ message: 'Ошибка сервера' });
  }
});

Шаг 4: Вход и выдача JWT

app.post('/login', async (req, res) => {
  try {
    const { username, password } = req.body;
    
    // Ищем пользователя
    const user = users.find(u => u.username === username);
    if (!user) {
      return res.status(400).json({ message: 'Неверные данные' });
    }

    // Проверяем пароль
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
      return res.status(400).json({ message: 'Неверные данные' });
    }

    // Создаём JWT токен
    const token = jwt.sign(
      { userId: user.id, username: user.username },
      JWT_SECRET,
      { expiresIn: '1h' }
    );

    res.json({ token });
  } catch (error) {
    res.status(500).json({ message: 'Ошибка сервера' });
  }
});

Шаг 5: Middleware для проверки токена

function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN

  if (!token) {
    return res.status(401).json({ message: 'Токен не предоставлен' });
  }

  jwt.verify(token, JWT_SECRET, (err, user) => {                

Блоги

Рекомендаций по книгам