Sorry for my bad English!
I build an app using MEAN Stack (MongoDB + Express.js + Angular.js + Node.js) and authentication using passport.js and JWT (jsonwebtoken and express-jwt).
What i want to do?
The login and registration routes render html, using nunjucks, and if it goes success we render index.html file, placing in public directory.
P.S.: is this a correct method?
What is my question?
Can anyone tell me, the technology to do this?
My code (based on https://thinkster.io/mean-stack-tutorial):
app.get('/', function(req,res){
if (!req.user)
res.redirect('/about')
else
res.render('index')
});
app.get('/login',function(req, res) {
res.render('auth/login', {
title: 'Login'
});
});
app.post('/', function(req, res, next) {
if (!req.body.login || !req.body.password) {
return res.status(400).json({ message: 'Please fill out all fields' });
}
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (user) { return res.json({ token: user.generateJWT()});
/*generateJWT form user model code returns jwt.sign({}) using jsonwebtoken:
var jwt = require('jsonwebtoken');
*/
} else { return res.status(401).json(info);}
})(req, res, next);
});
In this code we return generated token, if login is success. What should i do to render index.html and what could i do with generated token?
Sorry for this dummy questions, i'm still learning jwt. Thank's
Node is a Server Side Language. Since you are using MEAN stack, generally,
you need to create APIs in node and pass datas to client side Angular.
So to answer your question- To render html, your function for login needs to return something to client, using callbacks, and Angular will render your html pages.
What you need to do with the generated token is that from next time any requests to server without the token will/should generate error.
Else anyone can call your node APIs and and desired results. This is extremely necessary atleast for GET methods.
Related
I am currently using app.get and app.post for input and output from my database. This works perfectly fine, but when I go to the /login page for my web application, I am able to see all of the data for all of the players in a large array. I tried this on multiple computers, and it seems that anyone can view it. Is there any way to make app.get and app.post pages unreachable?
My code snippet:
app.use(express.json());
app.use(express.urlencoded());
app.post('/login', (req, res) => {
var query = { username: req.body.username };
dbo.collection("data").find(query).toArray(function(err, result) {
if(result.length == 0){
var myobj = { username: req.body.username, password: req.body.password };
dbo.collection("data").insertOne(myobj, function(err, res) {});
}
res.send(result);
});
});
app.get('/login', (req, res) => {
dbo.collection("data").find({}).toArray(function(err, result) {
if (err) throw err;
res.send(result);
});
});
I am using mongodb's serverless instance, and node.js to run the code.
On the /login page(example.com/login):
The passwords were changed for privacy sake.
With everyone's comments, I was able to figure out how to fix it!
The way to fix the problem, is to use app.post() functions to transfer data from the index.html file to the index.js file. This allows everything to be done behind the scenes. With this information, I was able to only res.send() a boolean instead of the entire array. This made it so that the page only showed "true" or "false" instead of everyone's data. Furthermore, I used bcrypt to encrypt passwords, so even if hackers could see the data, they could not hack anyone.
so i have a chat app that i am working on here and i am trying to make it to where a user can type in like https://niknet.ddns.net/room/randomroomUID and it will join them to that room if they are logged in (i use password for handling login and signup) my code looks like this on my routes.js (in case you dont know it's the js that handles all my express stuff)
i tried this
app.get('/room/:roomUid', isLoggedIn, function(req, res) {
console.log(req.params.roomUid)
console.log(req.user)
res.cookie('uid',req.user.uid, { maxAge: 999999999999999999999});
var username = req.user.displayName;
app.post( 'apolloMainchat',{ roomUid:req.params.roomUid , username});
});
but im not sure how to pass the information across to the express code that handles when users /apolloMainchat
typically a user can get to /apolloMainchat like this
app.get('/apolloMainchat', isLoggedIn, function(req, res) {
console.log(req.user)
res.cookie('uid',req.user.uid, { maxAge: 999999999999999999999});
var username = req.user.displayName;
res.render('apolloMainchat.ejs', username);
console.log(req.user.displayName)
});
any one know how to help me?
You will want to pass this by redirecting the client to a new endpoint and then reading those parameters from the query as Renato Gama said in the comments.
Your code will then become something like this.
app.get('/room/:roomUid', isLoggedIn, function(req, res) {
res.cookie('uid',req.user.uid, { maxAge: 999999999999999999999});
app.redirect('apolloMainchat?roomUid=' + req.params.roomUid);
});
app.get('/apolloMainchat', function(req, res, next) {
console.log(req.params.roomUid);
});
You're just using a HTTP redirect to pass them to the new endpoint and attaching the data as a query parameter as you would if they requested it directly. It's not quite clear what you're trying to achieve, but this should do what you've described.
I am creating a user management system - However I am current finding myself checking the user type on a per router bases.
router.get('/admin/settings', (req, res) => {
if(admin) {
//Proceed.
}
}
router.get('/admin/users', (req, res) => {
if(admin) {
//Proceed.
}
}
Is there a better way of doing this? Can't I just set a route like this?
router.get('/admin*', (req, res) => {
if(!admin) {
res.status(404).send('Not found')
}
}
(I have tried and not succeeded, feels like it clashes with other routes)
Also, on a similar note. How Am I supposed to handle denying a user access to a script? Do I send a 404 or 403?
You can use an Express middleware function:
router.use(function(req, res, next) {
if(admin) {
return next();
}
// We fail closed
return res.status(403).send('Forbidden');
});
// This won't get called if the middleware doesn't call next()
router.get('/admin/settings', (req, res) => {
// Do stuff
}
Here, we call next() only if the user is an admin, which allows the call to continue. Any routes added after this middleware will be protected.
Also, on a similar note. How Am I supposed to handle denying a user access to a script?
A 403 is the appropriate code here, though a 404 can also be used if you wish to hide the route from unauthorized clients. I would suggest reading up on what each code is designed for.
I just went through a tutorial and made a simple restful api. Afterwards, I added an admin user to my database. When I run the server, the authentication works, but if I try to access data via the api from the browser I get the eternal "waiting for response from localhost". I'm not sure what else I need to do for the request to be processed now that I've included a user authentication in mongodb.
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://admin:password#localhost/bookstore?authSource=admin");
app.get("/", function(req, res){
res.send("Hello World");
});
When going to localhost:3000/ I see hello world, but localhost:3000/api/books won't return anything
app.get("/api/books", function(req, res){
Genre.getBooks(function(err, books){
if(err){
throw err;
}
res.json(books);
});
});
Here's the getBooks function
module.exports.getBooks = function(callback, limit){
Book.find(callback).limit(limit);
};
You're not in any way handling the callbacks from Node correctly. You also haven't defined what Genre or Book is in your answer.
That said, a couple notes. First, if you are in a callback, you never want to throw an error (as in don't use the syntax throw err), instead you want to either handle it or pass it back to your calling code.
A common approach I use would be like this:
app.get("/api/books", function(req, res, next){ // note adding next here
Genre.getBooks(function(err, books){
if(err){
return next(err);
}
return res.json(books);
});
});
// sometime later, a generic error middleware. You can make yours more useful
app.use((err, req, res, next) => {
return res.status(500).send({ message: 'An error has occurred' });
});
Your mongoclient connection and getBooks syntax are also probably wrong, but I can't advise you the best way to fix it without knowing if you're using Mongoose or if you're doing something else.
Ok, so since you're using Mongoose, you should remove the MongoClient code you have. Instead, add at app startup:
const mongoose = require('mongoose');
mongoose.connect('your connectionstring here');
and your getBooks should look like this:
module.exports.getBooks = function(callback, limit){
Book.find({}).limit(limit).exec(callback);
};
As a sidenote, node apps typically use the callback as the final argument in a parameter list, so you might want to change the function signature to (limit, callback) and adjust the calling code accordingly.
I figured out the problem. I didn't have mongoose properly set as the client, so when referencing the exported code for finding the book data nothing happened.
I am trying to simply set the cookie for the JSON Web Token during authentication in my Node.js and Express web application.
Since I cannot do res.redirect after using res.cookie(), how can I achieve this?
router.post('/', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (!user) { return res.redirect('/auth'); }
var theToken = jwt.encode({ id : user.id }, req.app.get('appSecret'));
res.cookie(theToken);
return res.redirect('/profile/' + username);
})(req, res, next);
});
Am I approaching this problem correctly? I cannot find much of anything on how people are setting their JSON Web Tokens once they have created them.
It seems that res.redirect works with setting the cookies, despite what some other SO answers state. Hopefully this helps someone else.