I found a few issues on the main passport repo, however, I think this primarily pertains to this specific strategy as I'm able to successfully authenticate using the passport-google-oauth strategy.
Error: failed to find request token in session
at Strategy.OAuthStrategy.authenticate (/home/glug/application/node_modules/passport-dropbox/node_modules/passport-oauth/lib/passport-oauth/strategies/oauth.js:124:54)
at attempt (/home/glug/application/node_modules/passport/lib/passport/middleware/authenticate.js:243:16)
at Passport.authenticate (/home/glug/application/node_modules/passport/lib/passport/middleware/authenticate.js:244:7)
at callbacks (/home/glug/application/node_modules/express/lib/router/index.js:161:37)
at param (/home/glug/application/node_modules/express/lib/router/index.js:135:11)
at pass (/home/glug/application/node_modules/express/lib/router/index.js:142:5)
at Router._dispatch (/home/glug/application/node_modules/express/lib/router/index.js:170:5)
at Object.router (/home/glug/application/node_modules/express/lib/router/index.js:33:10)
at Context.next (/home/glug/application/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at Context.actions.pass (/home/glug/application/node_modules/passport/lib/passport/context/http/actions.js:77:8)
I am using redis as the session store, however, even after eliminating that, it's still failing with the identical error message.
var DropboxStrategy = require('passport-dropbox').Strategy;
app.configure(function(){
app.set('port', config.express.port);
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({
// store: new RedisStore({ client: redis}),
secret: config.express.secret
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
});
passport.serializeUser(function(user, done) {
// console.log('Serializing: ' + JSON.stringify(user));
done(null, user);
});
passport.deserializeUser(function(obj, done) {
// console.log('Deserializing: ' + obj);
done(null, obj);
});
passport.use(new DropboxStrategy({
consumerKey: config.dropbox.key,
consumerSecret: config.dropbox.secret,
callbackURL: config.dropbox.callbackURL
},
function(token, tokenSecret, profile, done) {
// My storage function
return done(null, profile);
}
));
I'm happy to try anything, I've filed an issue on the repo, but I think it may be something I'm doing wrong rather than something wrong with the passport-dropbox repo.
... Sigh. I forgot I changed the subdomain. So, the cookie wasn't readable because the domain name was different.
Hey if someone is still having the issue I have another solution...
add this code :
app.use(passport.session({ secret: 'Shhh.. This is a secret', cookie: { secure: true } }));
just add cookie: { secure: true } and it will work just fine...
I too had this issue and above technique helped me solve this.
To solved this problem in my case, was necessary setup the host file to use custom domain instead localhost or 127.0.0.1..
Related
When I call req.isAuthenticated() in my local login strategy upon successful login, it always returns true as it should. However, when I try to call req.isAuthenticated in any other file/route in my express server, it always returns false, even when I have a successful login cookie and session. Does anyone have any idea as to why this is? If not, does anyone have any good open source alternatives to passport.js for auth?
Relevant code from express server:
app.use(session({
secret: process.env.AUTH_SECRET,
resave: false,
saveUninitialized:false,
cookie: {
secure: false,
expires: cookieExpirationDate
}
})); // session secret
app.use(passport.initialize());
app.use(passport.session());
...
app.get('/logincheck', (req, res) =>{ //route called by front end component to check auth status
if(req.isAuthenticated()){ //returns false even with cookie and session in browser
res.json({isAuth: true})
}
else res.json({isAuth: false})
})
Relevant code from local login strategy:
var userinfo = user.get();
req.login(user, function(error) {
if (error) return next(error);
console.log('success!')
})
console.log(req.isAuthenticated()) //always returns true on successful login
return done(null, userinfo);
I've tried all of the relevant solutions discussed in this issue:
passport's req.isAuthenticated always returning false, even when I hardcode done(null, true) so any help is greatly appreciated as I feel like I have been getting nowhere with this problem.
I have created a session variable in the login request but unable to access it in logout request(it is undefined).
I want users only that have logged in to request a logout ,if someone who has not logged on requests a logout then ill redirect them to login page.I am using express-session as middleware in the code below.
Here is the session code
var app = express();
app.set('trust proxy', 1); // trust first proxy
app.use(session({
secret: 'nikhilsingh',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
Here is the login function
app.post('/login',bodyparserencoder,function(req,res){
console.log('login requested');
let query=require('../'+'dbconnect/'+'login.js');
let exists=query.login({username:req.body.Username,password:req.body.Password},res,req);
console.log('everything done, exists= ' + exists);
req.session.loggedin=true;
});
here is the logout
app.get('/logout',function(req,res){
console.log(req.session.loggedin);
if(req.session.loggedin){
console.log('logout requested');
res.render('Addmie.ejs');}
else{
console.log('login to continue');
}
});
I am new to nodejs ,please ellaborate and explain if I am doing something wrong.Thanks.
I solver this problem by removing the secure attribute from cookie object,anyways I did not understand what actually was causing the problem.
My TypeScript server is based on this example project. Whenever nodemon restarts my server, whether automatic or manually, I lose my session and have to log in again. I hate this because it's a massive waste of time when done for the 1000th time. I've tried to configure my Express.js session settings, but nothing seems to be working. Here's my configuration:
/**
* Configure application
*
* #class Server
* #method config
*/
public config() {
//add static paths
this.app.use(express.static(path.join(__dirname, 'public')));
//configure pug
this.app.set('views', path.join(__dirname, 'views'));
this.app.set('view engine', 'ejs');
//use logger middlware
this.app.use(logger('dev'));
//use json form parser middlware
this.app.use(bodyParser.json());
//use query string parser middlware
this.app.use(bodyParser.urlencoded({
extended: true
}));
this.app.use(cookieParser("my secret"));
this.app.use(session({
name: 'MyStudio',
secret: "my secret",
resave: false,
saveUninitialized: false,
cookie: {
maxAge: 86400000,
httpOnly: true,
secure: false
}
}));
this.app.use(passport.initialize());
this.app.use(passport.session());
//this.app.set('trust proxy', 1) // trust first proxy
this.app.set('json spaces', 4);
passport.serializeUser((user, done) => {
return done(null, user);
});
passport.deserializeUser((user, done) => {
return done(null, user);
});
passport.use('local-login', new Local.Strategy(
(username, password, done) => {
// My custom login logic
}
));
this.app.use(methodOverride());
}
How do I stop Express.js from losing my session on every restart?
express-session has support for different stores (databases) to store the session data in.
The default that is used is MemoryStore which keeps session data in memory for as long as the Express process runs. When the Express process stops (for instance, when it restarts), all session data is gone.
If you want session data to survive restarts, you need to use a persistent session store. Instead of storing the session data in memory, these store the session data in (for instance) a database. There are plenty of persistent session stores available, a list of which can be found here: https://github.com/expressjs/session#compatible-session-stores
Ok, so this is a common error with many causes. I am trying to modify an existing Node-Passport-Facebook module to have local images from the desktop uploaded to a users Facebook account after they log in. That is my goal. This is the code module I am extending
https://github.com/passport/express-4.x-local-example
which in turn is based on
https://github.com/jaredhanson/passport-facebook
I never get past console.log('ERROR HERE... with an error of "This authorization code has been used."
What's confusing is that the auth code returned is ALWAYS DIFFERENT! so how could it already have been used when I try and exchange it for an access token?
Can anyone offer some suggestions, and or next steps I might try? My hunch is that there is something about Passport.js that is not implemented properly.
So my question is, how would I modify the code below (based on this passport facebook example) https://github.com/passport/express-4.x-facebook-example/blob/master/server.jsto upload an image after logging in?
var express = require('express');
var passport = require('passport');
var Strategy = require('passport-facebook').Strategy;
var CLIENTSECRET ='<client secret>';
var APPID ='<app id>';
// Configure the Facebook strategy for use by Passport.
//
// OAuth 2.0-based strategies require a `verify` function which receives the
// credential (`accessToken`) for accessing the Facebook API on the user's
// behalf, along with the user's profile. The function must invoke `cb`
// with a user object, which will be set at `req.user` in route handlers after
// authentication.
passport.use(new Strategy({
clientID: APPID,
clientSecret: CLIENTSECRET,
callbackURL: 'http://localhost:3000/login/facebook/return',
enableProof: true
//callbackURL: 'http://localhost:3000/login/facebook/return'
},
function(accessToken, refreshToken, profile, cb) {
// In this example, the user's Facebook profile is supplied as the user
// record. In a production-quality application, the Facebook profile should
// be associated with a user record in the application's database, which
// allows for account linking and authentication with other identity
// providers.
cb(null, profile);
}));
// Configure Passport authenticated session persistence.
//
// In order to restore authentication state across HTTP requests, Passport needs
// to serialize users into and deserialize users out of the session. In a
// production-quality application, this would typically be as simple as
// supplying the user ID when serializing, and querying the user record by ID
// from the database when deserializing. However, due to the fact that this
// example does not have a database, the complete Twitter profile is serialized
// and deserialized.
passport.serializeUser(function(user, cb) {
cb(null, user);
});
passport.deserializeUser(function(obj, cb) {
console.log(" ");
console.log("ASSERT passport.deserializeUser being called");
console.log(" ");
cb(null, obj);
});
// Create a new Express application.
var app = express();
// Configure view engine to render EJS templates.
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
// Use application-level middleware for common functionality, including
// logging, parsing, and session handling.
app.use(require('morgan')('combined'));
app.use(require('cookie-parser')());
app.use(require('body-parser').urlencoded({ extended: true }));
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }));
// Initialize Passport and restore authentication state, if any, from the
// session.
app.use(passport.initialize());
//app.use(passport.session());
// Define routes.
app.get('/',
function(req, res) {
res.render('home', { user: req.user });
});
app.get('/login',
function(req, res){
res.render('login');
});
app.get('/login/facebook',
passport.authenticate('facebook'));
app.get('/login/facebook/return',
passport.authenticate('facebook', { failureRedirect: '/login' }),
function(req, res) {
//my code changes start here!!
var code = req.query.code;
console.log("1 ASSERT after successful login! code="+code);
if(req.query.error) {
// user might have disallowed the app
return res.send('login-error ' + req.query.error_description);
} else if(!code) {
return res.redirect('/');
}
var options={
host:'graph.facebook.com',
path:'/oauth/access_token?client_id='+APPID+'&code='+code +'&client_secret='+CLIENTSECRET+'&redirect_uri=http://localhost:3000/login/faceboo k/return'
}
var https=require('https');
https.get(options,function(res){
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('ERROR HERE'+chunk);
});
});
console.log("2 ASSERT after successful login!")
//my code changes end here!!
});
app.get('/profile',
require('connect-ensure-login').ensureLoggedIn(),
function(req, res){
res.render('profile', { user: req.user });
});
app.listen(3000);
You don't need to make a request to /oauth/access_token at all (well you do, but passport has already handled it for you). That endpoint is for getting an access token when you don't have one, but you already have an access token here:
passport.use(new Strategy({
clientID: APPID,
clientSecret: CLIENTSECRET,
callbackURL: 'http://localhost:3000/login/facebook/return',
enableProof: true
//callbackURL: 'http://localhost:3000/login/facebook/return'
},
function(accessToken, refreshToken, profile, cb) {
// You have the access token here!
cb(null, profile);
}));
You'll need to save that accessToken some way, so that you can use it later when you make requests to the Graph API. You'll probably want to save it to the user's session, but you can also use a strategy like this: https://stackoverflow.com/a/24474900/772035
If you want the user to grant permission to publish (which you will need them to do, to be able to post to their feeds) you also need to replace every call to passport.authenticate with:
passport.authenticate('facebook', { scope: ['publish_actions'] } );
So that the posting permission is requested when the user first adds your app. Then you'll be able to use the /user/photos endpoint to upload a photo, passing the accessToken that you saved earlier in the query string.
You need to encode your query params.
var qs = {
client_id: APPID,
redirect_uri: 'http://localhost:3000/login/facebook/return',
client_secret: CLIENTSECRET,
code: code,
};
options = {
host:'graph.facebook.com',
path:'/oauth/access_token?' + require('querystring').stringify(qs),
};
I think that's your problem. The code itself looks fine apart from that. You'll want the querystring module to parse the results too by the way.
I solved this error. Follow the progress.
Facebook Log in -> Settings -> Apps -> Logged in with Facebook -> Delete Your apps.
After deleting your apps, Try to login with Facebook button.
you need to define profileFields instead of enableProof: true
passport.use(new FacebookStrategy({
clientID:keys.FacebookAppID,
clientSecret:keys.FacebookAppSecret,
callbackURL:'http://localhost:3000/auth/facebook/callback',
profileFields:['email','name','displayName','photos']
},(accessToken,refreshToken,profile,done)=>{
console.log(profile);
}));
I can't quite figure out how to use Passport's serializeUser function in express/SQL.
Here are my questions:
How does passport.serializeUser know what "user" is? Where should I have specified it?
How does passport.serializeUser know which request object should be bound with a cookie?
My app configuration looks like this:
var passport = require('passport');
app.use(session({ secret: 'Secret',
saveUninitialized: true,
resave: true}));
app.use(passport.initialize());
app.use(passport.session());
I also expose the following code to the app in twitter_auth.js:
// twitter authentication and login
app.get('/auth/twitter', passport.authenticate('twitter'));
// handle callback after twitter has authenticated user
app.get('/auth/twitter/callback',passport.authenticate('twitter',{
successRedirect: '/',
failureRedirect: '/'
}));
// used to serialize user
passport.serializeUser(function(user,done){
done(null,user);
});
// used to deserialize the user
passport.deserializeUser(function(User_ID,done){
connection.query('SELECT * from UsersTable where User_ID = '+User_ID, function(err,rows){
done(err,rows[0]);
});
});
When I try spotting it:
// used to serialize user
passport.serializeUser(function(user,done){
console.log('spotted here!');
done(null,user);
});
I never see anything. What's wrong?
To answer your two questions:
You have to define what 'user' is inside the authentication code.
It should look like this:
passport.use(new TwitterStrategy({
consumerKey:*******,
consumerSecret:******,
callbackURL:'/auth/twitter/callback'
},
function(token, tokenSecret, profile,done){
var user = db.call(retrieve a user) ; //whatever you want it to be
done(null,user);
});
The authentication route was accessed via some request object to begin with, and it's the code there:
done(null,user);
that knows of your req object. From my understanding, that is.
A good source on this is: http://toon.io/understanding-passportjs-authentication-flow/