I have an application node js using express for authentication via facebook but the url /auth/facebook/callback does not load.
Dependencies version:
Express: 4.13.3
Passport 0.3.0
Passport-facebook 2.0.0
app.js
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
passport.use(new FacebookStrategy({
clientID: '806175282757975',
clientSecret: '*************',
callbackURL: "http://localhost:3000/auth/facebook/callback"
},
function(accessToken, refreshToken, profile, done) {
process.nextTick(function () {
return done(null, profile);
});
}
));
app.use(function(req,res,next){
req.passport = passport;
next();
});
app.use('/', routes);
app.use('/users', users);
module.exports = app;
routes/index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/auth/facebook', function(req, res, next){
req.passport.authenticate('facebook')(req, res, next);
});
router.get('/auth/facebook/callback', function(req, res, next){
req.passport.authenticate('facebook', { successRedirect: '/',
failureRedirect: '/login' });
});
module.exports = router;
No error is returned on console.
In routes/index.js in /auth/facebook/callback route you forgot about calling authenticate method with req, res, next arguments. That is why your application was stuck ('next' callback was never called).
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/auth/facebook', function(req, res, next){
req.passport.authenticate('facebook')(req, res, next);
});
router.get('/auth/facebook/callback', function(req, res, next){
req.passport.authenticate('facebook', {
successRedirect: '/',
failureRedirect: '/login' }
)(req, res, next); // missing function call
});
module.exports = router;
Related
I'm currently learning and a newbie to Node.js. I'm trying to build a simple REST API and currently getting an error 404 when try post to a particular route in postman to test if data has successfully been sent to Mongo db. I'm sure what i'm missing. I have double checked all my routes and they seem fine. It works when i make a get request and falls through when i make a post request.
This is my app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var Developer = require('./models/developers');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true}));
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use('/', indexRouter);
app.use('/users', usersRouter);
// Connect to DB
mongoose.connect('mongodb://127.0.0.1:27017');
// API Routes
var router = express.Router();
// Routes will be prefixed with /api
app.use('/api', router);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
// Test Route
router.get('/', function (req, res) {
res.json({message: 'Welcome to my simple API!'});
});
router.route('/developers')
.post(function (req, res) {
var developer = new Developer(); // New instance of sa developer
developer.firstName = req.body.firstName;
developer.lastName = req.body.lastName;
developer.jobTitle = req.body.jobTitle;
developer.save(function (err) {
if (err) {
res.send(err);
} else {
res.json('Developer was successfully fetched');
}
});
})
.get(function (req, res) {
Developer.find(function (err, developers) {
if (err) {
res.send(err);
} else
res.json(developers);
});
});
router.route('/developer/:developer_id')
.get(function (req, res) {
Developer.findById(res.params.developer_id, function (err, developer) {
if (err) {
res.send(err);
}
res.json(developer);
});
});
router.route('/developer/firstName/:firstName')
.get(function (req, res) {
Developer.find({firstName:res.params.firstName}, function (err, developer) {
if (err) {
res.send(err);
}
res.json(developer);
});
});
My model is developer.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var DevelopersSchema = new Schema({
firstName: String,
lastName: String,
jobTitle: String
});
module.exports = mongoose.model('Developers', DevelopersSchema);
To connect the database, instead of
mongoose.connect('mongodb://127.0.0.1:27017');
Use,
mongoose.connect('mongodb://127.0.0.1:27017/yourDatabaseName');
Check the doc.
Mongoose database connection require a database name in connect() method.
Your final app.js should be like,
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var Developer = require('./models/developers');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true}));
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use('/', indexRouter);
app.use('/users', usersRouter);
// Connect to DB
mongoose.connect('mongodb://127.0.0.1:27017/my_unique_data_base_name');
// API Routes
var router = express.Router();
// Routes will be prefixed with /api
app.use('/api', router);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
// Test Route
router.get('/', function (req, res) {
res.json({message: 'Welcome to my simple API!'});
});
router.route('/developers')
.post(function (req, res) {
var developer = new Developer(); // New instance of sa developer
developer.firstName = req.body.firstName;
developer.lastName = req.body.lastName;
developer.jobTitle = req.body.jobTitle;
developer.save(function (err) {
if (err) {
res.send(err);
} else {
res.json('Developer was successfully fetched');
}
});
})
.get(function (req, res) {
Developer.find(function (err, developers) {
if (err) {
res.send(err);
} else
res.json(developers);
});
});
router.route('/developer/:developer_id')
.get(function (req, res) {
Developer.findById(res.params.developer_id, function (err, developer) {
if (err) {
res.send(err);
}
res.json(developer);
});
});
router.route('/developer/firstName/:firstName')
.get(function (req, res) {
Developer.find({firstName:res.params.firstName}, function (err, developer) {
if (err) {
res.send(err);
}
res.json(developer);
});
});
if I'm correct, the line of app.use('/api', router); does nothing.
When coming a request for /api endpoint, a response should be sent at the end of operations. The code pass the request to router. And router does nothing.
Then if createError(404) method calls res.send() or res.end() methods
you should move the use() method to the bottom of your code page:
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
Because at every single time it works before the other routes.
IMHO, using a standard coding style make more readable the program-flow.
Good luck..
I'm using React Router with Passport.js to set up Facebook login. I've set up the express routes and passport config, but every time I hit the
<a href="/api/auth/facebook"> link on my client side, it makes a request to RR because of my express app with this line:
app.get('/*', function(req, res) {
res.sendFile(path.resolve(__dirname, '../client', 'build', 'index.html'))
});
As I am making a call to the server side route, it returns this error:
Warning: [react-router] Location "/api/auth/facebook" did not match any routes
How can I bypass React Router for this one particular route?
my user_routes.js file looks like:
'user strict';
var bodyparser = require('body-parser');
var User = require('../models/User.js');
module.exports = function loadUserRoutes(router, passport) {
router.use(bodyparser.json());
router.get('/auth/facebook', passport.authenticate('facebook', {
session: false,
successRedirect: '/chat',
failureRedirect: '/'
}));
router.get('/auth/facebook/callback', passport.authenticate('facebook', {
session: false,
successRedirect: '/chat',
failureRedirect: '/'
}));
router.post('/sign_up', passport.authenticate('local-signup', { session: false}), function(req, res) {
res.json(req.user);
});
router.post('/sign_in', passport.authenticate('local-login', { session: false}), function(req, res) {
res.json(req.user);
});
router.get('/signout', function(req, res) {
req.logout();
res.end();
});
//get auth credentials from server
router.get('/load_auth_into_state', function(req, res) {
res.json(req.user);
});
// get usernames for validating whether a username is available
router.get('/all_usernames', function(req, res) {
User.find({'local.username': { $exists: true } }, {'local.username': 1, _id:0}, function(err, data) {
if(err) {
console.log(err);
return res.status(500).json({msg: 'internal server error'});
}
res.json(data);
});
})
};
In express routes are matches in the order they get defined.
So before your /* route you need something to handle api requests.
app.get('/api/auth/facebook', passport.authenticate('facebook'))
app.get('/*', function(req, res) {
res.sendFile(path.resolve(__dirname, '../client', 'build', 'index.html'))
});
I am using passport.js for a basic log in/log out system. For some reason, the router.get('/signout', function(req, res)) is not being called when I run http://localhost:3000/auth/signout on Advanced rest client. Instead I am getting a Internal Server Error: 500. Login works just fine, but signout does not. Here is my app.js and authenticate.js:
App.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var passport = require('passport');
var session = require('express-session');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//Initialize models
require('./models/models.js');
var api = require('./routes/api');
var authenticate = require('./routes/authenticate')(passport);
var mongoose = require('mongoose');
//connect to mongodb
mongoose.connect("mongodb://localhost:27017/chirp-test");
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(session({
secret: 'super duper secret'
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.session()); //This creates a unique has for our session
//Initialize Passport
var initPassport = require('./passport-init');
initPassport(passport);
app.use('/auth', authenticate);
app.use('/api', api);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
Authenticate.js
var express = require('express');
var router = express.Router();
module.exports = function(passport){
//sends successful login state back to angular
router.post('/success', function(req, res){
console.log('successful');
res.send({state: 'success', user: req.user ? req.user : null});
});
//sends failure login state back to angular
router.get('/failure', function(req, res){
res.send({state: 'failure', user: null, message: "Invalid username or password"});
});
//log in
router.post('/login', passport.authenticate('login', { failureRedirect: '/auth/failure' }),
function(req, res) {
//res.redirect('/auth/success');
res.send({state: 'success', user: req.user ? req.user : null});
});
//sign up
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failure'
}));
//log out
router.get('/signout', function(req, res) {
console.log('Signing out...');
req.logout();
res.redirect('/');
});
return router;
}
You have registered nothing under "/". So when "auth/logout" call redirect to redirect("/"), I guess client is redirected but goes into your "error handler" which sends a 500 error...
I'm trying to call the passport.authenticate function as response to post request for my registration view. I've been following this tutorial here to get my head around passport.js and express but having completed the first page of instructions and making the necessary changes for express.js 4.0 every page I try to access returns error 500 and displays the following stacktrace:
TypeError: Object #<serverResponse> has no method 'authenticate'
at module.exports (/home/myUserName/Desktop/manufacturing/routes/index.js:66:37)
at Layer.handle [as handle_request] (/home/myUserName/Desktop/manufacturing/node_modules/express/lib/router/layer.js:82:5)
at trim_prefix (/home/myUserName/Desktop/manufacturing/node_modules/express/lib/router/index.js:302:13)
at /home/myUserName/Desktop/manufacturing/node_modules/express/lib/router/index.js:270:7
at Function.proto.process_params (/home/myUserName/Desktop/manufacturing/node_modules/express/lib/router/index.js:321:12)
at next (/home/myUserName/Desktop/manufacturing/node_modules/express/lib/router/index.js:261:10)
at /home/myUserName/Desktop/manufacturing/node_modules/connect-flash/lib/flash.js:21:5
at Layer.handle [as handle_request] (/home/myUserName/Desktop/manufacturing/node_modules/express/lib/router/layer.js:82:5)
at trim_prefix (/home/myUserName/Desktop/manufacturing/node_modules/express/lib/router/index.js:302:13)
at /home/myUserName/Desktop/manufacturing/node_modules/express/lib/router/index.js:270:7
Here is the code for /routes/index.js:
var express = require('express');
var bodyParser = require('body-parser');
var router = express.Router();
module.exports = function(app, passport) {
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', {
title: 'Home Page'
});
});
/* GET about page */
router.get('/about', function(req, res, next) {
res.render('about', {
title: 'About Us'
});
});
/* GET contact page */
router.get('/contact', function(req, res, next) {
res.render('contact', {
title: 'Contact Us'
});
});
/* GET login page */
router.get('/login', function(req, res, next) {
res.render('login', {
title: 'User Login',
message: req.flash('loginMessage')
});
});
/* GET register page */
router.get('/register', function(req, res, next) {
res.render('register', {
title: 'User Registration',
message: req.flash('signupMessage')
});
});
/* POST register page */
router.post('/register', passport.authenticate('local', {
successRedirect : '/',
failureRedirect : '/register',
failureFlash : true
}));
/* Log Out */
router.get('/logout', function(req, res, next) {
req.logout();
res.redirect('/');
});
/* 404 - page not found */
router.get('*', function(req, res){
res.render('404', {
title: '404 - Not Found'
});
});
// Route middleware to make sure a user is logged in
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
};
};
And here is my server.js:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var passport = require('passport');
var flash = require('connect-flash');
// Database
var configDB = require('./config/database.js');
mongoose.connect(configDB.url);
require('./config/passport')(passport);
// Routes
var routes = require('./routes/index');
var port = process.env.PORT || 3000;
var app = express();
// Express configuration
app.use(logger('dev')); // log every request to console
app.use(bodyParser.json()); // get information from html forms
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser()); // read cookies (needed for auth)
app.use(express.static(path.join(__dirname, 'public')));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
if (app.get('env') === 'development') {
app.locals.pretty = true;
}
// Passport configuration
app.use(session({ secret: 'MySecretHere',
saveUninitialized: true,
resave: true})); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
app.use('/', routes);
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
app.listen(port);
console.log('Server running on ' + port);
The reason your are getting the error is because your exporting a function that takes app and passport as a parameters for your http handlers, but when your require it in your server.js your are not passing passport or app.
You need to somehow pass passport into the require.
You could change your routes files to
If your are using the express.Router
var router = express.Router();
module.exports = function(passport) {
// init your routes with passport and router
router.post('/' function(req, res) {
//...
});
// make sure to return router in the function though
return router;
}
If not using express.Router you could pass both app and passport and simply attach handlers to app
module.exports = function (app, passport) {
app.post('/', function(req, res) {
//...
});
// no need to return app
}
then in server.js
// if your using `express.Router()` in routes file
app.use('/', require('./routes')(passport));
// If your registering handler on app itself just bootstrap it
require('./routes')(app, passport);
You need to pass passport to your route. You can do it changing your code this way:
/routes/index.js
from module.exports = function(app, passport) {...}
to
module.exports = function(passport){ return function(app) {...}}
/server.js
from app.use('/', routes);
to app.use('/', routes(passport));
I'm trying to do twitter oauth in nodejs using passportjs but getting error
Cannot GET /auth/twitter/callback?oauth_token=alksdkalsjdsjd23232378skjdfjsdhf&oauth_verifier=234jjh23j4k234k23h4j2h342k34hj
Here is my node js code
var express = require('express')
, passport = require('passport')
, util = require('util')
, GoogleStrategy = require('passport-google').Strategy
, TwitterStrategy = require('passport-twitter').Strategy;
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
passport.use(new TwitterStrategy({
consumerKey: 'xxxxxxxxxxxxxxxxxxxx',
consumerSecret: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
callbackURL: 'http://127.0.0.1:3000/auth/twitter/callback'
},
function(token, tokenSecret, profile, done) {
process.nextTick(function () {
return done(null, profile);
});
}
));
var app = express();
// configure Express
app.configure(function() {
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({ secret: 'keyboard cat' }));
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(__dirname + '/../../public'));
});
app.get('/', function(req, res){
res.render('index', { user: req.user });
});
app.get('/login', function(req, res){
res.sendfile('./views/auth.html');
});
app.get('/auth/twitter', passport.authenticate('twitter'));
app.get('auth/twitter/callback',
passport.authenticate('twitter', { successRedirect: '/success',
failureRedirect: '/login' }));
app.get('/success', function(req, res){
res.send("success logged in");
});
app.listen(process.env.PORT || 3000);
EDIT
There is missing / in auth/twitter/callback route definition.
Also for the routers /auth/twitter and auth/twitter/callback, passport.authenticate() as middleware will do the authentication, and you should have route handling functions.
So the definition of your routes should look something like:
app.get('/auth/twitter',
passport.authenticate('twitter'),
function(req, res) {}); // empty route handler function, it won't be triggered
app.get('/auth/twitter/callback',
passport.authenticate('twitter', {
successRedirect: '/success',
failureRedirect: '/login' }),
function(req, res) {}); // route handler
You don't need the empty route handler function(req, res) {} - you can just leave the argument out and express will understand you don't plan on ever using the handler