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.