Реализация OAuth 2.0 в Express с GitHub
TL;DR
OAuth 2.0 позволяет безопасно предоставить сторонним приложениям доступ к данным пользователя без передачи пароля. В этой статье показана пошаговая реализация авторизации через GitHub в приложении на Express: настройка окружения, маршруты, обмен кода на access token, рекомендации по безопасности и список альтернатив.

OAuth 2.0 — это стандарт авторизации, который позволяет сторонним приложениям получать доступ к данным веб-сервисов безопасно. Он полезен, когда нужно получить профиль пользователя, список событий, адрес электронной почты и другие ресурсы, размещённые у провайдеров вроде GitHub, Google или Facebook. Сервис получает разрешение действовать от имени пользователя без передачи его пароля стороннему приложению.
В этом руководстве вы найдёте пошаговое описание реализации потока OAuth в приложении на Express с использованием GitHub как провайдера. Материал включает примеры кода, советы по безопасности, варианты альтернативной реализации и контрольные списки для разных ролей.
Кому пригодится этот материал
- Разработчикам backend, которые хотят добавить вход через третьи стороны.
- Фронтенд-инженерам, создающим кнопку «Войти с GitHub».
- DevOps-инженерам, настраивающим окружение и секреты.
Ключевые термины (1‑строчное определение)
- OAuth 2.0 — протокол авторизации, позволяющий получить токен доступа без передачи пароля.
- Access token — маркер, позволяющий приложению запрашивать данные от имени пользователя.
- Client ID / Client Secret — идентификатор и секрет приложения у провайдера.
Общий поток OAuth (объяснение)
- Пользователь нажимает «Войти с GitHub» на вашем сайте.
- Браузер перенаправляется на страницу авторизации GitHub с параметрами (client_id, scope и т. п.).
- Пользователь даёт согласие (если ещё не дал).
- GitHub перенаправляет обратно на ваш callback URL с кодом авторизации.
- Ваш сервер обменивает код на access token на защищённом сервер‑сервер запросе.
- С этим токеном вы можете вызывать API GitHub для чтения данных в пределах scope.
Шаг 1: Подготовка окружения разработки
Создайте пустую папку проекта и перейдите в неё:
mkdir github-app
cd github-appИнициализируйте npm:
npm init -yОткройте package.json и укажите тип модуля ES6:
{
"name": "github-app",
"version": "1.0.0",
"type": "module",
"main": "index.js"
}Это позволит использовать import вместо require.
Шаг 2: Установка зависимостей
Мы будем использовать:
- express — минимальный фреймворк для Node.js.
- axios — HTTP‑клиент для запросов к API провайдера.
- dotenv — загрузка секретов из .env в process.env.
Установите пакеты:
npm install express axios dotenvШаг 3: Создание простого Express‑приложения
Создайте файл index.js и вставьте базовую конфигурацию сервера:
// index.js
import express from "express";
import axios from "axios";
import * as dotenv from "dotenv";
dotenv.config();
const app = express();
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`App is running on port ${port}`);
});Этот код запускает сервер на порту 3000 по умолчанию или на значении из переменной окружения PORT.
Шаг 4: Маршруты для OAuth
Нам нужны два маршрута:
- /auth — перенаправляет пользователя на GitHub для запроса разрешений.
- /github-callback — обрабатывает ответ GitHub и получает access token.
Добавьте первый маршрут — перенаправление на авторизацию GitHub:
// index.js
app.get("/auth", (req, res) => {
// Store parameters in an object
const params = {
scope: "read:user",
client_id: process.env.CLIENT_ID,
};
// Convert parameters to a URL-encoded string
const urlEncodedParams = new URLSearchParams(params).toString();
res.redirect(`https://github.com/login/oauth/authorize?${urlEncodedParams}`);
});Параметр scope определяет, к каким данным вы запрашиваете доступ. Для чтения профиля подойдёт read:user; для email — user:email.
Теперь второй маршрут: обмен кода на токен:
// index.js
app.get("/github-callback", (req, res) => {
const { code } = req.query;
const body = {
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
code,
};
let accessToken;
const options = { headers: { accept: "application/json" } };
axios
.post("https://github.com/login/oauth/access_token", body, options)
.then((response) => response.data.access_token)
.then((token) => {
accessToken = token;
res.redirect(`/?token=${token}`);
})
.catch((err) => res.status(500).json({ err: err.message }));
});Этот маршрут принимает code, отправляет POST‑запрос к GitHub и получает JSON с access_token. После получения токена сервер перенаправляет пользователя на корень приложения с токеном в query (в реальном приложении лучше не передавать токен в URL).
Важно: никогда не логируйте client_secret и не храните его в публичном репозитории.
Шаг 5: Регистрация OAuth‑приложения на GitHub
- Войдите в GitHub.
- Перейдите в Settings → Developer settings → OAuth Apps.
- Нажмите Register a new application.

