Saltar al contenido

Cómo actualizar el token en Nestjs

Esta pregunta se puede resolver de diferentes formas, pero te enseñamos la que en nuestra opinión es la resolución más completa.

Solución:

La implementación del token de actualización podría manejarse en canActivate método en la protección de autenticación personalizada.

Si el token de acceso caduca, el token de actualización se utilizará para obtener un nuevo token de acceso. En ese proceso, el token de actualización también se actualiza.

Si ambos tokens no son válidos, se borrarán las cookies.

@Injectable()
export class CustomAuthGuard extends AuthGuard('jwt') 
  private logger = new Logger(CustomAuthGuard.name);

  constructor(
    private readonly authService: AuthService,
    private readonly userService: UserService,
  ) 
    super();
  

  async canActivate(context: ExecutionContext): Promise 
    const request = context.switchToHttp().getRequest();
    const response = context.switchToHttp().getResponse();

    try 
      const accessToken = ExtractJwt.fromExtractors([cookieExtractor])(request);
      if (!accessToken)
        throw new UnauthorizedException('Access token is not set');

      const isValidAccessToken = this.authService.validateToken(accessToken);
      if (isValidAccessToken) return this.activate(context);

      const refreshToken = request.cookies[REFRESH_TOKEN_COOKIE_NAME];
      if (!refreshToken)
        throw new UnauthorizedException('Refresh token is not set');
      const isValidRefreshToken = this.authService.validateToken(refreshToken);
      if (!isValidRefreshToken)
        throw new UnauthorizedException('Refresh token is not valid');

      const user = await this.userService.getByRefreshToken(refreshToken);
      const 
        accessToken: newAccessToken,
        refreshToken: newRefreshToken,
       = this.authService.createTokens(user.id);

      await this.userService.updateRefreshToken(user.id, newRefreshToken);

      request.cookies[ACCESS_TOKEN_COOKIE_NAME] = newAccessToken;
      request.cookies[REFRESH_TOKEN_COOKIE_NAME] = newRefreshToken;

      response.cookie(ACCESS_TOKEN_COOKIE_NAME, newAccessToken, COOKIE_OPTIONS);
      response.cookie(
        REFRESH_TOKEN_COOKIE_NAME,
        newRefreshToken,
        COOKIE_OPTIONS,
      );

      return this.activate(context);
     catch (err) 
      this.logger.error(err.message);
      response.clearCookie(ACCESS_TOKEN_COOKIE_NAME, COOKIE_OPTIONS);
      response.clearCookie(REFRESH_TOKEN_COOKIE_NAME, COOKIE_OPTIONS);
      return false;
    
  

  async activate(context: ExecutionContext): Promise 
    return super.canActivate(context) as Promise;
  

  handleRequest(err, user)  !user) 
      throw new UnauthorizedException();
    

    return user;
  

Adjuntar usuario a la solicitud se realiza en validate método en JwtStrategy clase, se llamará si el token de acceso es válido

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) 
  constructor(
    readonly configService: ConfigService,
    private readonly userService: UserService,
  ) 
    super(
      jwtFromRequest: cookieExtractor,
      ignoreExpiration: false,
      secretOrKey: configService.get('jwt.secret'),
    );
  

  async validate( id ): Promise 
    const user = await this.userService.get(id);
    if (!user) 
      throw new UnauthorizedException();
    

    return user;
  

En lugar de usar el incorporado AuthGuard puede crear uno propio y sobrescribir el controlador de solicitudes:

@Injectable()
export class MyAuthGuard extends AuthGuard('jwt') 

  handleRequest(err, user, info: Error) 
    if (info instanceof TokenExpiredError) 
      // do stuff when token is expired
      console.log('token expired');
    
    return user;
  


Dependiendo de lo que desee hacer, también puede sobrescribir el canActivate método donde tiene acceso al objeto de solicitud. Echa un vistazo a la AuthGuard código fuente.

Aquí puedes ver las comentarios y valoraciones de los lectores

Puedes añadir valor a nuestro contenido informacional colaborando tu experiencia en las críticas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *