Trying to understand user authentication in order to integrate into my web app. I've been following http://www.sitepoint.com/user-authentication-mean-stack/ as a guide.
I'm a novice when it comes to webdev, so I'm having trouble searching the right thing to fix my problem. The issue is when I try to register a new user my object isn't getting received in my api controller.
register.controller.js
(function () {
angular
.module('misplaced')
.controller('registerCtrl', registerCtrl);
registerCtrl.$inject = ['$location', 'authentication'];
function registerCtrl($location, authentication) {
var vm = this;
vm.onSubmit = function () {
authentication
.register(vm.credentials)
.error(function(err){
alert(err);
})
.then(function(){
$location.path('profile');
});
};
authentication.service.js
(function () {
angular
.module('misplaced')
.service('authentication', authentication);
authentication.$inject = ['$http', '$window'];
function authentication ($http, $window) {
register = function(user) {
return $http.post('/api/register', user).success(function(data){
saveToken(data.token);
});
};
authentication.js
module.exports.register = function(req, res) {
var user = new User();
user.name = req.body.name;
user.email = req.body.email;
user.setPassword(req.body.password);
user.save(function(err) {
var token;
token = user.generateJwt();
res.status(200);
res.json({
"token" : token
});
});
};
Through some console.log I've tracked that the object gets created fine from the register.controller and gets passed to authentication.service fine, but when I try to console.log the object in authentication.js file it's empty. Can someone help explain to me what might be happening? Thanks in advance!
This sounds like an Express configuration issue, you may not be using the bodyParser module in Express.
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
This will allow your middleware to access the request body properties in req.body
Related
I'm trying to build an API that receives a POST req to create a user but I am getting undefined errors for all of my req.body requests. My app is set up like this (simplified for brevity):
User controller that gets called by Express Router in my user routes file
/controllers/user.js
userController.addUser = function(req, res) {
let user = new User();
user.username = req.body.username;
user.first_name = req.body.first_name;
user.last_name = req.body.last_name;
user.email = req.body.email;
user.type = req.body.user_type
// This returns undefined as does all other req.body keys
console.log("REQ.BODY.EMAIL IS: " + req.body.email);
}
User Route File:
/routes/user.js - requires user controller above
router.post('/user/create', userController.addUser);
Main App:
all routes and controllers work per my tests except where req.body.* is used
index.js - main app file
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/api', routes);
I have looked through the Express documentation and through countless StackOverflow posts with no luck. Let me know if you need further clarification.
My issue was how I was sending the body to the API endpoint. I was using form-data instead of x-www-form-urlencoded with Postman. User error
Sometime with change in version body-parser seems to not work, in that case just use following, this will remove dependency from body-parser:
router.post('/user/create', (req, res, next) => {
let body = [];
req.on('error', (err) => {
console.error(err);
}).on('data', (chunk) => {
// Data is present in chunks without body-parser
body.push(chunk);
}).on('end', () => {
// Finally concat complete body and will get your input
body = Buffer.concat(body).toString();
console.log(body);
// Set body in req so next function can use
// body-parser is also doing something similar
req.body = body;
next();
});
}, userController.addUser);
I have a controller(login.controller.js):
var express = require('express');
var router = express.Router();
var request = require('request');
var config = require('config.json');
router.get('/', function (req, res) {
// log vendor out
delete req.session.token;
// move success message into local variable so it only appears once (single read)
var viewData = { success: req.session.success };
delete req.session.success;
res.render('login', viewData);
});
router.post('/', function (req, res) {
// authenticate using api to maintain clean separation between layers
request.post({
url: config.apiUrl + '/vendors/authenticate',
form: req.body,
json: true
}, function (error, response, body) {
if (error) {
return res.render('login', { error: 'An error occurred' });
}
if (!body.token) {
return res.render('login', { error: body, vendorname: req.body.vendorname });
}
// save JWT token in the session to make it available to the angular app
req.session.token = body.token;
// redirect to returnUrl
var returnUrl = req.query.returnUrl && decodeURIComponent(req.query.returnUrl) || '/';
res.redirect(returnUrl);
});
});
module.exports = router;
Where var request is working accessing Remote REST Api. Where as I have one service(vendor.service.js) which has $http not request. But $http is not working:
(function () {
'use strict';
angular
.module('app')
.factory('VendorService', Service);
function Service($http, $q) {
var service = {};
//Store
service.GetCurrent = GetCurrent;//st_details
return service;
function GetCurrent() {
return $http('http://localhost:3000/api/vendors/st_details').then(handleSuccess, handleError);
}
function handleSuccess(res) {
alert('hi3');
alert(res.data);
return res.data;
}
function handleError(res) {
alert('hi2');
alert(JSON.stringify(res));
return $q.reject(res.data);
}
}
})();
Can I use "var request = require('request');" in this vendor.service.js if yes how? Thanks a million in advance!
It seems like you are not using CORS, which you need to use in order to allow apps to access your API via $http.get
Follow the instructions on https://www.npmjs.com/package/cors to add CORS to your express application and it should work.
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});
});
I'm trying to create a Keen event from parse.com cloud code (node.js). I'm using a JS module (https://github.com/roycef/keen-parse) which seems to be set up OK. To test things, I've set up a simple test and here is the complete main.js (credentials removed):
var express = require('express');
var app = express();
// Global app configuration section
app.use(express.bodyParser());
var Keen = require('cloud/keen.js');
var keen = Keen.configure({
projectId: "xxxxxxxx",
writeKey: "xxxxxxxx"
});
app.get('/kiss', function (req, res) {
var resp = {};
var respCode = 404;
var testObj = {"firstname": "John", "surname": "Doe"};
// send single event to Keen IO
keen.addEvent("Testola", testObj, function (err, res) {
if (err) {
resp = err;
respCode = 500;
} else {
resp = res.data;
respCode = 200;
}
}).then(function () {
// send something back to the app
res.setHeader('Content-Type', 'application/json');
res.send(resp, respCode);
});
});
app.listen();
When I GET /kiss:
the record is stored in the relevant collection at Keen.io (yay - I can see it in the Expolorer!) however
the response received (err) is {"code": "UnknownError"}
So, 2 questions:
why is the error response being sent when the event seems to be recorded correctly at keen.io?
what can I do to get the above working?
It looks like keen-parse is using the old node-specific SDK for Keen. That SDK was deprecated quite a while ago, and I believe there have been some breaking changes in the API since then.
You probably want to use keen-js directly, instead. It's super simple to set up, and I don't think you really lose any functionality from keen-parse.
Give keen-tracking.js a try. This is a new tracking-only SDK that is a full drop-in replacement for keen-js. Here is a quick rewrite of your example code w/ the new SDK in place:
var express = require('express');
var app = express();
// Global app configuration section
app.use(express.bodyParser());
var Keen = require('keen-tracking');
var keen = new Keen({
projectId: "xxxxxxxx",
writeKey: "xxxxxxxx"
});
app.get('/kiss', function (req, res) {
var resp = {};
var respCode = 404;
var testObj = {"firstname": "John", "surname": "Doe"};
// send single event to Keen IO
keen.recordEvent("Testola", testObj, function (err, res) {
res.setHeader('Content-Type', 'application/json');
if (err) {
res.send(err, 500);
}
else {
res.send(res, 200);
}
});
});
app.listen();
I am learning Node.Js, I would like to understand how to interact between front-end / backend.
I would do backend --> Front End interaction by sendig data using app.get(), but now, I'd like to understand how can I get variable from Front End to Backend.
Front-ENd. (I want to pass varGetFromFrontend to backend)
<html>
<script>
var varGetFromFrontend = 2; // This is variable I want to pass to backend
</script>
<head>
<title>Home Page</title>
</head>
<body>
<h1> This is a test</h1>
</body>
</html>
On Node.Js (backend)
var express = require('express');
var app = new express();
app.use(express.json());
app.use(express.static(__dirname + '/public'));
var entries = [
{"id":1, "title":"Hello World!"},
{"id":2, "title":"Hello World!"}
{"id":3, "title":"Hello World!"}
{"id":4, "title":"Hello World!"}
];
if(entries.id == varGetFromFrontend){
console.log("This is to print a variable by choosing it from Front End")
console.log(varGetFromFrontend)
}
var port = Number(process.env.PORT || 5000);
app.listen(port);
I would like to know how can I print "varGetFromFrontend" on server side
Make an HTTP request to the server. Include the variable in the request.
There are lots of ways to do this:
Put it in a hidden input in a form, then submit the form.
or
Set location.href to a new value and include the variable in it (e.g. in a query string)
or
Use the XMLHttpRequest object to make an HTTP request
or
Create a script element and include the variable in the URL for the src attribute
(This is a non-exhaustive list)
You can interact with the nodejs server from the browser with socket.io
First, install socket.io:
npm install socket.io
and write these code to their respective filenames.
app.js:
var express = require("express");
var http = require("http");
var socketIO = require("socket.io");
var app = express();
app.get("/", function(req, res){
res.sendfile("./index.html");
});
var server = http.createServer(app);
var io = socketIO.listen(server, {log: false});
io.sockets.on("connection", function(socket){
socket.on("sendVar", function(value){
console.log("The value of the variable is " + value);
});
});
server.listen(5000);
index.html:
<html>
<head>
<title>Index Page</title>
</head>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
var variableFromFrontEnd = 2;
var socket = io.connect("/");
socket.on("connect", function(){
console.log("connected!")
socket.emit("sendVar", variableFromFrontEnd);
});
</script>
</html>
and run it.
Check out the MEAN framework I built: http://mean.wolframcreative.com/
This uses Node as the back-end server utilizing Express as the API router. The front-end uses angular and is purely an api consumption tool.
Short answer is this:
in angular:
$http
.get('/api/users/bobsaget')
.success(function (response) {
console.log(response);
});
in node(with express):
app.get('/api/users/:username', function (req, res) {
var variable = req.params.username;
//do logic here with the database(mongo) to get user info:
db.users.findOne({username: username}, function (error, response) {
if (!error) {
res.send(200, response);
} else {
res.send(500, {success: false, message: error.message});
}
});
)};
Long answer is to play around with my framework and get your hands dirty.
I'm currently working on a restful framework for node call snooze. I'm writing an api along side it and it's going very well. The framework is written to be modular and easy to use. Everything is built around modules, routes, controllers, services, and validators.
https://github.com/iamchairs/snooze
snooze.module('myServer', ['snooze-stdlib']) // inject the snooze-stdlib module
.route('get', '/users/:username', { // define the route
controller: 'UserCtrl', // what controller should handle this route
action: 'getUserByUsername', // what action to perform on this route
validator: 'GetUsername' // before processing this action what validation should occur
})
.controller('UserCtrl', function(User) { // inject the User service
return {
getUserByUsername: function(res, options) {
User.getUserByUsername(options.query.username).then(function(username) {
res.send(200, username);
}).fail(function(err) {
res.send(500, err);
});
}
};
})
.service('User', function($q) { // inject the $q service
return {
getUserByUsername: function() {
var deferred = $q.defer();
deferred.resolve('iamchairs');
return deferred.promise;
}
};
})
.validator('GetUsername', function($validator) { // inject the validator service
return function(deferred, req) {
if($validator.isLength(req.query.username, 2, 32)) {
deferred.resolve(); // resolve (valid request)
} else {
deferred.reject([400, 'Username must be between 2 and 32 characters']); // reject (invalid request)
}
}
});