Home > Software engineering >  Express JS middleware function - jwt.verify() is not a function
Express JS middleware function - jwt.verify() is not a function

Time:10-27

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'),
});
  • Related