Passport Express (NodeJS) authentication gives an error - express

I'm having this problem that Passport Express (NodeJS Framework) gives back an error when testing with Postman. The code looks like this:
passport.use(new BasicStrategy(function verify(username, password, cb) {
cb("Bla", password === "Route")
}));
const app = express()
app.get('/haha', passport.authenticate('basic', { session: false }), (req, res) => {
res.send("Hello World")
console.log("Hello World")
})
const server = app.listen(8080, () => {
console.log("Server started")
})
This is the error from Postman. I did give it as input the above credential
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
Any help would be appreciated. Thank you!

Related

Failed to load resource: the server responded with a status of 404 (Not Found) on routing

I am trying to route in my project. I want that on clicking connect button the rooms page should get rendered. Home page is working fine but as soon I as click connect it shows Cannot GET /rooms/0b2636b5-c254-47f4-ade8-9e6b745a96d1.The code works fine when instead of routing to rooms it is on root url.
I am new to web development and I tried reading other questions on similar problem but couldn't understand.
Server side(Server.js):
const express = require('express');
const app = express();
const server = require('http').Server(app);
const { v4: uuidV4 } = require('uuid');
const io = require('socket.io')(server);
const { ExpressPeerServer } = require('peer');
const peerServer = ExpressPeerServer(server, {
debug: true
});
app.use('/peerjs', peerServer);
app.set('view engine', 'ejs');
app.use(express.static('public'));
app.get('/', (req, res) => {
res.render('home');
})
app.get('/rooms', (req, res) => {
res.redirect(`/rooms/${uuidV4()}`);
})
app.get('/rooms:room', (req, res) => {
res.render('room', { roomId: req.params.room })
})
server.listen(3000);
Client Side(script.js)
const socket = io('/rooms');
const videoGrid = document.getElementById('video-grid');
var peer = new Peer(undefined, {
path: '/peerjs',
host: '/rooms',
port: '3000'
})
Navigation bar on home.ejs
<nav class="nav">
<li class="nav-link">
Connect
</nav>
room.ejs
<script>
const ROOM_ID = "<%=roomId%>"
</script>
<script src="/socket.io/socket.io.js" defer ></script>
<script src="script.js" defer></script>
Structure of file
public
-script.js
views
-home.ejs
-room.ejs
server.js
You're really close to it, just 1 mistake in this block:
app.get('/rooms:room', (req, res) => {
res.render('room', { roomId: req.params.room })
})
It should be:
app.get('/rooms/:room', (req, res) => {
res.render('room', { roomId: req.params.room })
})
Express documentation page here in case you need it (section Route parameters).

Express file upload using multer file is undefined always

I have tried to make an api to upload files in express using multer middleware but the request.file is undefined.
the express code is given below,
const express = require("express");
var multer = require('multer');
const cors = require("cors");
var app = express();
app.use(cors({ origin: true }));
const multerMid = multer({
storage: multer.memoryStorage(),
limits: {
fileSize: 5 * 1024 * 1024,
},
});
app.post('/saveFile', multerMid.single('dp'), (request,response)=>{
try{
var dp = request.file;
if(dp)
{
return response.send("file uploaded");
}
else{
return response.send("No file uploaded");
}
}catch(error)
{
return response.send(error.errorMessage);
}
});
exports.app = functions.https.onRequest(app);
No file uploaded
this is what I always receive when I post a file to the route using the following html.
<html>
<head>
</head>
<body>
<form action = "<server>/saveFile" method="post" enctype="multipart/form-data">
<input type="file" name="dp"/>
<input type="submit" value="Save">
</form>
</body>
</html>
I need to upload the file to file to firebase storage thats why I don't use a static storage location in the multer object,
I am stuck please help.
Here a middleware needs to be defined
app.post('/saveFile', multerMiddleWare, (request,response)=>{...});
const multerMiddleWare = (req, res, next) => {
multerMid(req, res,
(error) => {
if (!error) return next();
return next('error');
});
};
const multerMid = multer({
storage: multer.memoryStorage(),
limits: {
fileSize: 5 * 1024 * 1024,
},
}).single('dp');

How can I conditionally render from 2 navbar choices using node, EJS, passport and session?

