Гид по технологиям

Реализация OAuth 2.0 в Express с GitHub

5 min read Backend Обновлено 22 Dec 2025
OAuth 2.0 в Express с GitHub
OAuth 2.0 в Express с GitHub

Человек в худи печатает на ноутбуке с логотипом OAuth на экране

Что такое OAuth 2.0

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

Ключевой термин: access token — коротко живущий секрет, дающий доступ к данным пользователя от имени приложения.

Обзор потока OAuth

Типичный поток выглядит так:

  1. Пользователь выбирает вход через провайдера (например, GitHub).
  2. Ваше приложение перенаправляет пользователя на страницу согласия провайдера с набором параметров (client_id, scope, state и т.д.).
  3. После согласия провайдер возвращает вашему приложению код авторизации (authorization code).
  4. Сервер вашего приложения обменивает код на access token, отправив POST-запрос к токен-эндпоинту провайдера.
  5. С access token вы можете запрашивать данные пользователя с API провайдера.

Важно: всегда используйте параметр state для защиты от CSRF и храните секреты в окружении (ENV).

Быстрая диаграмма потока

flowchart LR
  A[Пользователь] --> B[Кнопка 'Войти через GitHub']
  B --> C[Перенаправление на GitHub /authorize]
  C --> D[Страница согласия GitHub]
  D --> E[Redirect с кодом на /github-callback]
  E --> F[Сервер: POST /login/oauth/access_token]
  F --> G[Получен access token]
  G --> H[Запрос /user с токеном]
  H --> I[Профиль пользователя отображён в приложении]

Подготовка окружения (шаг 1)

  1. Создайте пустую директорию проекта и перейдите в неё:
mkdir github-app
cd github-app
  1. Инициализируйте npm и включите ES модули:
npm init -y
# Откройте package.json и добавьте:
# "type": "module"
  1. Установите зависимости (Express, Axios, dotenv):
npm install express axios dotenv

Создание простого сервера Express (шаг 2)

Создайте файл index.js в корне проекта и добавьте базовый сервер:

// index.js
import express from "express";
import axios from "axios";
import * as dotenv from "dotenv";
import crypto from "crypto";

dotenv.config();

const app = express();
const port = process.env.PORT || 3000;

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

Пояснение: мы используем ES-модули, dotenv для переменных окружения и подключаем crypto для генерации state.

Роуты для OAuth (шаг 3)

Ниже — два ключевых обработчика: один для перенаправления на GitHub, второй для обработки callback и получения токена.

Обратите внимание на использование параметра state — он нужен для предотвращения CSRF. В простом примере state генерируется и хранится в cookie.

// index.js (добавьте к предыдущему коду)
import cookieParser from "cookie-parser";
app.use(cookieParser());

app.get("/auth", (req, res) => {
  const state = crypto.randomBytes(16).toString("hex");
  res.cookie("oauth_state", state, { httpOnly: true, sameSite: "lax" });

  const params = {
    scope: "read:user",
    client_id: process.env.CLIENT_ID,
    state,
  };

  const urlEncodedParams = new URLSearchParams(params).toString();
  res.redirect(`https://github.com/login/oauth/authorize?${urlEncodedParams}`);
});

app.get("/github-callback", async (req, res) => {
  try {
    const { code, state } = req.query;
    const savedState = req.cookies["oauth_state"];

    if (!code || !state || state !== savedState) {
      return res.status(400).send("Invalid state or missing code");
    }

    const body = {
      client_id: process.env.CLIENT_ID,
      client_secret: process.env.CLIENT_SECRET,
      code,
      state,
    };

    const options = { headers: { accept: "application/json" } };

    const tokenResponse = await axios.post(
      "https://github.com/login/oauth/access_token",
      body,
      options
    );

    const accessToken = tokenResponse.data.access_token;
    if (!accessToken) {
      return res.status(500).json({ err: "No access token received" });
    }

    // Пример запроса профиля пользователя
    const userResponse = await axios.get("https://api.github.com/user", {
      headers: {
        Authorization: `token ${accessToken}`,
        Accept: "application/vnd.github.v3+json",
      },
    });

    // В реальном приложении: создать/обновить локального пользователя и сессию
    res.json({ profile: userResponse.data });
  } catch (err) {
    res.status(500).json({ err: err.message });
  }
});

Важно: в продакшне не передавайте токены в URL. Сохраняйте их в безопасном хранилище (шифрованные куки, сессии на сервере или секретное хранилище).

Пример .env

CLIENT_ID=ваш_client_id_от_github
CLIENT_SECRET=ваш_client_secret_от_github
PORT=3000

Создайте файл .env в корне и добавьте в него значения, полученные после регистрации OAuth-приложения в GitHub.

Форма регистрации OAuth приложения на GitHub

Создание OAuth-приложения на GitHub (шаг 4)

  1. Войдите в GitHub → Settings → Developer settings → OAuth Apps → Register a new application.
  2. Укажите Homepage URL: http://localhost:3000
  3. Authorization callback URL: http://localhost:3000/github-callback
  4. Зарегистрируйте приложение и сохраните CLIENT_ID и CLIENT_SECRET в .env.