- Homepage URL: http://localhost:3000
- Authorization callback URL: http://localhost:3000/github-callback
После регистрации GitHub выдаст вам client_id и предложит сгенерировать client_secret. Скопируйте оба значения и поместите их в файл .env:
CLIENT_ID=your_client_id_here
CLIENT_SECRET=your_client_secret_here
PORT=3000Примеры использования access token
После получения access token вы можете запросить API GitHub. Пример получения информации о пользователе:
const user = await axios.get('https://api.github.com/user', {
headers: { Authorization: `token ${accessToken}` }
});
console.log(user.data);Не используйте token в блоке фронтенда или в URL — храните его на сервере в безопасном месте (сессия, encrypted store).
Безопасность и лучшие практики
- Храните CLIENT_SECRET в системах управления секретами (Vault, AWS Secrets Manager) или в защищённом .env, недоступном репозиторию.
- Используйте HTTPS в продакшн для защиты обмена кодами и токенами.
- Ограничьте scope минимально необходимыми правами.
- Не передавайте access token в URL и не логируйте его.
- Используйте одноразовые state‑параметры (CSRF‑защита) при отправке на /authorize и проверяйте state при callback.
- Обновляйте зависимости и отслеживайте уязвимости.
Краткая инструкция по добавлению state:
// Перед redirect на GitHub сгенерируйте state и сохраните в сессии
const state = crypto.randomBytes(16).toString('hex');
req.session.oauthState = state;
const params = { scope: 'read:user', client_id: process.env.CLIENT_ID, state };А при callback сравните req.query.state с сохранённым state.
Приватность и соответствие правилам (GDPR/Privacy)
- Запрашивайте только те данные пользователя, которые действительно необходимы для функциональности.
- Информируйте пользователя, какие данные вы запрашиваете и для каких целей.
- Обеспечьте возможность удаления привязки OAuth и удаление связанных данных по запросу пользователя.
- Храните логи с персональными данными ограниченное время.
Если ваше приложение работает с европейскими пользователями, опишите в политике конфиденциальности, как вы используете данные, и предоставьте контакт для запросов по удалению или экспорту данных.
Альтернативные подходы
- Passport.js (стратегия passport‑github) — готовая библиотека для интеграции OAuth с express-сессиями и множеством стратегий.
- simple-oauth2 — библиотека для управления токенами и обновлениями.
- Auth0, Okta, Firebase Auth — готовые IDaaS решения для аутентификации и управления пользователями.
Когда использовать альтернативы:
- Используйте Passport.js, если вам нужна быстрое подключение множества провайдеров и интеграция с сессиями.
- Используйте внешнего провайдера (Auth0), если вы хотите делегировать управление пользователями и снизить операционные риски.
Ментальные модели и эвристики
- «Минимальные права» — всегда запрашивайте минимум scope.
- «Сервер‑сервер» — обмен кода на токен должен происходить на сервере, а не в браузере.
- «Срок жизни и отзыв» — думайте о том, как отозвать доступ и как обновлять токены.
Контрольный список для ролей
Разработчик backend:
- Зарегистрировать приложение на GitHub.
- Реализовать /auth и /github-callback.
- Обменять code на access token на сервере.
- Сохранить токен и сопоставить с сессией/пользователем.
Фронтенд‑разработчик:
- Добавить кнопку «Войти с GitHub» и ссылку на /auth.
- Не хранить access token в localStorage без шифрования.
DevOps / Безопасность:
- Хранить CLIENT_SECRET в менеджере секретов.
- Включить HTTPS и HSTS.
- Настроить ротацию секретов и мониторинг.
Тесты и критерии приёмки
Критерии приёмки:
- При нажатии «Войти с GitHub» пользователь попадает на страницу согласия GitHub.
- После отказа от доступа приложение корректно обрабатывает ошибку.
- При успешной авторизации сервер получает access token и возвращает успешный ответ клиенту.
- Токен не передаётся в виде незашифрованного логирования или в URL в продакшне.
Примеры тест-кейсов:
- Успешный сценарий: пользователь даёт доступ — получение и использование токена.
- Отказ пользователя: GitHub возвращает error — приложение показывает понятное сообщение.
- Несоответствие state: state не совпадает — запрос отклоняется.
Когда OAuth не подходит (контрпримеры)
- У вас одно API и вы хотите полностью контролировать пользователей: проще реализовать собственную систему аутентификации.
- Ваше приложение — внутренний инструмент без внешних пользователей: используйте корпоративные SSO решения.
- Вам нужно длительное доверие без взаимодействия пользователя и без возможности обновлять токен: рассмотрите другие схемы аутентификации и авторизации.
SOP: быстрый план действий для запуска в прод
- Зарегистрировать приложение у провайдера и настроить callback URL.
- Поместить client_id и client_secret в менеджер секретов.
- Реализовать маршруты /auth и /callback с проверкой state.
- Использовать HTTPS и защиту от CSRF.
- Проверить логи и удалить тестовые секреты.
- Настроить мониторинг ошибок и алерты для неудачных попыток авторизации.
Краткая справка — факты и конвенции
- Endpoint авторизации GitHub: https://github.com/login/oauth/authorize
- Endpoint обмена кода на токен: https://github.com/login/oauth/access_token
- Типичный scope для чтения профиля: read:user
- Токены GitHub не обязательно обновляются через refresh token; стратегия зависит от провайдера.
Подсказки миграции и совместимости
- При переводе на Passport.js сохраните ту же логику state и сессии, но замените ручные запросы на готовую стратегию.
- При переносе в прод установите корректные callback URL (HTTPS) в настройках приложения на стороне провайдера.
Резюме
OAuth 2.0 даёт безопасный способ делегировать доступ к ресурсам пользователя без хранения пароля. Реализация в Express включает регистрацию приложения на GitHub, два ключевых маршрута (/auth и /github-callback), обмен кода на access token и набор процедур безопасности: хранение секретов, проверка state, использование HTTPS и минимизация scope.
Если вам нужна быстрая интеграция с множеством провайдеров — рассмотрите Passport.js. Если вы хотите делегировать всю аутентификацию — посмотрите на Auth0 или другие IDaaS.
Ключевые шаги: зарегистрировать приложение, добавить маршруты, защитить секреты и протестировать сценарии отказа.
Похожие материалы
Документация API с Postman
Автовход в Windows 11/10 — как включить и обезопасить
Автоматическое перемещение файлов на Windows и macOS
Обновление офлайн‑Windows через Portable Update
ChatGPT для выбора фильмов и сериалов