Session access issue in nodejs? - debugging

I have modify https://github.com/jimpick/everyauth-example-password/blob/master/server.js for making login with mysql.
I want to access the session in
authenticate(function(login, password) {
var errors = [];
var user = [];
userModule.CheckUserLogin(login, password, function(err, results) {
if(results.length > 0) {
req.session.login = login;
return user;
}
else {
if(!user) return ['Login failed'];
}
});
return user;
})
I have this code in bottom
var app = express.createServer(
express.bodyParser()
, express.static(__dirname + "/public")
, express.cookieParser()
, express.session({ secret: 'htuayreve' })
, everyauth.middleware()
);
app.configure(function() {
app.set('view engine', 'jade');
});
app.get('/', function(req, res) {
res.render('home', { users: JSON.stringify(usersByLogin, null, 2) });
});
If I paste app code from bottom to top then everyayth's routing not worked.I want to simple know how I can access the req.session.login inside everyauth function.

You can't access the session from your authenticate function. The everyauth way of supporting access the authenticated user's information is for you to provide a findUserById function to everyauth that will look up a user record given the user's id that gets stored in the session during authentication. Once you do that you can access all the user's attributes in your route handlers via req.user.
See the 'Accessing the User' section on the everyauth website.

Related

Error: Client is unauthorized to retrieve access tokens (ServiceAccountCredentials) nodejs

I have been trying to create an app to list all gmail labels of given user by using service account.
Service account have domain-wide delegation and it's raise error when I ran this script "Client is unauthorized to retrieve access tokens".
var {google} = require('googleapis');
const SCOPES = [
'https://www.googleapis.com/auth/gmail.readonly'
];
var emailToLoginWith = 'useremail#anydomain.com';
var key = require('json_key_file_name.json');
var jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
SCOPES,
emailToLoginWith
);
jwtClient.authorize( function (err, tokens) {
if (err) {
console.log(err);
return;
}
console.log('tokens : ', tokens);
listLabels(jwtClient);
});
function listLabels(auth) {
var gmail = google.gmail({version: 'v1', auth: auth });
gmail.users.labels.list({
userId: 'user_id',
}, function(err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
console.log('labels response', response);
var labels = response.labels;
if (labels.length == 0) {
console.log('No labels found.');
} else {
console.log('Labels:');
for (var i = 0; i < labels.length; i++) {
var label = labels[i];
console.log('- %s', label.name);
}
}
});
}
Client is unauthorized to retrieve access tokens.
This error normally happens when you have created the incorrect type of credentials on Google Developer console. You say that you are using a service account make sure that you have download the correct json file from. After that credentials and the code used to use them are diffrent. You cant use the credentials for a service account with code from browser you will get this error.
I am not a node developer but i found this
http://isd-soft.com/tech_blog/accessing-google-apis-using-service-account-node-js/
You may want to try to get the service account working with drive first. Then when that works move to gmail domain delegation with gmail and service accounts can be tricky sometimes its better to have an example you know works to build off of.

Parse On Buddy Logout User