Примечание: для production используйте HTTPS и корректный домен в callback.

Запрос данных пользователя

После получения access token вы можете запросить профиль:

const resp = await axios.get("https://api.github.com/user", {
  headers: { Authorization: `token ${accessToken}` }
});
console.log(resp.data);

Для получения email используйте /user/emails или указывайте дополнительные scope (например, user:email).

Рекомендации по безопасности

  • Никогда не храните client_secret в репозиториях. Используйте переменные окружения или секретные менеджеры.
  • Используйте state для защиты от CSRF.
  • Применяйте HTTPS в production.
  • Ограничьте время жизни токенов и поддерживайте возможность их отзыва.
  • Храните токены в безопасных куках с флагами httpOnly и Secure или в серверной сессии.
  • Валидируйте redirect_uri на стороне провайдера (GitHub требует совпадения).

Альтернативные подходы и библиотеки

  • Passport.js — популярная стратегическая библиотека для Node.js с готовыми стратегиями для GitHub.
  • simple-oauth2 — абстракция для работы с токенами OAuth на сервере.
  • NextAuth — если используете Next.js, предоставляет готовые провайдеры и хранение сессий.
  • OpenID Connect (OIDC) — если нужна аутентификация плюс профилизация и стандартные claims.

Выбор зависит от масштаба: для простых случаев достаточно собственного кода; для сложных сценариев лучше использовать проверенные библиотеки.

Когда этот подход не подходит

  • Если нужно единое SSO для множества приложений — рассмотрите полноценный провайдер идентификации (Keycloak, Auth0).
  • Если приложение — CLI или устройство без браузера, используйте device flow (GitHub поддерживает устройство, но оно в отдельной документации).

Частые ошибки и способы их устранения

  • Ошибка: «No access token received» — проверьте корректность client_id и client_secret, а также заголовок Accept: application/json.
  • Ошибка: «Invalid state» — проверьте хранение и сравнение state (cookie, session).
  • Ошибка: CORS при запросах с фронта — не делайте обмен токена на клиенте; выполняйте обмен на серверной стороне.

Критерии приёмки

  • Пользователь может авторизоваться через GitHub и увидеть профиль.
  • CLIENT_SECRET не хранится в публичном репозитории.
  • State защищает от CSRF и проверяется на callback.
  • В продакшне callback использует HTTPS.

Чек-лист по ролям

  • Разработчик:

    • Реализовать /auth и /github-callback
    • Генерировать и проверять state
    • Запросить профиль и сохранить пользователя
  • Безопасность:

    • Проверить хранение секретов
    • Настроить HTTPS
    • Произвести ревью токенов и прав доступа (scope)
  • DevOps:

    • Обеспечить секреты в CI/CD
    • Настроить корректные переменные окружения на серверах
  • Продукт:

    • Утвердить список scope и privacy-политику
    • Решить, какие данные получать и хранить

Мини-методология внедрения

  1. Зарегистрировать приложение в GitHub и получить client_id/client_secret.
  2. Настроить окружение и базовый сервер Express.
  3. Реализовать роут /auth (с state) и /github-callback.
  4. Обменять код на access token на сервере.
  5. Запросить профиль и реализовать создание/вход пользователя в системе.
  6. Провести ревью безопасности и тестирование.

Тесты и сценарии приёмки

  • При клике на /auth пользователь перенаправляется на GitHub.
  • После согласия GitHub возвращает код и state; сервер корректно обменивал код на токен.
  • Неверный state приводит к 400.
  • При проблемах на стороне GitHub приложение возвращает информативную ошибку.

Риск-матрица и mitigations

  • Утечка client_secret → mitigations: секреты в менеджерах, доступ по ролям, регулярная ротация.
  • Перехват токена → mitigations: HTTPS, httpOnly cookie, короткий TTL.
  • CSRF → mitigations: state, SameSite куки.

Заключение

OAuth 2.0 упрощает интеграцию авторизации через сторонние сервисы и позволяет избежать хранения пользовательских паролей. При правильной реализации (защита state, безопасное хранение секретов, HTTPS) интеграция становится безопасной и масштабируемой. Для простых проектов можно обойтись собственным минимальным кодом; для проектов с повышенными требованиями безопасности или множеством провайдеров стоит рассмотреть использование проверенных библиотек.

Важно: тестируйте поток в staging и проверяйте поведение при отказах провайдера.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Технологические новости: Facebook, Apple, Microsoft и другое
Технологии

Технологические новости: Facebook, Apple, Microsoft и другое

Нативное разрешение экрана на Mac — как узнать
macOS

Нативное разрешение экрана на Mac — как узнать

Как отключить людей от Wi‑Fi и защитить роутер
Безопасность

Как отключить людей от Wi‑Fi и защитить роутер

Как объединить устройства HomeKit в комнаты, зоны и сцены
Умный дом

Как объединить устройства HomeKit в комнаты, зоны и сцены

Меню «Дополнительные параметры» в Windows 11 — как использовать
Windows

Меню «Дополнительные параметры» в Windows 11 — как использовать

Как провести встречу в Zoom — полное руководство
Руководство

Как провести встречу в Zoom — полное руководство