I kept getting
res.jwt is not a function
I have installed jwt-express and import it like so
import jwt from 'jwt-express'
This is my auth.js
import Account from '../services/account.js'
import env from 'dotenv'
import _ from 'lodash'
const dotenv = env.config();
module.exports = {
/**
* Process the user login, generating and returning a token if successful.
*
* #return {res}
*/
async login(req, res, next) {
try {
let origin = req.headers.origin;
let accounts = await Account.getAccounts();
let account = _.find(accounts, {
'email_address' : req.body.username,
'password' : req.body.password
});
if (!account) {
res.send('Username/Password Wrong');
}
// res.send(account);
let authentication = res.jwt({
'email': account.email_address,
'id': account.account_id
});
res.send(authentication);
} catch (error) {
next(error)
}
}
};
index.js
import express from 'express'
import favicon from 'serve-favicon'
import path from 'path'
import bodyParser from 'body-parser'
import bluebird from 'bluebird'
import jwt from 'jwt-express'
import env from 'dotenv'
//Controllers
import fortinetController from './controllers/fortinet'
import authController from './controllers/auth.js'
//Logger
import logger from './config/logger.js'
//Constant
const router = express.Router();
const app = express();
const PORT = 3000;
const dotenv = env.config();
Promise = bluebird;
app.use(bodyParser.urlencoded({extended: true }));
app.use(bodyParser.json());
app.use(router)
app.use(express.static('public'))
app.use(favicon(path.join(__dirname,'public','favicon.ico')))
app.use(jwt.init('CARWASH', {cookies: false }));
router.get('/', (req,res) => {
res.send('Welcome to the backend provisioning daemon to program FortiManager')
});
router.post('/login', authController.login);
//Fortinet
router.post('/fortinet/login', fortinetController.login);
router.post('/fortinet/getSessionTimeOut', fortinetController.getSessionTimeOut);
router.post('/fortinet/logout', fortinetController.logout);
//Error handling function
app.use((err,req,res,next) => {
console.error(err.stack)
res.status(500).send(`Red alert! Red alert!: ${err.stack}`)
logger.error(`${req.method} ${req.url} - ${err.log || err.message}`);
});
app.listen(PORT, () => {
console.log(`Your server is running on ${PORT}`)
}
);
How can I debug this?
Update
I've tried to add this
console.log(jwt);
I got
[nodemon] 1.17.3
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `babel-node ./index.js`
{ active: [Function: active],
clear: [Function: clear],
create: [Function: create],
init: [Function: init],
options:
{ cookie: 'jwt-express',
cookieOptions: { httpOnly: true },
cookies: false,
refresh: true,
reqProperty: 'jwt',
revoke: [Function: revoke],
signOptions: {},
stales: 900000,
verify: [Function: verify],
verifyOptions: {} },
require: [Function: require],
valid: [Function: valid] }
Your server is running on 3000
You are not configuring express-jwt correctly.
You are using express-jwt completely wrong.
Let's walk through each point.
I'm not sure why you think you need to call jwt.init(...) when the documentation here states to simply do: jwt(...). So you'll need to make the following changes:
Change
app.use(jwt.init('CARWASH', {cookies: false }));
To
app.use(jwt({secret: 'CARWASH'}));
There does not exist a cookies options, not sure where you got that from.
Now express-jwt will only handle verification of the JWT. It does not generate JWT for as you are trying to do in your auth.js.
In order to generate JWT, you will need another module: jsonwebtoken. You will then use the module in your auth.js like so:
import jwt from "jsonwebtoken";
// ...
module.export = {
async login(req, res, next) {
try {
// ... auth logic omitted
// Here we generate the JWT
// Make sure the JWT secret is the SAME secret you used for express-jwt
let authentication = jwt.sign({
'email': account.email_address,
'id': account.account_id
}, 'CARWASH');
res.send(authentication);
}
catch (error) {
next(error);
}
}
}
Related
index.ts
import express, { Express } from 'express';
import dotenv from 'dotenv';
import { DataSource } from 'typeorm';
import cors from 'cors';
import bodyParser from 'body-parser';
import { Task } from './src/tasks/tasks.entity';
import { tasksRouter } from './src/tasks/tasks.router';
// Instantiate express app
const app: Express = express();
dotenv.config();
//Parsing incoming request
app.use(bodyParser.json());
//Use CORS install types as well
app.use(cors());
// Create Databse Connection
export const AppDataSource = new DataSource({
type: 'mysql',
host: 'localhost',
port: 3306,
username: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: process.env.MYSQL_DB,
entities: [Task],
synchronize: true,
logging: true,
});
//Define Server Port
const port = process.env.PORT;
AppDataSource.initialize()
.then(() => {
// Start listening Request on defined port
app.listen(port);
console.log('Data Source has been initialized');
})
.catch((err) => console.log(err));
//create a Route
app.use('/', tasksRouter);
tasks.router.ts
import { Request, Response, Router } from 'express';
import { validationResult } from 'express-validator';
import { tasksController } from './tasks.controller';
import { createValidator } from './tasks.validator';
export const tasksRouter: Router = Router();
tasksRouter.get('/tasks', tasksController.getAll);
tasksRouter.post(
'/tasks',
createValidator,
// eslint-disable-next-line #typescript-eslint/ban-ts-comment
//#ts-ignore
async (req: Request, res: Response) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res
.json({
errors: errors.array(),
})
.status(400);
}
},
);
tasks.controller.ts
import { AppDataSource } from '../../index';
import { Task } from './tasks.entity';
import { instanceToPlain } from 'class-transformer';
import { Request, Response } from 'express';
class TasksController {
constructor(private taskRepository = AppDataSource.getRepository(Task)) {}
// eslint-disable-next-line #typescript-eslint/ban-ts-comment
//#ts-ignore
public async getAll(req: Request, res: Response): Promise<Response> {
let allTasks: Task[];
try {
allTasks = await this.taskRepository.find({
order: {
date: 'ASC',
},
});
allTasks = instanceToPlain(allTasks) as Task[];
res.json(allTasks).status(200);
} catch (_errors) {
return res.json({ error: 'Internal Server Error' }).status(500);
}
}
}
export const tasksController = new TasksController();
Hi everyone, I wish you all a very Happy New Year.
I have a question, While accessing the Task Entity, I have been getting error in the tasks.controller.ts file and
TypeError: Cannot read properties of undefined (reading
'getRepository')
What can be the actual Issue? What difference soes it make if I Instantiate the class in tasks.controller.ts file instead of the tasks.router.ts file? coz it is working if I Instantiate the TasksController class inside the route
i find evrywhere solution white :
app.use(bodyParser.urlencoded({extended: true}));
i can use
JSON.stringify(req.files)
but im sur having a way to fix my problem
my mocha test :
it('a file', async function () {
const body = { pseudo: 'user', password: 'test#123', mail: 'supermail' };
const response = await fetch(hostName + '/authentication/register', {
method: 'post',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' }
})
const usr = await response.json();
request.post('/usrAction1/doc')
.field('token', usr.token)
.attach('file', 'test/test.pdf')
.end(function (err, res) {
if (err) {
console.log(err)
}
console.log(res.status) // 'success' status
});
});
and my rout handler :
router.post('/doc', async (req, res) => {
console.log('req.files');
console.log(req.files)
})
also my server.js:
import express from 'express'
import authentication from './src/login.js'
import './global/host.js'
import bodyParser from 'body-parser'
import cors from "cors"
import verifyToken from './middleware/auth.js'
import { userAction1, userAction2 } from './src/userAction.js'
import verifyLevel from './middleware/level.js'
import fileUpload from 'express-fileupload';
export default function myApp() {
const whitelist = [/http:\/\/localhost:*/, /http:\/\/127.0.0.1:*/]
const corsConfig = { origin: whitelist }
const app = express();
const port = hostPort;
//json encoded
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json())
app.use(cors(corsConfig))
// enable files upload
app.use(fileUpload({
createParentPath: true
}));
app.use('/usrAction1', userAction1())
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
return app;
}
myApp();
but don't to work for me .
i also test white external client server who juste runing a form and send it to my tested adress and
do the same [Object null prototype]
thank u for evry litel help
i waiting of some help i using this magique code i found somwhere on stackoverflow:
req.files && Object.keys(req.files)?.map((obj, idx) => { console.log(req.files['file'].data) })
if somone have a better idea i waiting .
thank to all
I am setting up a new server using nextJS and I would like to have a graphql endpoint within my app. This setup works perfectly when using 2 servers, however we only have access to 1 server so now I am moving the graphql server into my express server.
Server.js
import express from 'express'
import next from 'next'
import pg from 'pg'
import expressGraphiqlMiddleware from 'express-graphiql-middleware'
import requestProxy from 'express-request-proxy'
import ConnectionFilterPlugin from 'postgraphile-plugin-connection-filter'
const { ApolloServer } = require('apollo-server-express')
const { makeSchemaAndPlugin } = require('postgraphile-apollo-server')
....
app
.prepare()
.then(async () => {
const { schema, plugin } = await makeSchemaAndPlugin(
pgPool,
'public', // PostgreSQL schema to use
{
appendPlugins: [ConnectionFilterPlugin],
graphiql: true,
// PostGraphile options, see:
// https://www.graphile.org/postgraphile/usage-library/
}
)
...
const expressServer = express()
...
expressServer.get('/p/:id', (req, res) => {
const actualPage = '/post'
const queryParams = { title: req.params.id }
app.render(req, res, actualPage, queryParams)
})
...
//Scraping Tools
scrape(expressServer)
expressServer.get('*', (req, res) => {
return handle(req, res)
})
...
expressServer.listen(3001, err => {
if (err) throw err
console.log('> Ready on http://localhost:3001')
})
})
.catch(ex => {
console.info('error')
console.error(ex.stack)
process.exit(1)
})
I have simplified my example, but the key point here is: if I remove the async/await/promise from the current then() I will get the following error:
Error: Apollo Server requires either an existing schema, modules or typeDefs
As for course, schema and plugin will not be defined, however if I enable these promises I get: as the error
ror.js
generate SourceMap
error
Error: getaddrinfo ENOTFOUND undefined
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:60:26)
Waiting for the debugger to disconnect...
I am setting up a simple express.js node server, and I can't seem to get my custom error handler to work. It seems like it isn't being called at all and instead some default express.js error handler is being called.
Note that this is in typescript, and uses mongodb, if that matters (don't think it should). Here is the relevant code:
index.ts:
import routes from './routes/index.ts';
import express, { Request, Response, NextFunction } from 'express';
// other imports...
type ServerErrror = {
status: number;
message: string;
}
const app = express();
// set up logging...
app.use(bodyParser.json());
app.use('/', routes);
app.use((err: ServerError, req: Request, res: Response, next: NextFunction) => { // eslint-disable-line no-unused-vars
console.error('in error handler');
res.status(err.status).send(`got error: ${err.message}`);
});
mongoose.connect(MONGODB_URI)
.then(() => {
console.log('Successfully connected to database.');
app.listen(SERVER_PORT, () => {
console.log(`Server is up and running on port ${SERVER_PORT}`);
}).on('error', error => {
console.log('Error starting server:', error);
});
}, error => {
console.log('Error connecting to database:', error);
});
routes/index.ts:
import { Router } from 'express';
import dataRoutes from './data.ts';
const router = Router();
router.use('/data', dataRoutes);
export default router;
routes/data.ts:
import { Router } from 'express';
import Data from './models/Data';
const router = Router();
router.get('/', (_, res, next) => {
Data.find((error, data) => {
if (error) {
console.log('found an error')
next({ status: 500, message: 'got an error' });
return;
}
res.send(`Got data: ${JSON.stringify(data.map(datum => datum.toJSON()))}`);
});
});
export default router;
When I start the server and then send a GET request to the /data endpoint using postman, this is the output on the server:
Successfully connected to database.
Server is up and running on port 1234
found an error
GET /data 500 35.289 ms - 142 // this is from morgan logging
[object Object] // no idea where this is coming from, i assume express default error handler
And this is the return value i see in postman:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>[object Object]</pre>
</body>
</html>
Again, not sure where this is coming from. I assume it must be the express default error handler.
There are some problems with your code:
import routes from './routes/index.ts' should not have the *.ts extension.
import dataRoutes from './data.ts'; should not have the *.ts extension.
ServerErrror has one too many letters.
Here is short example that works on my machine. I removed the Mongoose-related code and changed the sample so that it is easy to reproduce in a single file. A call to http://localhost:5000/data returns customErrorHandler > dataRoutes.get > Error, which is I think what you require.
import { Request, Response, NextFunction } from 'express';
import bodyParser = require('body-parser');
import express = require('express');
type ServerError = {
status: number;
message: string;
}
const dataRoutes = express.Router().get('/', (_, res, next) => {
setTimeout(() => { // mimic an asynchronous operation
const error = true;
if (error) {
next({ status: 500, message: 'dataRoutes.get > Error' });
return;
}
res.send('dataRoutes.get > Success');
}, 1000);
});
const routes = express.Router().use('/data', dataRoutes);
const app = express();
app.use(bodyParser.json());
app.use('/', routes);
app.use((err: ServerError, req: Request, res: Response, next: NextFunction) => {
res
.status(err.status)
.send(`customErrorHandler > ${err.message}`);
});
app.listen(5000);
console.log('Now listening on port 5000');
This is my tsconfig.json file:
{
"compilerOptions": {
"moduleResolution": "node",
"module": "commonjs",
"allowSyntheticDefaultImports": true
}
}
These are my package.json dependencies:
"devDependencies": {
"#types/express": "^4.16.1",
"typescript": "^3.4.1"
},
"dependencies": {
"express": "^4.16.4"
}
It turns out the problem was my use of babel-preset-minify which apparently did not transform the code correctly. Getting rid of this preset made the code work with no other modifications.
In my case, I disable babel-preset-minify option deadcode and work well.
{
"presets": [
[
"minify",
{
"deadcode": false
}
]
]
}
I am trying to debug a failing JWT auth setup, which always returns a 401.
My passport setup (middleware/auth.js)
import passport from 'passport'
import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt'
module.exports = function() {
var options = {};
options.jwtFromRequest = ExtractJwt.fromAuthHeader()
options.secretOrKey = 'superdupersecret'
var strategy = new JwtStrategy(options, function(payload, done) {
console.log('this is not printing') <---------------
var user = payload.sub || null;
if (user) {
return done(null, { id: user._id });
} else {
return done(new Error("User not found"), null);
}
});
passport.use(strategy);
return {
initialize: () => {
console.log('this only prints on boot'); <---------------
return passport.initialize();
},
authenticate: () => {
console.log('this too') <---------------
return passport.authenticate("jwt", {session: false});
}
};
};
My server.js file where I initialize passport:
import express from 'express'
(...)
var auth = require("./middleware/auth.js")();
// Instantiate app
const app = express();
// Initialize passport for auth use
app.use(auth.initialize())
And my protected route that always returns a 401:
import express from 'express'
var auth = require("../middleware/auth.js")();
const userRouter = express.Router()
userRouter.get('/dashboard', auth.authenticate(), (req, res) => {
res.send('It worked! User id is: ' + req.user + '.')
})
export default userRouter
I have tried to add print statements within the actual passport.js module itself, as well as passport-jwt, with no success.
After the authentication middleware on the protected route, nothing logs.
I have tried a ton of setup permutations over the past 3 days now. Any help would be greatly appreciated
Ok, I followed the tutorial you mentioned and it seems to work.
Here are some notes (some may be obvious, no offense).
Copy exactly the code as the tutorial
After you have everything, you need to "login". Make a POST request to /token. Content type has to be application/json and on the body of the request you need to sent an object with email and password (from tutorial).
After you login, the server returns a token.
Take that token and now make a GET request to /user. In the headers of the request add: Authorization: JWT [your token here]. You have to write "JWT" and the token separated by one space.
The server returns a status 200. I modified so it returns the user.
app.get("/user", auth.authenticate(), function(req, res) {
res.json({user: req.user});
});