Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

+1 210новых вакансий за сутки·93 612вакансий открыто сейчас·Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Новые вакансии в TelegramРаботодателям
Talanto
Вакансии
Компании7 266
РезюмеAIПодготовкаСтатьи
BoostТарифыBoost
Войти

Не нашли подходящее?

Пусть нужная вакансия найдёт вас сама.

  1. Подборка в TelegramНовые вакансии по вашему фильтру — сразу в бота.Подключить
  2. Мэтчи по резюмеЗагрузите резюме — покажем, где вы подходите лучше всего.Загрузить
  3. Сохранить фильтрНастройте поиск один раз и возвращайтесь к новым вакансиям.Настроить
Что нового на TalantoTalanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Для работодателей

Опубликуйте вакансию — отклики придут в ваш кабинет.

  1. Вакансиябесплатно
  2. Откликиконтакты бесплатно
  3. Наймэтапы и интервью

40 компаний публикуют вакансии напрямую · 4 401 кандидат открыт к предложениям

Разместить вакансию

Популярные направления

Все подборки
  • Python17 126
  • Облачные технологии14 083
  • QA вакансии3 456
  • Backend вакансии2 115
  • Инженер данных1 809
  • Продакт-менеджер1 261

Разработка

  • Android1 862
  • iOS1 700
  • Fullstack вакансии986
  • AI вакансии950
  • Frontend вакансии744
  • Mobile вакансии44

По стеку

  • Go8 688
  • Java6 537
  • Node.js2 026
  • .NET1 722
  • Kotlin1 611
  • Rust1 458
  • C#710
  • PHP682
  • C++571

DevOps и инфраструктура

  • Kubernetes7 772
  • DevOps вакансии6 054
  • Linux-инфраструктура5 493
  • Terraform / IaC4 275
  • CI/CD3 239
  • Мониторинг и Observability1 790
  • SRE568
  • Кибербезопасность458

Аналитика и данные

  • Data Scientist1 143
  • Бизнес-аналитик923
  • Аналитик данных857
  • Системный аналитик152

Другие направления

  • Проджект-менеджер620
  • UI/UX дизайн146
  • Ручное тестирование14

По регионам

  • Вакансии в США44 276
  • Вакансии в Европе23 819
  • Вакансии в Канаде4 471
  • Работа в России3 904

По формату

  • Удалённые вакансии74 928
  • Релокация в США44 273
  • Гибридная работа12 388
  • Офисная работа7 083

По уровню

  • Senior вакансии42 625
  • Middle вакансии20 854
  • Junior вакансии6 721

Сейчас нанимают

Все компании
  • Wise190 вакансий
  • Rakuten189 вакансий
  • ASML166 вакансий
  • Grab137 вакансий
  • Celonis39 вакансий
  • Spotify37 вакансий
  • Adyen28 вакансий
  • Infobip28 вакансий
  • Monzo20 вакансий
  • Darktrace16 вакансий

Вакансии из 344 источников: карьерные страницы компаний и джоб-борды.

КомпанииО насНовостиПубличная офертаУсловия использованияПолитика конфиденциальностиПоддержка
←К теме Express.jsВсе вопросы
Express.jsMiddleКодинг

Как реализовать JWT-аутентификацию в Express-приложении?

В закладки
Сначала попробуйте ответить сами30 секунд
Сравнить с ответом ↓

JWT-аутентификация в Express: генерируем токен при логине через jsonwebtoken.sign(), отправляем клиенту, в middleware проверяем подпись через jwt.verify(). Access-токен живёт 15 мин, refresh-токен — в httpOnly cookie.

Установка

npm install jsonwebtoken bcrypt express-async-errors

Архитектура JWT-аутентификации

JWT (JSON Web Token) — самодостаточный токен, содержащий payload и подпись. Сервер не хранит сессии: при каждом запросе он только проверяет подпись токена. Стандартный подход: короткоживущий access token (15 мин) в заголовке Authorization + долгоживущий refresh token (7 дней) в httpOnly cookie.

Генерация токенов при логине

// auth.router.js
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const router = express.Router();

const ACCESS_SECRET = process.env.JWT_ACCESS_SECRET;   // минимум 32 байта
const REFRESH_SECRET = process.env.JWT_REFRESH_SECRET;

function generateTokens(userId, roles) {
  const accessToken = jwt.sign(
    { sub: userId, roles },
    ACCESS_SECRET,
    { expiresIn: '15m', algorithm: 'HS256' }
  );
  const refreshToken = jwt.sign(
    { sub: userId },
    REFRESH_SECRET,
    { expiresIn: '7d', algorithm: 'HS256' }
  );
  return { accessToken, refreshToken };
}

router.post('/login', async (req, res) => {
  const { email, password } = req.body;
  const user = await db.findUserByEmail(email);

  if (!user || !(await bcrypt.compare(password, user.passwordHash))) {
    return res.status(401).json({ error: 'Invalid credentials' });
  }

  const { accessToken, refreshToken } = generateTokens(user.id, user.roles);

  // Refresh token только в httpOnly cookie
  res.cookie('refreshToken', refreshToken, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'strict',
    maxAge: 7 * 24 * 60 * 60 * 1000, // 7 дней в мс
    path: '/auth/refresh',             // доступен только на endpoint обновления
  });

  res.json({ accessToken, expiresIn: 900 });
});

