Поиск по сайту
Ctrl + K
Вопросы по Nest.js

Как реализовать механизм обновления токенов в NestJS?

Введение

Механизм обновления токенов (token refresh) является важной частью систем аутентификации, так как позволяет поддерживать пользовательские сессии без необходимости повторной аутентификации. В данной статье мы рассмотрим, как реализовать автоматическую стратегию обновления токенов в приложении на NestJS.

Основные концепции

  • Токены доступа и токены обновления:
    • Токен доступа (access token): используется для доступа к защищенным ресурсам и имеет короткое время жизни (например, 15 минут).
    • Токен обновления (refresh token): используется для получения нового токена доступа и имеет более длительное время жизни (например, 7 дней).
  • Стратегия обновления токенов:
    • Когда токен доступа истекает, клиент отправляет токен обновления на сервер, чтобы получить новый токен доступа.
    • Сервер проверяет токен обновления, и если он действителен, возвращает новый токен доступа.
  • Реализация в NestJS

    Установка необходимых зависимостей

    Сначала установим необходимые пакеты:

    npm install @nestjs/jwt passport-jwt
    

    Создание модуля аутентификации

    Создадим модуль аутентификации, который будет содержать логику работы с токенами.

    import { Module } from '@nestjs/common';
    import { JwtModule } from '@nestjs/jwt';
    import { AuthService } from './auth.service';
    import { AuthController } from './auth.controller';
    
    @Module({
      imports: [
        JwtModule.register({
          secret: 'your-secure-secret', // Убедитесь, что секрет безопасен
          signOptions: { expiresIn: '15m' }, // Время жизни токена доступа
        }),
      ],
      providers: [AuthService],
      controllers: [AuthController],
    })
    export class AuthModule {}
    

    AuthService: Логика аутентификации и обновления токена

    import { Injectable } from '@nestjs/common';
    import { JwtService } from '@nestjs/jwt';
    
    @Injectable()
    export class AuthService {
      constructor(private readonly jwtService: JwtService) {}
    
      async generateAccessToken(userId: number) {
        return this.jwtService.sign({ userId });
      }
    
      async generateRefreshToken(userId: number) {
        return this.jwtService.sign({ userId }, { expiresIn: '7d' }); // Токен обновления
      }
    
      async refreshTokens(userId: number, refreshToken: string) {
        const payload = this.jwtService.verify(refreshToken); // Проверяем токен обновления
        if (!payload) throw new Error('Invalid refresh token');
    
        // Генерируем новый токен доступа
        const accessToken = await this.generateAccessToken(userId);
        return { accessToken };
      }
    }
    

    AuthController: Эндпоинт для обновления токена

    import { Controller, Post, Body } from '@nestjs/common';
    import { AuthService } from './auth.service';
    
    @Controller('auth')
    export class AuthController {
      constructor(private readonly authService: AuthService) {}
    
      @Post('refresh')
      async refreshTokens(@Body('refreshToken') refreshToken: string) {
        // Здесь userId должен быть получен из базы данных, часто в реальных приложениях
        const userId = /* logic to get userId from refresh token */;
        return this.authService.refreshTokens(userId, refreshToken);
      }
    }
    

    Клиентская сторона

    Для обновления токена с клиентской стороны (например, с использованием fetch):

    async function refreshToken() {
      const response = await fetch('/auth/refresh', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ refreshToken: localStorage.getItem('refreshToken') }),
      });
    
      if (response.ok) {
        const data = await response.json();
        localStorage.setItem('accessToken', data.accessToken);
      } else {
        // Обработка ошибки: токен обновления недействителен
        console.error('Unable to refresh token');
      }
    }
    

    Заключение

    Реализуя механизм обновления токенов в NestJS, вы улучшаете пользовательский опыт, позволяя пользователям оставаться в системе без частой повторной аутентификации. Этот пример служит базовым ориентиром, который можно адаптировать под более сложные сценарии в зависимости от требований вашего приложения.