Things are sort of working but, for some reason, I can't get the user_id into the URL, all I get is a literal ":user_id" like so:
here is the code in the my users.js route file
var main = require('../main');
exports.getAllUsers = function(req, res) {
var db = main.db();
db.collection('users').find().toArray(function(err, items) {
res.json(items);
});
};
exports.routeUserToTheirHome = function(req, res, next) {
res.json(req.user);
};
and here is the code in my main.js file:
app.param('user_id', function(req, res, next, user_id) {
// typically we might sanity check that user_id is of the right format
User.find(user_id, function(err, user) {
if (err) {
return next(err);
}
if (!user) {
return new Error("no user matched");
}
req.user = user;
next();
});
});
app.use('/users/:user_id/home', users.routeUserToTheirHome);
exports.routeUserToTheirHome = function(req, res, next) {
req.user.user_id = req.params.user_id;
res.json(req.user);
};
I figured out what the problem was, it was that I had this:
app.post('/login', passport.authenticate('local', {
successRedirect : 'users/:user_id/home',
failureRedirect : '/login',
failureFlash : true
}), function(req, res, next) {
next();
});
when in fact, I needed this:
app.post('/login', passport.authenticate('local', {
successRedirect : 'users/' + '5464370621a2569c18880876' +'/home',
failureRedirect : '/login',
failureFlash : true
}), function(req, res, next) {
next();
});
clearly I don't know what I am doing. The question now is, where do I get the user_id from, instead of hardcoding it?
here is the solution:
app.post('/login', passport.authenticate('local', {
failureRedirect : '/login',
failureFlash : true
}), function(req, res, next) {
res.redirect('users/' + req.user._id +'/home');
next();
});
Related
i'm trying to put passport logic in controllers file but the problem is when i put the logic inside the controllers it's tell me "Cannot read property 'body' of undefined" but when i move the code to the index routes everything goes right
index.js/controller the problem is in " postLogin "
const User = require('../models/user');
const passport = require('passport');
module.exports = {
async postRegister(req, res, next) {
const newUser = new User({
username: req.body.username,
email: req.body.email,
image: req.body.image
})
await User.register( newUser , req.body.password);
res.redirect('/');
},
postLogin(req, res, next) {
passport.authenticate('local', { successRedirect: '/' ,failureRedirect: '/login' })();
}
}
index.js/routes
const express = require('express');
const router = express.Router();
const { postRegister, postLogin } = require('../controllers/index');
const { errorHandler } = require('../middleware/index');
/* GET home page. */
router.get('/', (req, res, next) => {
res.render('index', { title: 'Surf Shop - Home' });
});
/* User routs */
//Get register
router.get('/register', (req, res, next) => {res.send('/register')});
//POST register
router.post('/register', errorHandler(postRegister));
//Get login
router.get('/login', (req, res, next) => { res.send('GET /Login') });
//POST login
router.post('/login', postLogin);
module.exports = router;
image form postman
Are the brackets intentional at the end of:
passport.authenticate('local', { successRedirect: '/' ,failureRedirect: '/login' })() <----
Issue with parameters not being passed?
router.post('/login', postLogin);
Becomes:
router.post('/login', () => {
postLogin(req, res, next)
});
Correct resolve:
Very helpful but the parameters not being passed here
passport.authenticate('local', { successRedirect: '/' ,failureRedirect: '/login' })(here)
So becomes
`passport.authenticate('local', { successRedirect: '/' ,failureRedirect: '/login' })(req, res, next)`
Online authentication of GitHub is not working. I've registered the new app in GitHub and still the application won't redirect to OAuth.
The following code I've written and getting Error:Unknown authentication strategy "github"
const passport = require('passport');
const bcrypt = require('bcrypt');
module.exports = function (app, db) {
app.route('/')
.get((req, res) => {
res.render(process.cwd()+'/views/pug/index', {title: 'Hello', message: 'Please login',showLogin: true, showRegistration: true});
});
app.route('/login')
.post(passport.authenticate('local',{ failureRedirect: '/' }),(req,res)=>{
res.redirect('/profile');
});
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/');
}
app.route('/profile')
.get(ensureAuthenticated, (req,res) => {
res.render(process.cwd() + '/views/pug/profile',{username:req.user.username});
});
app.route('/logout')
.get((req, res) => {
req.logout();
res.redirect('/');
});
app.route('/register')
.post((req, res, next) => {
var hash = bcrypt.hashSync(req.body.password, 12);
db.collection('users').findOne({ username: req.body.username }, function (err, user) {
if(err) {
next(err);
} else if (user) {
res.redirect('/');
} else {
db.collection('users').insertOne(
{username: req.body.username,
password: hash},
(err, doc) => {
if(err) {
res.redirect('/');
} else {
next(null, user);
}
}
)
}
})},
passport.authenticate('local', { failureRedirect: '/' }),
(req, res, next) => {
res.redirect('/profile');
}
);
/*GitHub OAuth*/
app.route('/auth/github')
.get(passport.authenticate('github'));
app.route('/auth/github/callback')
.get(passport.authenticate('github', { failureRedirect: '/' }), (req,res) => {
res.redirect('/profile');
});
/*End of GitHub OAuth*/
app.use((req, res, next) => {
res.status(404)
.type('text')
.send('Not Found');
});
}
It seems I have missing something or anything else for OAuth. The strategy wasn't defined in my side I just accessing default strategy for GitHub.
You have to configure passport github strategy in your script. https://github.com/jaredhanson/passport-github
var GitHubStrategy = require('passport-github').Strategy;
passport.use(new GitHubStrategy({
clientID: GITHUB_CLIENT_ID,
clientSecret: GITHUB_CLIENT_SECRET,
callbackURL: "http://127.0.0.1:3000/auth/github/callback"
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({ githubId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
I have started developing little project where I have React with Redux on the client side, and the backend is being done with Node, Express and Passport.js
I will try to describe best What I am struggling with for some hours.
after authentication, when user is being send from server to client, field req.session.passport is set, along with req.user. but when i do next request, no matter is it logout or for example /something/add these fields are undefined.
when authenticating, serializeUser is being called, but deserializeUser not and i dont think it should here, maybe im wrong. as far as I went into debugging the problem, req.login is being called too.
on the next requests it seems that passport isnt doing anything, and i'm out of ideas and anwsers from SO and google. i didnt try the custom callback.
req.session just before sending anwser to client looks like:
Session {
cookie:
{ path: '/',
_expires: 2017-01-11T02:31:49.235Z,
originalMaxAge: 14400000,
httpOnly: false,
secure: false } }
the code on the server side is:
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
global.Models.User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use(new LocalStrategy(
{
usernameField: 'login',
passwordField: 'password',
passReqToCallback: true
},
function(req, login, password, done) {
global.Models.User.logIn({login: login, password: password}, function(err, user){
if(err){
done(err);
}
else{
done(null, user);
}
});
}
));
var app = express();
var router = express.Router();
router.use(cookieParser());
router.use(bodyParser.urlencoded({extended: false}));
router.use(bodyParser.json());
router.use(session({
cookie : {
secure : false,
maxAge : (4 * 60 * 60 * 1000),
httpOnly: false
},
secret: this._config.session.secret,
resave: false,
saveUninitialized: true
}));
router.use(passport.initialize());
router.use(passport.session());
require('./Router')();
app.use(router);
session object here is the express-session. code under is the Router.js required above
var User = require('../Models/User');
var News = require('../Models/News');
var passport = global.Application.getInstanceOf("passport");
function setRoutes(){
router.use(function (req, res, next) {
var log = global.Application.getInstanceOf("logger");
var clientIP = req.headers['x-forwarded-for'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress;
log.log("info", req.method + " request from ip: " + clientIP);
res.header('Access-Control-Allow-Origin', 'http://localhost:8080');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
if('OPTIONS' == req.method){
res.sendStatus(200);
}
else{
next();
}
});
router.get('/ping', function(req, res){
res.send('ping');
});
router.get('/login/:login', (req, res) => {
Database.client.query(Database.queries.USER_LOGIN, {login: req.params.login}, {useArray: true},
(err, rows) => {
if(err){
res.send({error: "ERROR_DATABASE"});
}
else{
res.send(rows[0][0]);
}
});
});
router.post('/login', passport.authenticate('local', {session: true}),
function(req, res){
console.log(req.session);
req.session.save();
res.send(req.user);
}
);
router.post('/register', (req, res) => {
User.create(req.body, (err, result) => {
if(err){
res.send({error: "ERROR_DATABASE"});
}
res.send(result);
});
});
router.get('/logout', function(req, res){
console.log(req.session);
req.logout();
res.sendStatus(200);
});
router.post('/cms/article', isAuthenticated, (req, res) => {
res.send("BLA");
});
function isAuthenticated(req, res, next){
console.log(req.user);
console.log(req.session);
console.log(req.session.passport);
if(req.isAuthenticated()){
next();
}
else{
res.send("OK");
}
}
}
module.exports = setRoutes;
I have solved the problem.
Explanation:
Cookie was being sent by express to client, but it wasn't saved. For that, it needed change from using $.post to $.ajax with xhrFields option set to {withCredentials: true}.
Aside from that, the problem could also be that, that cookieParser probably need to know cookie secret too now.
In my app.js I do this
app.use(function(req, res, next){
if(!req.user){
return res.redirect('/login_');
}
next();
})
I don't see anything wrong and in route/index.js I do
router.get('/login_', function(req, res) {
res.render('login', { user : req.user });
});
But I got an error. I know this is caused by the request is not ended but what's wrong with my code above? clueless with this error.
Full code of route/index.js
var express = require('express');
var passport = require('passport');
var Account = require('../models/account');
var router = express.Router();
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/uploads')
}
})
var upload = multer({ storage: storage })
var Photo = require('../models/photos');
router.get('/', function(req, res, next) {
if(req.user){
res.redirect('/'+req.user.username+'/screen');
}else{
res.redirect('/login_');
}
});
router.get('/:username/screen', function(req, res, next) {
res.render('screen', { user : req.user });
});
router.get('/:username', function(req, res, next) {
var excludes = ["/login_", "/register_","/logout_"];
if (excludes.indexOf(req.originalUrl) > -1){
return next();
}else{
res.render('upload_photo');
}
});
router.post('/:username', upload.any(), function(req, res, next) {
var excludes = ["/login_", "/register_","/logout_"];
if (excludes.indexOf(req.originalUrl) > -1){
return next();
}else{
var photo = new Photo({
photo:req.files[0].filename,
caption:req.body.caption
});
photo.save(photo);
res.sendStatus(200);
}
});
router.get('/:username/manager', function(req, res, next) {
Photo.getAllPhotos(function(err,result){
var headers = req.headers.host;
var pathname = '128.199.128.108:3000';
if(headers.indexOf('localhost') > -1){
pathname = 'localhost:3000'
}
res.render('manager',{pathname:pathname,photos:result});
});
});
//* passport for register/login_ *//
router.get('/register_', function(req, res) {
res.render('register', { });
});
router.post('/register_', function(req, res) {
Account.register(new Account({ username : req.body.username }), req.body.password, function(err, account) {
if (err) {
return res.render('register', { account : account });
}
passport.authenticate('local')(req, res, function () {
res.redirect('/');
});
});
});
router.get('/login_', function(req, res) {
res.render('login', { user : req.user });
});
router.post('/login_', passport.authenticate('local'), function(req, res) {
res.redirect('/');
});
router.get('/logout_', function(req, res) {
req.logout();
res.redirect('/login_');
});
module.exports = router;
You are printing something before this line.
Either trace that, or instruct your server to cache some of the output to the user.
(if the server does not display anything to the user, headers can be sent, even if code tries to print something before)
However that is general knowledge, not familiar with node.js
Server side code:
var User = require("./models/user");
var express = require('express'),
app = express(),
Account = require("./models/account"),
mongoose = require('mongoose'),
passport = require("passport"),
basicAuth = require('basic-auth'),
bodyParser = require("body-parser"),
LocalStrategy = require("passport-local"),
passportLocalMongoose = require("passport-local-mongoose"); //libraries
mongoose.connect("mongodb://localhost/test");
app.set('view engine', 'ejs'); //using engine of ejs file
app.use(bodyParser.urlencoded({extended: true}));
app.use(require("express-session")({
secret: "kiss my ass",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(Account.authenticate()));
passport.serializeUser(Account.serializeUser());
passport.deserializeUser(Account.deserializeUser());
// AUTH Routes
//create account success
app.get('/success', function (req, res) {
res.render('success');
});
// deleteUser form
app.get("/delete", function(req, res, next) {
res.render("deleteuser");
});
app.get("/viewall", function(req, res, next) {
res.render("viewall");
});
//view all User form
app.get('/view', function (req, res) {
console.log('getting all user');
Account.find({})
.exec(function(err, results) {
if(err) {
res.send('error has occured');
}else{
console.log(results);
res.json(results);
}
});
});
app.get('/viewall/:id', function (req, res) {
console.log('getting one user');
Account.findOne({
_id:req.params.id
})
.exec(function(err, account) {
if(err) {
res.send('error occured');
}else{
console.log(account);
res.json(account);
}
})
})
// LOGIN for user
// render login form
app.get("/", function(req, res) {
res.render("login");
});
//login for user
//middleware
app.post("/login", passport.authenticate("local", {
successRedirect: "http://localhost:8082/viewImage.html",
failureRedirect: "http://localhost:8081/error"
}), function(req, res) {
});
//logout from basicauth
app.get('/logout', function (req, res) {
res.set('WWW-Authenticate', 'Basic realm=Authenticate Required');
return res.sendStatus(401);
// res.send("<a href='/login'>Show Users</a>");
});
//basicauth for admin login
var auth = function (req, res, next) {
function unauthorized(res) {
res.set('WWW-Authenticate', 'Basic realm=Authenticate Required');
return res.send(401);
};
var user = basicAuth(req);
if (!user || !user.name || !user.pass) {
return unauthorized(res);
};
if (user.name === 'admin' && user.pass === 'admin123') {
return next();
} else {
return unauthorized(res);
};
};
//LOGIN for admin
//render login form
app.get("/register", auth, function(req, res) {
res.render("register");
});
// register post
app.post("/register", function(req,res){
Account.register(new Account({username: req.body.username}), req.body.password, function(err, user){
if(err){
console.log(err);
return res.render('/register');
}
passport.authenticate("local")(req, res, function(){
res.redirect("/success");
});
});
});
app.listen(8081, function () {
console.log('ImageViewer listening on port 8081!');
});
JS code:
$scope.delete = function (data) {
if (confirm('Do you really want to delete?')){
$window.location.reload();
$http['delete']('/viewall/' + data._id).success(function() {
$scope.users.splice($scope.users.indexOf(data), 1);
});
}
};
html code:
<tr ng-repeat="user in users | filter:searchBox | orderBy:'+username'">
<td>{{user._id}}</td>
<td>{{user.username}}</td>
<td><button class="btn btn-primary" ng-click="delete(user)">Delete</button></td>
This is the error i got:
DELETE
XHR
http://localhost:8081/viewall/5784919136ccb93d0ba78d4b [HTTP/1.1 404 Not Found 8ms]
But when i run the url of http://localhost:8081/viewall/5784919136ccb93d0ba78d4b and it does give me the data:
{"_id":"5784919136ccb93d0ba78d4b","username":"qs","__v":0}
Anybody can help me? don't know what's with the error404 when i'm able to get the data.
You have no route for '/viewall/:id' with DELETE verb. So you should add route with DELETE verb. like
app.delete('/viewall/:id',function(req,res){
// rest of code here
// assume your model name Account
Account.remove({ _id: req.params.id },function(err,doc) {
if(err) {
return res.status(400).send({msg: 'Error occurred during delete account'});
}
return res.status(200).send({msg: 'Successfully deleted'});
});
}
and you should reload after success in your angular controller. like
$http['delete']('/viewall/' + data._id).then(function(response) {
$scope.users.splice($scope.users.indexOf(data), 1);
$window.location.reload();
});