How can I conditionally render from 2 navbar choices using node, EJS, passport and session?
I would like to conditionally render from 2 navbar choices. I am using EJS, passport and session. I tried a few things but nothing worked. The goal is to render a Login nav bar if the client has not been authenticated or a nav bar with options if the client has been authenticated both nav bars using the same rest of the page.
I am posting a lot of code here that I wrote following Brad Traversy’s video “Node.js With Passport Authentication | Full Project” (by the way... thanks Brad. Big fan!). I do believe I am close to the solution in the nav-bar file. I just need a bit of help from someone who really knows what he is doing (I don’t). I would really appreciate it if one of you nice guys could take a look at the files below and tell me what I am missing.
It looks like Tiger Abrodi already asked this same question and it was solved by the Discord team (see How can i conditionally render the navbar using ejs). However, the answer is not shown. I believe this is a very useful solution that should be posted here for other guys so I promise that your solution will remain posted here for anyone else to see.
Thanks guys!
My Home Page; you can see I use "include" to call the nav-bar and this works.
<!-- Navigation Bar ----------------------------------->
<%- include('assets/nav-bar'); %>
<!--------- Main Body --------->
<div class="mainBodyContainter mBC2">
<h3>Busca por Marca:</h3>
<ul>
<li>Marca</li>
<li>Año</li>
<li>Modelo</li>
<li>Sub-Modelo</li>
</ul>
<button class="button">Buscar</button>
</div>
<!-- Right *** Anuncio -->
<%- include ('assets/main-ad') %>
<!----------------- Footings ----------------->
<%- include ('assets/footings') %>
My nav bar; PROBLEM: This decision making is NOT WORKING as it keeps considering user as UNDEFINED. I can verify that the user has been successfully authenticated by checking my dashboard included below.
<!-- -- Navigation Bar Decision -->
<% if (typeof user === 'undefined') { %>
<!---- Navigation Bar NON AUTHENTICATED CLIENT -------->
<div id="navBarHTML">
<nav>
<ul>
<li>Ayuda</li>
<li>Registrate</li>
<li>Acceso</li>
<li>Inicio</li>
</ul>
</nav>
</div>
<% } else { %>
<!---- Navigation Bar AUTHENTICATED CLIENT------------->
<div id="navBarHTML">
<nav>
<ul>
<li>Ayuda</li>
<li>Notificaciones</li>
<li>Mis Publicaciones</li>
<li>Salir</li>
<li>Inicio</li>
<li><a>Bienvenido <%= name %></a></li>
</ul>
</nav>
</div>
<% } %>
Dashboard
<h1>Dashboard</h1>
<br>
<p>Bienvenido <%= name %></p>
<br>
Logout
My index.js; it feeds the user name to my dashboard and it works fine!
const express = require('express');
const router = express.Router();
const { ensureAuthenticated } = require('../config/auth');
// Home page
router.get('/', (req, res) => res.render('home'));
// Dashboard ***PROTECTED FOR NO ACCESS UNLESS LOGGED IN***
router.get('/dashboard', ensureAuthenticated, (req, res) =>
res.render('dashboard', {
name: req.user.name
}));
module.exports = router;
My app.js; it works fine.
const express = require('express');
const expressLayouts = require('express-ejs-layouts');
const mongoose = require('mongoose');
const app = express();
const db = mongoose.connection;
const flash = require('connect-flash');
const session = require('express-session');
const passport = require('passport');
// Passport config
require('./config/passport') (passport);
// Connect to Mongo
mongoose.set('useNewUrlParser', true);
mongoose.set('useUnifiedTopology', true);
mongoose.connect('mongodb://localhost/eyonke_server')
.then(() => console.log('La base de datos de MongoDB conectó correctamente...'))
.catch(err => console.log(err));
// EJS
app.use(expressLayouts);
app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/views'));
// Bodyparser
app.use(express.urlencoded({ extended: false }));
// Express session middleware
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true,
}));
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
// Connect flash
app.use(flash());
// Global Variables
app.use((req, res, next) => {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
// Routes
app.use('/', require('./routes/index'));
app.use('/users', require('./routes/users'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`El servidor de eYonke esta corriendo en el puerto numero ${PORT}...`));
My passport config; works fine!
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// Load User model
const User = require('../models/User');
module.exports = function(passport) {
passport.use(
new LocalStrategy({ usernameField: 'email'}, (email, password, done) => {
//Match user
User.findOne({ email: email })
.then(user => {
if(!user) {
return done(null, false, { message: 'Email no registrado' });
}
// Match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if(err) throw err;
if(isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Contraseña incorrecta' });
}
});
})
.catch(err => console.log(err));
})
);
// Session
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
}
auth.js; works fine!
module.exports = {
ensureAuthenticated: function(req, res, next) {
if(req.isAuthenticated()) {
return next();
}
req.flash('error_msg', 'Necesitas entrar a tu cuenta para accesar este recurso');
res.redirect('/'); /*if not authenticated, then redirected to home page*/
}
}
My users.js for registering and logging in/out; works fine!
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');
//User model
const User = require('../models/User');
//Login page
router.get('/login', (req, res) => res.render('login'));
//Registration page
router.get('/register', (req, res) => res.render('register'));
// Register Handle
router.post('/register', (req, res) => {
const { name, email, password, password2 } = req.body;
let errors = [];
//Check for errors
//Check required fields
if(!name || !email || !password || !password2) {
errors.push({ msg: 'Por favor llena todos los campos'});
}
// Check passwords match
if(password !== password2) {
errors.push({ msg: 'Las contraseñas no son iguales'});
}
// Check password length
if(password.length < 6) {
errors.push({ msg: 'La contraseña debe tener al menos 6 caracteres'});
}
if(errors.length > 0) {
res.render('register', {
errors,
name,
email,
password,
password2
});
} else {
// Validation passed
User.findOne({ email: email })
.then(user => {
if(user) {
// User exists
errors.push({ msg: 'Email ya está registrado en eYonke'});
res.render('register', {
errors,
name,
email,
password,
password2
});
} else {
const newUser = new User({
name,
email,
password
});
// Hash Password
bcrypt.genSalt(10, (err, salt) =>
bcrypt.hash(newUser.password, salt, (err, hash) => {
if(err) throw err;
// set password to hashed
newUser.password = hash;
// Save user
newUser.save()
.then(user => {
req.flash('success_msg', 'Te has registrado exitosamente');
res.redirect('/users/login');
})
.catch(err => console.log(err));
}))
}
});
}
});
// Login handle
router.post('/login', (req, res, next) => {
passport.authenticate('local', {
successRedirect: '/', /*'/dashboard',*/
failureRedirect: '/users/login',
failureFlash: true
})(req, res, next);
});
// Logout handle
router.get('/logout', (req, res) => {
req.logOut();
req.flash('success_msg', 'Tu sessión ha terminado');
res.redirect('/');
});
module.exports = router;
I was able to find Tiger A. and he kindly helped me to solve it. The changes I made to my code are as follows:
1.- in app.js I added a global variable as follows:
app.use((req, res, next) => {
res.locals.user = req.user;
next();
});
2.- in my navbar I replace the decision line with the following:
<% if (!user) { %>
and that did the trick. Now I am able to decide which nav bar to use depending if the user has been authenticated or not.

Cannot display data from API request in views

I am brand new to Express and Node.js, trying to build server-rendered app which will display some data from API.
This is my code
app.js
var express = require("express");
var app = express();
var request = require("request");
var apiKey = '****************************';
var bodyParser = require("body-parser");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.set('viewEngine', 'ejs');
const options = {
method: 'POST',
url: 'http://api.somethingsomething.com/content/search/v1?',
headers: {
'X-Api-Key': `${apiKey}`,
'Content-Type': 'application/json'
},
body: {
'queryString': 'pigs',
'resultContext' : {
'aspects' :['title','lifecycle','location','summary','editorial' ]
}
},
json: true
}
app.get('/', function(req, res) {
request(options, function(error, response, body) {
if (!error && response.statusCode == 200) {
var info = JSON.stringify(body);
console.log(info);
res.render('index', { results: info}); // this does not render anything
}
})
});
app.listen(3000, function() {
console.log("Listening on port 3000");
})
index.ejs
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="searchResults">
<%= results %>
</div>
</body>
</html>
It does not render index.ejs and cannot display data.
Error: No default engine was specified and no extension was provided.
I tried googling it, but no luck. Any help will be appreciated; Thank you
problem was simple app.set('viewEngine', 'ejs'); was wrong, should be pp.set('view engine', 'ejs');

Auth on server side from an isomorphic js app

Hi I'm working on a isomorphic react app that uses passport.js for auth.
My problem is requests can come from the client, or from the server. If the request comes from the client, it's authenticated and all is good. BUT, if the request comes from the server, then the auth fails :(
Server (lots removed for sake of clarity):
server.use('/api/data', require('./api/data'));
server.get('*', async (req, res, next) => {
await Router.dispatch({ path: req.path, query: req.query, context }, (state, component) => {
<div>
{component}
</div>
);
data.css = css.join('');
});
});
/api/data:
router.get('/', auth.isAuthenticated, async (req, res, next) => {
res.status(200).send({result: 'working!'});
});
Routes:
on('/route', async (state, next) => {
// RESP IS A REJECTED RESPONSE :(
const resp = await fetch('/api/data');
const data = await resp.json();
return <Component data={data} />;
});