I am migrating an application from parse.com to buddy.com. One of the caveats of the migration was that Parse.User.current() is no longer available on buddy.com, instead you have to get the user and session token from the request itself: https://github.com/ParsePlatform/Parse-Server/wiki/Compatibility-with-Hosted-Parse#no-current-user
The application I am migrating has a logoutUser method that I am attempting to migrate:
Parse.Cloud.define("logoutUser", function(request, response) {
Parse.User.logOut().then(
function onSuccess(result){
response.success(result);
},
function onError(error) {
response.error(error);
}
)
});
now I am attempting to do this in the new style, but am receiving an error. (NOTE: This is cloud code not a nodejs environment)
{
"code":"500",
"error":"Error: There is no current user user on a node.js server environment."
}
New implementation:
function logoutUser(request, response) {
var user = request.user;
var sessionToken = user.getSessionToken();
Parse.User.logOut({ sessionToken }).then(
function onSuccess(result){
response.success(result);
},
function onError(error) {
response.error(error);
}
)
}
Parse.Cloud.define("logoutUser", function(request, response) {
logoutUser(request, response);
});
Suggestions on how to correctly log out users in the Parse on Buddy cloud code?
You could fetch user's session or sessions and delete it / them:
var query = new Parse.Query("_Session");
query.descending('createdAt');
query.equalTo('user', {__type:"Pointer", className:"_User", objectId:"idhere"});
query.first({
useMasterKey: true
}).then(function(session) {
var sessions = [];
sessions.push(session);
Parse.Object.destroyAll(sessions);
}, function (err) {
console.log("Internal error " + err);
});
OR for more tokens you could use find instead of first like:
var query = new Parse.Query("_Session");
query.equalTo('user', {__type:"Pointer", className:"_User", objectId:"idhere"});
query.find({
useMasterKey: true
}).then(function(sessions) {
Parse.Object.destroyAll(sessions);
}, function (err) {
console.log("Internal error " + err);
});
The above will mostly delete or tokens related to the given user. If you wish to delete only tokens used for login, and not for signup or upgrade, then you could put into your query:
query.equalTo('createdWith', { action: 'login', authProvider: 'password'});
As far as i know, deleting a user's last used for login token, then he is logged-out.
To add to the above, if you pass up the user's session key to the Cloud Code function via the X-Parse-Session-Token header, you can use the populated request.user object in the session query directly, instead of the user's ID.

New Session/Cookie for Each User in Express

I'm using express to make API calls to a e-commerce platform. The API uses sessions to handle the persistent data needed for user tasks, like account and cart records. Cart and account details are attached to sessions (and the cookies that the sessionID is stored in), so when I log in with User1 and create a cart with items, and then log out, the cart persists. However, when logging in with User2, they inherit the cart of User1 because it's attached to the session.
EDIT/UPDATE
Main app.js:
var nodemailer = require("nodemailer"),
request = require("superagent"),
flash = require("connect-flash"),
bodyParser = require("body-parser"),
session = require("express-session"),
cookieParser = require("cookie-parser"),
methodOverride = require("method-override"),
Schema = require("schema-client"),
express = require("express"),
nodeuuid = require("uuid"),
cors = require("cors"),
app = express();
app.use(session({
name: "X-Session",
secret: "randomstring",
resave: false,
saveUninitialized: false,
cookie: {
maxAge: 60*60*1000,
secure: false
}
}));
app.use(bodyParser.urlencoded({extended:false}))
.use(cookieParser())
.set("view engine", "ejs")
.use(express.static(__dirname + "/public"))
.use(methodOverride("_method"))
.use(flash())
var client = new Schema.Client("clientname", 'privateKeyhere');
var SchemaAPI = "https://clientname:privatekey#api.schema.io";
app.use(function(req, res, next){
res.locals.success = req.flash("success");
res.locals.errors = req.flash("error");
res.locals.account = req.session.account;
res.locals.session = req.session;
res.locals.cart = req.session.cart;
if(req.session.account_id){
client.get("/accounts/{id}", {
id: req.session.account_id
}, function(err, account){
if(account){
req.account = account;
res.locals.account = account;
};
next();
});
} else {
next();
}
});
Login Route:
app.post("/login", function(req, res, next) {
request
.post('http://localhost:3001/v1/account/login')
.set('X-Session', req.session.id)
.set('Accept', 'application/json')
.send({
email: req.body.email,
password: req.body.password
})
.end(function (error, account){
if(account){
account = account.body;
req.session.account = account;
console.log(account.name + " - " + account.id);
console.log(req.sessionID);
req.flash("success", "Logged in, " + account.email + ".");
res.redirect("/index");
} else if(account == null){
req.flash("error", "Your username or password is incorrect. Try again or <a href='/register'> sign up here</a>");
res.redirect("login");
} else {
console.log(error);
res.redirect('login');
}
});
});
All my other app routes have that "X-Session" header being passed with each request.
How can I create one session for each user such that when they log in, their session is retrieved, along with any cart information associated with their session? I'm using express-session to generate a sessionID, and then passing that ID to the API. Thanks in advance for your help.

Parse express server side login using express-session

