Reputation: 4192
I am using to create backend NestJs
library. In my code i have used a guard
to check if my token is still active:
import {Injectable, CanActivate, ExecutionContext, HttpException, HttpStatus} from '@nestjs/common';
import { Observable } from 'rxjs';
import * as jwt from 'jsonwebtoken';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): any | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
const token = request.headers.authorization.split(' ')[1];
try {
const decoded = jwt.verify(token, '123');
console.log(decoded)
return true
} catch(e) {
console.log('tkn error', e)
throw new HttpException('User unauthorized', HttpStatus.UNAUTHORIZED);
}
}
}
also i have this service
that check the refresh token:
import {HttpException, HttpStatus, Injectable} from '@nestjs/common';
import * as jwt from 'jsonwebtoken';
import {InjectRepository} from "@nestjs/typeorm";
import {User} from "../entities/user.entity";
import {Repository} from "typeorm";
@Injectable()
export class RefreshService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
) {
}
async refresh(res, req) {
const userId = req.headers['userid'];
const refreshToken = req.headers.authorization.split(' ')[1];
const user = await this.usersRepository.findOne({
where: {
id: userId,
},
});
if (!refreshToken) {
throw new HttpException('User unauthorized', HttpStatus.UNAUTHORIZED);
}
jwt.verify(refreshToken, 'refresh', function (err, decoded) {
if (err) {
console.log(err)
throw new HttpException('User unauthorized rt', HttpStatus.UNAUTHORIZED);
} else {
const token = jwt.sign({foo: 'bar'}, '123', {expiresIn: '55s'});
res.send({
message: "You are logged in",
timestamp: new Date().toISOString(),
token: token,
user: user
});
}
});
console.log('refresh', refreshToken)
res.send(refreshToken)
}
}
Even if i used try catch
i get the error in console:
[0] (node:1444) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
[0] (node:1444) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
also i get:
[0] (node:15492) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Question: Which are my mistakes in the code above? How to solve them?
Upvotes: 1
Views: 268
Reputation: 17382
You throw some exeptions that aren't caught anywhere
canActivate(context: ExecutionContext): any | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
const token = request.headers.authorization.split(' ')[1];
try {
const decoded = jwt.verify(token, '123');
console.log(decoded)
return true
} catch(e) {
console.log('tkn error', e)
//remove the exception here and just return false
return false;
}
}
Furthermore in your second snippet, you are calling res.send(..)
for the same res
object twice, which results in the Error [ERR_HTTP_HEADERS_SENT]
you are seeing. Furthermore, you probably want some error handling also, when the user is not found ...
async refresh(res, req) {
const userId = req.headers['userid'];
const refreshToken = req.headers.authorization.split(' ')[1];
const user = await this.usersRepository.findOne({
where: {
id: userId,
},
});
if (user && refreshToken) {
jwt.verify(refreshToken, 'refresh', function (err, decoded) {
if (err) {
console.log(err);
//remove the exception and send an appropriate response
res.sendStatus(401);
} else {
const token = jwt.sign({foo: 'bar'}, '123', {expiresIn: '55s'});
res.send({
message: "You are logged in",
timestamp: new Date().toISOString(),
token: token,
user: user
});
}
});
} else {
//if no user or no refreshToken is found
res.sendStatus(401); //send unauthorized status
}
}
And just a hint for the security of the process: You should probably check somewhere, if refreshToken
and user
belong together. Otherwise, a user which has a valid refreshToken
can login impersonating any other user ...
Upvotes: 1