I have a middleware to authenticate user via access & refresh token (JWT).
Everything was working fine until I put typescript into my project.
Here's my code:
import { UserJWTPayload } from '../interfaces/UserJWTPayload'
import { NextFunction, Request, Response } from 'express'
import { ResponseObject } from '../api/classes/ResponseObject'
import SequelizeApi from '../sequelize/sequelize-api'
import * as jwt from 'jsonwebtoken'
const authenticateUserTokens = async (req: Request, res: Response, next: NextFunction) => {
try {
const accessToken: string = req.cookies.access_token
const refreshToken: string = req.cookies.refresh_token
if (!accessToken || !refreshToken) return res.status(401).json(new ResponseObject(false, 'not authenticated', null))
console.log(jwt)
/*
[Module: null prototype] {
decode: [Function (anonymous)],
default: {
decode: [Function (anonymous)],
verify: [Function (anonymous)],
sign: [Function (anonymous)],
JsonWebTokenError: [Function: JsonWebTokenError],
NotBeforeError: [Function: NotBeforeError],
TokenExpiredError: [Function: TokenExpiredError]
}
}
*/
console.log(jwt.verify())
/*
export function verify(token: string, secretOrPublicKey: Secret, options?: VerifyOptions & { complete?: false }): JwtPayload | string;
An argument for 'token' was not provided
*/
console.log(jwt.verify(accessToken, process.env.JWT_ACCESS_TOKEN_PRIVATE_KEY))
/*
TypeError: jwt.verify is not a function
at file:///C:/Users/Jakub/Desktop/Projekty/StoriesBatchApi/src/middlewares/authenticate-user-tokens.ts:16:25
at Generator.next (<anonymous>)
at file:///C:/Users/Jakub/Desktop/Projekty/StoriesBatchApi/src/middlewares/authenticate-user-tokens.ts:7:71
at new Promise (<anonymous>)
at __awaiter (file:///C:/Users/Jakub/Desktop/Projekty/StoriesBatchApi/src/middlewares/authenticate-user-tokens.ts:3:12)
at file:///C:/Users/Jakub/Desktop/Projekty/StoriesBatchApi/src/middlewares/authenticate-user-tokens.ts:7:96
at Layer.handle [as handle_request] (C:\Users\Jakub\Desktop\Projekty\StoriesBatchApi\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\Jakub\Desktop\Projekty\StoriesBatchApi\node_modules\express\lib\router\route.js:144:13)
at Route.dispatch (C:\Users\Jakub\Desktop\Projekty\StoriesBatchApi\node_modules\express\lib\router\route.js:114:3)
at Layer.handle [as handle_request] (C:\Users\Jakub\Desktop\Projekty\StoriesBatchApi\node_modules\express\lib\router\layer.js:95:5)
*/
const accessTokenData = jwt.verify(accessToken, process.env.JWT_ACCESS_TOKEN_PRIVATE_KEY) as UserJWTPayload
const refreshTokenFromDatabase = await SequelizeApi.getModel('user_token').findOne({ where: { refresh_token: refreshToken } })
if (!refreshTokenFromDatabase) return res.status(401).json(new ResponseObject(false, 'invalid refresh token', null))
jwt.verify(refreshToken, process.env.JWT_REFRESH_TOKEN_PRIVATE_KEY)
res.locals.id_user = accessTokenData.id_user
return next()
} catch (e) {
console.error(e)
return res.status(401).json(new ResponseObject(false, 'server error | not authenticated', e.message))
}
};
export default authenticateUserTokens
I console logged JWT object as well, but it didn't help to understand what's going on.
I will provide protected route too:
userRouter.delete('/:id', authenticateUserTokens(), async (req, res) => {
try {
const deletedUserId = parseInt(req.params.id)
const actionByUserId = parseInt(res.locals.id_user)
if (actionByUserId !== deletedUserId)
return res.status(403).json(new ResponseObject(false, 'not authorized', null))
const arrayOfAffectedRows = await userModel.update({ status: 'deleted' }, {
where: {
id: deletedUserId
}
})
if (arrayOfAffectedRows[0] === 1)
return res.status(200).json(new ResponseObject(true, 'user deleted', null))
else
return res.status(404).json(new ResponseObject(false, 'user not found', null))
} catch(e) {
return res.status(500).json(new ResponseObject(false, 'server error', e))
}
})
Here's my tsconfig.ts file:
{
"compilerOptions": {
"module": "ES6",
"removeComments": true,
"target": "es6",
"rootDir": "./",
"esModuleInterop": true,
"moduleResolution":"node",
},
"include": [ "src/**/*" ],
"exclude": [ "node_modules" ]
}
I use nodemon to run app in development:
nodemon -r dotenv/config --experimental-specifier-resolution=node --esm src/server.ts
I tried removing brackets in protected route:
authenticateUserTokens()
---> authenticateUserTokens
But it throwed error.
CodePudding user response:
I solved the problem by correcting import:
import * as jwt from 'jsonwebtoken'
--> import jwt from 'jsonwebtoken'
CodePudding user response:
use import jwt from 'jsonwebtoken' instead .
Why :
import * as jwt from 'jsonwebtoken' means that you are asking for an object with all of the named exports of 'jsonwebtoken'.
Then you can access any of the exports in 'jsonwebtoken' as something.name. In this case they will be something. but in the jsonwebtoken this the file they are exporting : node-jsonwebtoken/index.js is :
module.exports = {
verify: require('./verify'),
sign: require('./sign'),
JsonWebTokenError: require('./lib/JsonWebTokenError'),
NotBeforeError: require('./lib/NotBeforeError'),
TokenExpiredError: require('./lib/TokenExpiredError'),
};
Object.defineProperty(module.exports, 'decode', {
enumerable: false,
value: require('./decode'),
});