I'm using parse on node. I have an express app, and a JS browser app, that is hosted off the express server.
At the moment the app has it's own login. It logs the user in on the client, and the client remains logged in.
I want to be able to log the client in via an express route /login. When they log in via this route, i want to log them in on the client side.
I have poured over documentation on this but I have struggled to find any real examples of how this is all done.
Here is some code i have found:
var cookieSession = require('cookie-session'),
// I added this require as it seems the code is using it;
session = require('express-session');
app.use(cookieSession({
name: COOKIE_NAME,
secret: "SECRET_SIGNING_KEY",
maxAge: 15724800000
}));
//
// This will add req.user if they are logged in;
//
app.use(function (req, res, next) {
Parse.Cloud.httpRequest({
url: 'http://localhost:1337/parse/users/me',
headers: {
'X-Parse-Application-Id': 'myAppId',
'X-Parse-REST-API-Key': 'myRestAPIKey',
'X-Parse-Session-Token': req.session.token
}
}).then(function (userData) {
req.user = Parse.Object.fromJSON(userData.data);
next();
}).then(null, function () {
return res.redirect('/login');
});
});
//
// login route;
//
app.post('/login', function(req, res) {
Parse.User.logIn(req.body.username, req.body.password).then(function(user) {
req.session.user = user;
req.session.token = user.getSessionToken();
res.redirect('/');
}, function(error) {
req.session = null;
res.render('login', { flash: error.message });
});
});
//
// and logout.
//
app.post('/logout', function(req, res) {
req.session = null;
res.redirect('/');
});
This looks pretty good, but this won't add a session on the client? How do parse the server login down to the client; Do i pass the session Token and use it on the client?
//
// If i call this code in the browser, i want the logged in user;
//
var current_user = Parse.User.current();
I have been unable to find any real code on-line that demonstrates all of this in the best-practice manner.
Is this the 'best practice' known solution or is there a better way of doing this?

Cloud Code Parse.User.current() return null

When i use this function in Cloud Code Parse.User.current() return null.
I'm using parseExpressCookieSession for login.
Any advice?
var express = require('express');
var expressLayouts = require('cloud/express-layouts');
var parseExpressHttpsRedirect = require('parse-express-https-redirect');
var parseExpressCookieSession = require('parse-express-cookie-session');
// Required for initializing enter code hereExpress app in Cloud Code.
var app = express();
// Global app configuration section
app.set('views', 'cloud/views');
app.set('view engine', 'ejs'); // Switch to Jade by replacing ejs with jade here.
app.use(expressLayouts); // Use the layout engine for express
app.set('layout', 'layout');
app.use(parseExpressHttpsRedirect()); // Require user to be on HTTPS.
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('helloworld'));
app.use(parseExpressCookieSession({
fetchUser: true,
cookie: { maxAge: 3600000 * 24 }
}));
Parse.Cloud.beforeSave('Menu', function(request, response) {
var Business = Parse.Object.extend('Business');
var query = new Parse.Query(Business);
query.equalTo('profile', Parse.User.current().get('profile'));
query.find({
success: function(business) {
console.log(business);
response.success();
},
error: function(error) {
response.error(error.message);
}
});
});
app.listen();
This the code that i use to login/logout
app.post('/login', function(req, res) {
Parse.User.logIn(req.body.username, req.body.password).then(function(user) {
// Login succeeded, redirect to homepage.
// parseExpressCookieSession will automatically set cookie.
res.redirect('/');
},
function(error) {
// Login failed, redirect back to login form.
res.redirect('/');
});
});
// Logs out the user
app.post('/logout', function(req, res) {
Parse.User.logOut();
res.redirect('/');
});
It is an old question but answering for future reference.
Parse.User.current() works in Javascript SDK when used in clients ex. WebApp where users log in and the you can fetch the current user with that function.
To get the user calling a Cloud Code function or doing an operation on an object (beforeSave,afterSave,beforeDelete and so on) you use the request.user property it contains the user issuing the request to Parse.com.
More details about Parse.Cloud.FunctionRequest here: https://parse.com/docs/js/api/classes/Parse.Cloud.FunctionRequest.html
Example code:
Parse.Cloud.beforeSave('Menu', function(request, response) {
var requestUser = request.user;
// instance of Parse.User object of the user calling .save() on an object of class "Menu"
// code cut for brevity
});

Resources