Middleware для проверки токена

// middleware/authenticate.js
const jwt = require('jsonwebtoken');

function authenticate(req, res, next) {
  const authHeader = req.headers['authorization'];
  if (!authHeader?.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'No token provided' });
  }

  const token = authHeader.slice(7);
  try {
    const payload = jwt.verify(token, process.env.JWT_ACCESS_SECRET, {
      algorithms: ['HS256'],  // явно указываем алгоритм!
    });
    req.user = { id: payload.sub, roles: payload.roles };
    next();
  } catch (err) {
    if (err.name === 'TokenExpiredError') {
      return res.status(401).json({ error: 'Token expired' });
    }
    return res.status(401).json({ error: 'Invalid token' });
  }
}

function requireRole(role) {
  return (req, res, next) => {
    if (!req.user?.roles?.includes(role)) {
      return res.status(403).json({ error: 'Forbidden' });
    }
    next();
  };
}

module.exports = { authenticate, requireRole };

Обновление access token

router.post('/refresh', (req, res) => {
  const token = req.cookies.refreshToken;
  if (!token) return res.status(401).json({ error: 'No refresh token' });

  try {
    const payload = jwt.verify(token, process.env.JWT_REFRESH_SECRET, {
      algorithms: ['HS256'],
    });
    // Опционально: проверяем токен в allowlist в Redis
    const { accessToken } = generateTokens(payload.sub, payload.roles);
    res.json({ accessToken, expiresIn: 900 });
  } catch {
    res.clearCookie('refreshToken', { path: '/auth/refresh' });
    res.status(401).json({ error: 'Invalid refresh token' });
  }
});

router.post('/logout', (req, res) => {
  res.clearCookie('refreshToken', { path: '/auth/refresh' });
  // Если нужен blacklist: добавляем jti access-токена в Redis до истечения
  res.status(204).end();
});

Использование middleware в маршрутах

const { authenticate, requireRole } = require('./middleware/authenticate');

app.get('/api/profile', authenticate, (req, res) => {
  res.json({ userId: req.user.id });
});

app.delete('/api/users/:id', authenticate, requireRole('admin'), async (req, res) => {
  await db.deleteUser(req.params.id);
  res.status(204).end();
});

Подводные камни

  • Алгоритм none — без явного указания algorithms: ['HS256'] библиотека может принять токен с алгоритмом none и нулевой подписью.
  • Хранение access token в localStorage — доступен через XSS; лучше держать в памяти JS (переменная) и обновлять через refresh.
  • Слабый секрет — короткие секреты ломаются брутфорсом офлайн, если утёк токен. Используйте минимум 256-битные ключи из crypto.randomBytes(32).toString('hex').
  • Нет инвалидации токенов — JWT stateless, поэтому смена пароля или выход не отзывают уже выданные токены. Нужен Redis-blacklist по jti (JWT ID).
  • Чувствительные данные в payload — payload не зашифрован, только подписан; не кладите пароли, email, PII в claims.
  • refresh token в localStorage — при XSS злоумышленник получает долгоживущий токен; только httpOnly cookie.
  • Отсутствие ротации refresh token — каждый запрос на /refresh должен выдавать новый refresh token и инвалидировать старый (refresh token rotation).

Частые вопросы на собеседовании

  • В чём разница между app.use() и app.get() / app.post()?
  • Какова роль next() в middleware Express? Что происходит, если его не вызвать?
  • Как работает маршрутизация в Express? Как организовать маршруты с помощью express.Router()?
  • Что такое middleware в Express.js? Объясните цикл запрос-ответ (request-response cycle).

Типичные ошибки

  • Дает общий ответ про Node.js и не называет конкретные API Express.js.
  • Не объясняет, где в lifecycle находится JWT-аутентификация.
  • Не разделяет validation, authorization, business logic и persistence.
  • Игнорирует ошибки, лимиты входных данных, observability и тестирование.

Что проверяет интервьюер

  • Может объяснить JWT-аутентификация на примере кода.
  • Называет ключевые API: Authorization: Bearer, jwt.verify().
  • Использует точные API Express.js, а не вымышленные hooks/decorators/methods.
  • Видит production-риски: безопасность, отказоустойчивость, логирование и тесты.

Как вы знаете этот вопрос?

Проверить себя по теме Express.js →

Источники

  • https://expressjs.com/en/advanced/best-practice-security.html
  • https://github.com/auth0/node-jsonwebtoken#readme
←Предыдущий вопросКак реализовать rate limiting в Express?Следующий вопрос→Как реализовать валидацию запросов в Express?

Связанные темы

Express.jsauthenticationauthorizationsecurity-boundaries

Вакансии с этим навыком

  • Fullstack JavaScript разработчик