So, I've been struggling with these for a couple of hours now. The session won't get sent to server when I use AJAX to POST something to the server, but it works fine without AJAX, like clicking links, logout, etc and this is makes me pulling my hair in frustration. Anyway, these are my codes:
var express = require('express'), // express 4
mongoskin = require('mongoskin'),
Busboy = require('busboy'),
cookieParser = require('cookie-parser'),
session = require('express-session'),
mailer = require('nodemailer'),
compress = require('compression'),
morgan = require('morgan'),
ect = require('ect'),
suspend = require('suspend'),
MongoStore = require('connect-mongo')(session);
app.use(compress());
app.engine('.ect', renderer.render);
app.set('env', 'development');
app.use(express.static(__dirname + '/public'));
app.use(cookieParser());
app.use('/admin', session({
secret : 'qlauwork secret yo',
name : 'qlauworks.sess',
proxy : true,
rolling : true,
cookie : {
maxAge : 1000 * 60 * 60 * 6
},
store : new MongoStore({
db : 'qlauworks',
auto_reconnect : true,
defaultExpirationTime : 1000 * 60 * 60 * 6
}),
unset : 'destroy'
}));
// ... etc etc
app.post('/admin/login', function (req, res) {
var msg = {};
var busboy = new Busboy({ headers : req.headers });
busboy.on('field', function (fieldName, val) {
msg[fieldName] = val;
});
busboy.on('finish', function () {
suspend.run(function * () {
msg.password = crypto.createHash('whirlpool').update(SALT).update(msg.password).digest('hex');
var user = yield db.users.findOne({ username : msg.username, password : msg.password }, suspend.resume());
if (!user) {
return res.json({ error : 'Wrong username or password' });
}
// create session token
var token = yield crypto.randomBytes(32, suspend.resume());
token = token.toString('hex');
yield db.users.update({ username : msg.username }, { $set : { token : token } }, { upsert : true }, suspend.resume());
req.session.token = token;
res.redirect('/admin/forms');
}, function (err) {
if (err) {
console.log('login: ', err);
res.send('Server error');
}
});
});
req.pipe(busboy);
});
// this is the logout and forms, works just fine
app.get('/admin/logout', auth, function (req, res) {
suspend.run(function * () {
var token = req.session.token;
yield db.users.update({ token : token }, { $unset : { token : true } }, suspend.resume());
delete req.session.token;
req.session.destroy(function (err) {
if (!err) {
res.clearCookie('qlauworks.sess', { path : '/' });
res.redirect('/admin');
}
});
}, function (err) {
if (err) {
console.log('logout: ', err);
res.json({ error : 'Server error' });
}
});
});
app.get('/admin/forms', auth, function (req, res) {
res.send(formPage);
});
// and this is the auth middleware, could logout and moving around the admin page
// but req.session always undefined if comes from an AJAX request
function auth (req, res, next) {
suspend.run(function * () {
console.log(req.session);
console.log('=====================================================')
if (!req.session.token) {
return res.json({ error : 'Invalid token' });
}
var user = yield db.users.findOne({ token : req.session.token }, suspend.resume());
if (!user.username) {
return res.json({ error : 'Invalid token' });
}
next();
}, function (err) {
if (err) {
console.log('auth: ', err);
res.json({ error : 'Server error' });
}
});
}
and this is the client side
$.post('/api/item/new', elem, function (rep) {
thisForm.find('input[type="submit"]').attr('disabled', false);
if (rep.error) {
$('#alert-multi').removeClass('success').addClass('alert').text(rep.error);
} else {
$('#alert-multi').removeClass('alert').addClass('success').text('Success');
$('input[type="reset"]').click();
for (var i = 0; i < len; i++) {
$('#preview-multi' + i).attr('src', '');
$('#multi' + i).attr('data-image-src', '');
}
}
});
So, how do I solve this?
It looks like you mounted the session middleware on /admin but you're trying to call /api/item/view.
That won't work as using express.use(path, middleware) will invoke middleware only for requests whose req.url contains path.
Either mount the session middleware on / (by not using path parameter - simple express.use(middleware) will do), or change your ajax url to start with /admin (probably not something you want to do).
Related
I'm trying to develop api with node.js express api for my angular web front end.This code worked when I used the params (http://localhost:5000/login/admin/00606006350066500673 ).
But I don't know why I'm getting an error while using the Request raw body data ({ strUserID: "admin" , strUserPwd: "00606006350066500673"})
router.post('/login', function (req, res, next) {
let User = {
strUserID : req.body.strUserID,
strUserPwd : req.body.strUserPwd };
function getUserPwd(strUID){
var sqlConfig = {
user: 'sa',
password: 'XXXXX',
server: 'XXXXXXXXXXXXXX.us-east-2.rds.amazonaws.com',
database: 'XXXXX'
};
sql.connect(sqlConfig, function () {
var request = new sql.Request();
var strquery = "select fUserPwd from tblUser where fUserID ='"+User.strUserID+"'"
request.query(strquery, function (err, recordset) {
return(recordset);
});
sql.close();
});
}
if ( User.strUserPwd == getUserPwd(User.strUserID)) {
let token = jwt.sign(User, global.config.secretKey, {
algorithm: global.config.algorithm,
expiresIn: '15m'
});
console.log("Token Generated : "+ token + User );
res.status(200).json({
token , User
});
}
else {
res.status(401).json({
message: 'Login Failed'
});
}
});
I am making an iOS project which uses Stripe. I am using a STPCustomerContext and the parameter to create an instance is an object of MainAPI below. When I create the instance, it automatically calls createCustomerKey() but an error (404) is throwing. The URL is "http://localhost:1337/ephemeral_keys" and I believe that is what I have everywhere but yet it is throwing a 404. Here is the code for MainAPI.swift, index.js, & api.js.
The code is:
MainAPI.swift
class MainAPI:NSObject, STPEphemeralKeyProvider {
// override init(){}
static let shared = MainAPI()
var baseURLString = Constants.BASE_URL
// MARK: STPEphemeralKeyProvider
enum CustomerKeyError: Error {
case missingBaseURL
case invalidResponse
}
func createCustomerKey(withAPIVersion apiVersion: String, completion: #escaping STPJSONResponseCompletionBlock) {
// the request
func request(id: String) {
print("creating a eph key request with customerId: \(id)") // good
let url = self.baseURLString.appending("/ephemeral_keys")
Alamofire.request(url, method: .post, parameters: [
"api_version": apiVersion,
"customerId": id
])
.validate(statusCode: 200..<300)
.responseJSON { responseJSON in
switch responseJSON.result {
case .success(let json):
print("created customer ephemeral key!")
completion(json as? [String: AnyObject], nil)
case .failure(let error):
print("could not customer ephemeral key!\n Error info: ")
print(error.localizedDescription)
completion(nil, error)
}
}
}
print("attempting to create customer ephemeral key . . .(createCustomerKey())")
let customerId = . . . // get customer id
request(id: costumerId) // this passes on the CORRECT customerId each time
}
}
api.js
var express = require('express')
var router = express.Router()
var stripe_key = process.env.STRIPE_KEY || "sk_test_myTestKey"
var stripe = require('stripe')(stripe_key);
var request = require("request-promise-native")
//API
router.get('/', function (req, res) {
res.status(200).send(JSON.stringify({ message: 'API Gateway', success: true, error: null }));
}) // Just for testing, just for error-handling
//1. Create a customer account
router.post('/new_customer', function (req, res) {
console.log("Creating new customer account...")
var body = req.body
stripe.customers.create({ email: body.email, })
.then((customer) => {
console.log(customer)
// Send customerId -> Save this for later use
res.status(200).send(JSON.stringify({ success: true, error: null, customerId: customer.id }));
})
.catch((err) => {
console.log(err)
res.status(400).send(JSON.stringify({ success: false, error: err }))
});
})
//2. Save Credit Card with token
router.post('/new_card', function (req, res) {
var customerId = req.body.customerId
var token = req.body.token
stripe.customers.update(customerId, { source: token })
.then((customer) => {
console.log(customer)
res.status(200).send(JSON.stringify({ success: true, error: null }));
})
.catch((err) => {
console.log(err)
res.status(400).send(JSON.stringify({ success: false, error: err }))
});
})
//3. Use customerId to post a charge
router.post('/new_charge', function (req, res) {
var customerId = req.body.customerId
var amount = req.body.amount
var source = req.body.source
stripe.charges.create({
amount: amount, //in cents
currency: "usd",
customer: customerId, //CUSTOMER_STRIPE_ACCOUNT_ID
source: source, // obtained with Stripe.js
}).then((charge) => {
res.status(200).send(JSON.stringify({ message: 'Sucess.', success: true, error: null }));
}).catch((error) =>{
res.status(400).send(JSON.stringify({ message: 'Error', success: false, error: error }));
})
})
// here is the error I am assuming
router.post('/ephemeral_keys', (req, res) => {
const stripe_version = req.body.api_version;
var customerId = req.body.customerId;
if (!stripe_version) {
res.status(400).end();
return;
}
console.log(stripe_version)
// This function assumes that some previous middleware has determined the
// correct customerId for the session and saved it on the request object.
stripe.ephemeralKeys.create(
{customer: customerId},
{stripe_version: stripe_version}
).then((key) => {
console.log("Ephemeral key: " + key)
res.status(200).json(key);
res.status(200).send(JSON.stringify({ message: 'AAAAhh', success: true, error: null }));
}).catch((err) => {
console.log("Ephemeral key error: " + err)
res.status(200).send(JSON.stringify({ message: 'ABBBBBB', success: true, error: null }));
res.status(500).end();
});
});
module.exports = router;
index.js
//Environment Vars
var uri = process.env.NODE_ENV || "development"
console.log(uri + " environment")
//Express App
var express = require('express');
var app = express();
//Api for reading http post request body in express
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json())
//Log Connections
app.use(function timeLog (req, res, next) {
console.log('incoming connection . . . ')
next()
})
//API middelware
var api = require('./api')
app.use('/api', api)
app.get('/', function (req, res) {
res.status(200).send(JSON.stringify({ message: 'Welcome!', success: true, error: null }));
});
//Create Server
var port = process.env.PORT || 1337;
var httpServer = require('http').createServer(app);
httpServer.listen(port, function () {
console.log('server running on port ' + port + '.');
});
When I create a STPCustomerContext (like this):
let apiKeyObject = MainAPI.shared
customerContext = STPCustomerContext(keyProvider: apiKeyObject)
The following error prints (not allowing the STPPaymentContext later to display):
Response status code was unacceptable: 404.
Please try with the below nodejs code, because syntax which your code is using might not be correct, I was using the same code as you, but later changed the implementation & deployed to firebase CLI
exports.createEphemeralKeys = functions.https.onRequest((req, res) => {
var api_version = req.body.api_version;
var customerId = req.body.customerId;
if (!api_version) {
res.status(400).end();
return;
}
stripe.ephemeralKeys.create(
{ customer: customerId },
{ stripe_version: api_version },
function(err, key) {
return res.send(key);
});
});
You might get below kind of logs.
{
id: 'ephkey_1BramAFjruqsvjkVQGdZLiV5',
object: 'ephemeral_key',
associated_objects: [ { type: 'customer', id: 'cus_CEPMtLbshv7EaP' } ],
created: 1517701830,
expires: 1517705430,
livemode: false,
secret: 'ek_test_YWNjdF8xQmxUb0FGanJ1cXN2amtWLHVPcUdMN3d4UEhncW1sQkNJYmlOdzhwUGdjVUxOd1Y'
}
For .swift file
Please Click here
Please have a look at https://www.youtube.com/watch?v=NdszUvzroxQ
I believe you need to use some remote server, instead of local server,
In my Swift file I am using .responseString instead of .responseJSON by this is I am getting success but the response is a HTML file of requesting Google Signin
I am using express post api for login a user, the problem is it returns the previous post response.
I dont know what wrong thing I am doing.
Here is my app.js
var express = require('express');
var session = require('express-session');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var csrf = require('csurf');
// var lusca = require('lusca');
var db = require('./db.config');
var index = require('./routes/index');
var auth = require('./routes/auth');
var users = require('./routes/users');
var admin = require('./routes/admin');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// app.use(cookieParser());
//this or other session management will be required
app.use(session({
secret: 'Qwaszx',
resave: true,
saveUninitialized: true
}));
app.use(express.static(path.join(__dirname, 'public')));
/**
* CSRF
*/
// app.use(lusca({
// csrf: true,
// csp: { /* ... */},
// xframe: 'SAMEORIGIN',
// p3p: 'ABCDEF',
// hsts: {maxAge: 31536000, includeSubDomains: true, preload: true},
// xssProtection: true,
// nosniff: true,
// referrerPolicy: 'same-origin'
// }));
/**
* CSRF Token
*/
app.use(csrf());
app.use(function (req, res, next) {
res.cookie('XSRF-TOKEN', req.csrfToken());
res.locals._csrf = req.csrfToken();
next();
});
/**
* Routes
*/
app.use('/', index);
app.use('/auth', auth);
app.use('/users', users);
app.use('/admin', admin);
// 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;
and my auth.js route file is under routes directory which is as below:
where I am posting login and getting old response all the time time I do not quit the server and restart it.
var express = require('express');
var router = express.Router();
var userModel = require('../model/user.model');
var session = require('express-session');
var auth = require('../middleware');
/**
* Get register API
*/
router.get('/register', auth.Auth, function(req, res, next) {
res.render('auth/register', { title: 'Register a new user' });
});
/**
* Post register API
*/
router.post('/register', auth.Auth, function (req, res, next) {
if(req.body.password === req.body.c_password ){ //password match
userModel.create(req.body).then(function (result){//Create user
res.redirect('/auth/login');
}).catch( function (err) {
res.redirect('/auth/register');
});
}
else{
res.redirect('/auth/register');
}
});
/**
* Get login API
*/
router.get('/login', auth.Auth, function (req, res, next) {
res.render('auth/login');
});
/**
* Post login API
*/
router.post('/login', auth.Auth, function (req, res, next) {
userModel.login(JSON.stringify(req.body)).then( function(resp) {
// console.log(resp);
req.session.user = {
user_id : resp.user_id,
user_type : resp.user_type,
};
// res.send(resp);
res.json(resp);
// res.redirect('/auth/login')
}).catch(function (err){
// console.log(err);
res.json(err);
// res.redirect('/auth/login')
});
});
/**
* Logout API
*/
router.get('/logout', function (req, res, next) {
return userModel.logout(req.session.user.user_id).then(function (result) {
// console.log("result = " + result);
delete req.session.user;
res.redirect('/auth/login');
}).catch(function(err){
// console.log(err);
res.redirect('/');
});
});
module.exports = router;
now my model file where I put database interface is user.model.js is uder model directory which is shown below:
var connection = require('../db.config');
var randomstring = require("randomstring");
var passwordHash = require('password-hash');
var q = require('q');
var deferred = q.defer();
model = {};
model.index = index;
model.create = create;
model.show = show;
model.login = login;
model.logout = logout;
model.adminLogin = adminLogin;
module.exports = model;
/**
* Show all users
*/
function index(){
connection.query('SELECT * FROM users as U JOIN logs as L ON U.id = L.user_id WHERE U.user_type != "1" ORDER BY L.id DESC', function(error, response){
if(error) deferred.reject(error);
if(response.length > 0){
// console.log(response);
deferred.resolve(response);
}
else{
deferred.resolve([]);
}
});
return deferred.promise;
}
/**
* Create a new user
*
* #param {*array} data
*/
function create(data){
var hashedPassword = passwordHash.generate(data.password);
var user = {
'email' : data.email,
// 'user_name' : data.user_name,
'mac_add' : data.mac_add,
'password' : hashedPassword,
'verification_code' : randomstring.generate(10),
'_token' : data._csrf,
}
//Check user is already exists or not
connection.query('SELECT * FROM users WHERE email = "' + user.email + '" LIMIT 0,1', function(error, result) {
if(error) {
deferred.reject(error);
}
if(result[0]){
deferred.reject('Email ' + result[0].email + ' is already taken. Please try with another email.');
}
else{
return createUser();
}
});
//Create User
function createUser() {
connection.query('INSERT INTO users SET ? ', user , function (error, response){
if(error) {
console.log(error);
deferred.reject(error);
}
else{
console.log(response);
deferred.resolve(response);
}
});
}
return deferred.promise;
}
/**
* Show user details
*
* #param {*number} id
*/
function show(id){
connection.query('SELECT * FROM users WHERE id = "' + id + '"', function(error, response) {
if(error) deferred.reject(error);
if(response[0]) deferred.resolve(response[0]);
});
return deferred.promise;
}
/**
* Login user using email, password and mac address
*
* #param {* array} data
*/
function login(data){
var userData = JSON.parse(data);
connection.query('SELECT * FROM users WHERE email = "' + userData.email + '" LIMIT 0,1', function(error, response) {
if(error) deferred.reject(error);
//check if user exists
if(response.length > 0){
if(passwordHash.verify(userData.password, response[0].password)){//password matching
// Validate that an address is a mac address
if(response[0].user_type === 0){
console.log(response[0]);
deferred.resolve(response[0]);
// if ( require('getmac').isMac(response[0].mac_add) ) {
// // var res = JSON.parse(result[0]);
// return createLog(response[0].id, response[0].user_type);
// }
// else{
// deferred.reject('Unauthorized System!');
// }
}
// else{
// var result = {
// 'user_id' : response[0].id,
// 'user_type' : response[0].user_type,
// }
// deferred.resolve(result);
// }
}
else{
deferred.reject('Invalid credential');
}
}
else{
deferred.reject('User not found');
}
});
/**
* Create user logs
*
* #param {*numeric} user_id
*/
function createLog(user_id, user_type){
var log = {
'user_id' : user_id,
// 'in_time' : new Date(),
}
result = {
'user_id' : user_id,
'user_type' : user_type,
}
connection.query('INSERT INTO logs SET ? ', log, function(err, resp) {
if(err) deferred.reject(err);
if(resp) deferred.resolve(result);
});
}
return deferred.promise;
}
/**
* Logout out time entry
*
* #param {*number} user_id
*/
function logout(user_id){
//Get row id of current log from logs table
connection.query('SELECT id FROM logs where user_id = "' + user_id + '" ORDER BY id DESC LIMIT 0,1', function(err, resp){
if(err) deferred.reject(err);
if(resp[0]){
// console.log(result[0].id);
return updateLog(resp[0].id); //updating time
}else{
deferred.reject("No logs");
}
});
function updateLog(id){ // update the out time
// var out_time = new Date();
// console.log(out_time);
connection.query('UPDATE logs SET signature = "shift end", status = "1" WHERE id = ' + id, function(error, response) {
if(error) deferred.reject(error);
if(response) deferred.resolve(response);
});
// console.log(query.sql);
}
return deferred.promise;
}
/**
* Admin Login
*
* #param {*array} data
*/
function adminLogin(data){
var userData = JSON.parse(data);
connection.query('SELECT * FROM users WHERE email = "' + userData.email + '" AND user_type = "1" LIMIT 1', function(error, response) {
if(error) deferred.reject(error);
//check if user exists
if(response.length > 0){
if(passwordHash.verify(userData.password, response[0].password)){//password matching
// console.log("admin response = " + response[0]);
deferred.resolve(response[0]);
}
else{
deferred.reject('Invalid Credential');
}
}
else{
deferred.reject('Unauthorized user');
}
});
return deferred.promise
}
Now I want to know what wrong thing I am doing.
If I am hanging the node server and restarting it again then it works fine otherwise it returns same error or success response with the different credentials.
Thanks
Thanks Robert your answer was correct exactly. Thanks so much.
The soulution was to make seperate promise for each and every function.
I was using deferred = q.defer(); at the top of the page as globaly
So I have to remove it from here and put it seperately in each function.
Like
function index(){
deferred = q.defer();
....
......
return deferred.promise;
}
this was the correct solution thanks alot robert
Thanks
I am trying to login as admin using mobile device and after successful login, I am setting cookie in response header. Mean while, when I try to access routes from other device(laptop), I get all admin access from other device.
How do I maintain session for multiple users ?
Also the problem is I am trying to maintain the view state in global object(login/logout button based on if user in logged-in or not) which get lost with server-side rendering.
I mean all the JavaScript variable data(DataMixin object in my case) is lost.
How to develop isomorphic riotjs app? See similar issue fixed in reactJs: https://github.com/reactjs/react-chartjs/issues/57
State:
document.addEventListener('DOMContentLoaded', function (e) {
DataMixin = { //Global object
setAuthentication: function(){
if(arguments[0] != null){
localStorage.setItem('role', arguments[0][0]);
localStorage.setItem('loginStatus', arguments[0][1]);
}
},
getRole: function(){
return localStorage.getItem('role');
},
}
}
View:
ADMIN LOGIN
<li if="{DataMixin.getRole() == 'ROLE_ADMIN'}">
<a onclick="{logout}">LOGOUT</a>
</li>
Loading pages from server-side using node+express:
function urlDataApiResponse(url, params, req, res) {
swig = require('swig');
var header_tag = require('./public_html/tags/header_tag.tag');
var blog_post_details_tag = require('./public_html/tags/blog_post_details.tag');
var footer_tag = require('./public_html/tags/footer_tag.tag');
var blog_sidebar_tag = require('./public_html/tags/blog_sidebar.tag');
var slide_menu_tag = require('./public_html/tags/slide_menu.tag');
app.engine('html', swig.renderFile);
app.set('view engine', 'html');
app.set('views',__dirname + '/public_html/tags/');
var postDetails = {};
console.log('url inside getApiResponse ', url);
var options = {
method: 'GET',
uri: url,
qs: params,
headers: {
'User-Agent': 'Request-Promise'
},
json: true // Automatically parses the JSON string in the response
};
rp(options)
.then(function (response) {
createJWT(req,res);
var postDetails, categories, blog_sidebar_tag_rendered, slide_menu_tag_rendered,
header_tag_rendered, blog_tag_rendered, footer_tag_rendered;
postDetails = (response[0].attributes);
console.log('.............................................................');
console.log('.............SERVER-SIDE-RENDERING:START.....................');
console.log('.............................................................');
header_tag_rendered = riot.render(header_tag, {role: storage.getItemSync('role'), loginStatus: storage.getItemSync('loginStatus') });
slide_menu_tag_rendered = riot.render(slide_menu_tag, {role: storage.getItemSync('role'), loginStatus: storage.getItemSync('loginStatus') });
blog_tag_rendered = riot.render(blog_post_details_tag, {details: postDetails, role: storage.getItemSync('role')});
blog_sidebar_tag_rendered = riot.render(blog_sidebar_tag);
footer_tag_rendered = riot.render(footer_tag);
var meta_details = {
postImageUrl: postDetails.userImage,
title: postDetails.title + " - Rootscopeit.in",
description: postDetails.details.substring(0,200)+"...",
details: postDetails.details,
url: postDetails.url
};
res.render('blog_post_details', {
open_graph: meta_details,
header_details: header_tag_rendered,
slide_details: slide_menu_tag_rendered,
article_details: blog_tag_rendered,
sidebar_details: blog_sidebar_tag_rendered,
footer_details: footer_tag_rendered});
console.log('............................................................');
console.log('............SERVER-SIDE-RENDERING:END.......................');
console.log('............................................................');
})
.catch(function (err) {
console.log('=================================');
console.error('POST error ', err.stack);
console.log('=================================');
return res.status(res.statusCode).send(err);
});
}
Setting cookie in passport js:
//==============
//TOKEN CREATION
//==============
function createJWT(req, res){
var claims = {
sub: 'Social Authentication',
iss: 'https://rootscopeit.in',
};
var jwt = nJwt.create(claims, secretKey);
jwt.setExpiration(new Date().getTime() + (60 * 60 * 1000 * 1)); // One hour from now
var token = jwt.compact();
var cookies = new Cookies(req, res).set('access_token', token, {
//httpOnly: true,
//secure: true // for your production environment
});
}
//=======================================
//===Google Authentication
//=======================================
var passport = require('passport');
var GoogleStrategy = require('passport-google-oauth20').Strategy;
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (obj, done) {
var user = USERS[id];
done(null, user);
});
app.get('/auth/google', passport.authenticate('google',
{scope: ['profile', 'https://www.googleapis.com/auth/plus.login',
'https://www.googleapis.com/auth/plus.profile.emails.read',
'https://www.googleapis.com/auth/blogger']}));
app.get('/auth/google/callback', passport.authenticate('google', {failureRedirect: '/', failureFlash: true}),
function (req, res) {
console.log('success authentication');
createJWT(req,res);
res.send(popupTools.popupResponse(req.user));
}
);
I'm using nodejs, express 4 and everyauth for social network authentication. I'm having some problem where I click Accept from Google and and redirects back to my / I get
_http_outgoing.js:335
throw new Error('Can\'t set headers after they are sent.');
I'm using electrolyte as a DI as well but I don't think that would be an issue. Here's my code
index.js
var express = require('express'),
http = require('http'),
bootable = require('bootable');
var app = bootable(express());
app.phase(bootable.initializers('etc/init', app));
app.phase(bootable.routes(__dirname + '/routes.js', app));
app.phase(function listen(done) {
http.createServer(app).listen(process.env.PORT || 3000, function(err) {
if (err) { return done(err); }
var addr = this.address();
console.log('server listening on http://' + addr.address + ':' + addr.port);
done();
});
});
module.exports = app;
routes.js
var IoC = require('electrolyte');
module.exports = function routes() {
this.get('/', IoC.create('handlers/homepage'));
this.get('/api/foursquare', IoC.create('handlers/api/foursquare'));
//this.get('/auth/google/callback', IoC.create('handlers/auth/google_auth_callback'));
}
handlers/homepage
exports = module.exports = function() {
function render(req, res, next) {
res.render('index');
};
return [render];
};
google.js
var everyauth = require('everyauth'),
GoogleUser = require('../../app/models/google_user'),
mongoose = require('../../app/db/mongo');
require('dotenv').load();
module.exports = function() {
everyauth.google
.appId(process.env.GOOGLE_CLIENT_ID)
.appSecret(process.env.GOOGLE_CLIENT_SECRET)
.scope('https://www.googleapis.com/auth/plus.login') // What you want access to
.handleAuthCallbackError( function (req, res) {
// If a user denies your app, Google will redirect the user to
// /auth/facebook/callback?error=access_denied
// This configurable route handler defines how you want to respond to
// that.
// If you do not configure this, everyauth renders a default fallback
// view notifying the user that their authentication failed and why.
})
.findOrCreateUser( function (session, accessToken, accessTokenExtra, googleUserMetadata) {
console.log('come back from google');
console.log(session);
// find or create user logic goes here
// Return a user or Promise that promises a user
// Promises are created via
// var promise = this.Promise();
/*
var googleUser = new GoogleUser(mongoose);
var johndoe = new googleUser({
accessToken: 'accessToken',
expires: new Date(),
refreshToken: 'refreshToken',
email: 'john#doe.com',
createdAt: new Date()
});
var promise = this.Promise();
promise.resolve(johndoe);
return promise;
*/
}).redirectPath('/');
};
mongo.js
var mongoose = require('mongoose')
require('dotenv').load();
var uristring = process.env.MONGOLAB_URI;
mongoose.connect(uristring, function (err, res) {
if (err) {
console.log ('ERROR connecting to: ' + uristring + '. ' + err);
} else {
console.log ('Succeeded connected to: ' + uristring);
}
});
exports = module.exports = mongoose
You will get Can't set headers after they are sent. if your code is like this
if (err) {
res.send(err);
}
else if(!user) {
res.send(info);
}
res.send(user);
In the above code, if user is undefined it sends the info as response and it again comes to next statement i.e res.send(user);. So it cannot set headers to the response which is already sent.
You can prevent this by
if (err) {
res.send(err);
}
else if(!user) {
res.send(info);
}
else {
res.send(user);
}
or
if (err) {
return res.send(err);
}
else if(!user) {
return res.send(info);
}
return res.send(user);