web-dev-qa-db-fra.com

Node + Express + Passport: req.user Undefined

Ma question est semblable à celle-ci one , mais sa solution n’était pas claire.

J'utilise Passport pour utiliser Instagram. Une fois l’autorisation réussie, les utilisateurs sont dirigés vers "/". À ce stade, la demande a l'objet utilisateur (c'est-à-dire qu'il fonctionne). Cependant, une fois que je redirige, le req.user est indéfini. : '(

La partie étrange est que passport.deserializeUser est appelé à chaque demande. L'objet utilisateur a bien été récupéré, mais quelque part sur la route du middleware, req.user n'est pas défini (ou n'est pas défini).

// on successful auth, goto "/" 
app.get('/', function(req, res) {
    // if the request has the user object, go to the user page
    if (req.user) {
        res.redirect("/user/" + req.user._id);
    }

    res.render("index");
}

app.get('/user/:uid', function(req, res) {
    console.log(req.user) // undefined
}
53
gojohnnygo

Avez-vous configuré l'état de session pour votre application? Vous avez besoin de quelque chose comme ça ...

app.use(session({ secret: 'anything' }));
app.use(passport.initialize());
app.use(passport.session());
34
Martin

Mon problème ne spécifiait pas d'envoyer des cookies lors de l'utilisation de l'extraction côté client. Cela a fonctionné après avoir inclus les informations d'identification: champ 'include' dans la demande.

fetch('/api/foo', {credentials: 'include'})
43
Jon Rodness

Je suis super nouveau pour Node mais c'était un problème de middleware pour moi. BodyParser ajouté et réarrangé pour corriger. 

Code cassé:

app.use(express.cookieParser('secret'));
app.use(express.cookieSession());
app.use(express.session({ secret: 'anything' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public'))); 

Code de travail:

app.use(express.static(path.join(__dirname, 'public')));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({ secret: 'anything' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);

J'espère que cela t'aides

14
leylandjacob

Auparavant, j'ai ce code (n'a pas fonctionné):

app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('abcdefg'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
    secret: 'abcdefg',
    resave: true,
    saveUninitialized: false,
    cookie: { secure: true } // this line
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));

Ensuite, je supprime l'option cookie de l'initialiseur de session:

app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('abcdefg'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(session({
    secret: 'abcdefg',
    resave: true,
    saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));

et maintenant ça marche.

7
user3323765

Ouais, permets des sessions comme le dit @Martin. Toutefois, si vous utilisez la version Express 4. *, les middleware de type session ne sont pas fournis, vous devez donc l’installer individuellement.

  1. Ajouter "express-session": "1.4.0" dans votre package.json
  2. npm installer
  3. utilise le

;

var express = require('express');
var cookieParser = require('cookie-parser')
var session = require('express-session')
var app = express()
app.use(cookieParser()) // required before session.
app.use(session({secret: 'keyboard cat'}))

Pour plus d'informations, consultez la documentation de la session express.

4
Adrian Enriquez

Je rencontre le même problème à cause d'un simple copier-coller du code suivant dans la documentation de session express, mais je ne l'ai pas entièrement lu.

app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: true }
}))

Dans la documentation, il est mentionné:

Cependant, il nécessite un site Web compatible https, c’est-à-dire que HTTPS est nécessaire pour les cookies sécurisés. Si sécurisé est activé et que vous accédez à votre fichier site via HTTP, le cookie ne sera pas défini.

donc, si vous avez juste une connexion HTTP, supprimez l'option sécurisée, et le code ci-dessous devrait fonctionner:

app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  //cookie: { secure: true } remove this line for HTTP connection
}))
4
ufxmeng

Dans les itinéraires, essayez d'ajouter: {session: true}

app.get('/auto-login', passport.authenticate('cross', {session: true}))
3
Strawberry

J'ai eu exactement le même problème avec Express 4 et après avoir essayé à peu près tout ce que je pouvais trouver en ligne, j'ai finalement réussi à le faire fonctionner en ajoutant «cookie-session». 

var cookieSession = require('cookie-session');

app.use(cookieSession({
  keys: ['key1', 'key2']
}));
2
ergusto

La mienne concernait les cookies et les cors. J'ai résolu en ajoutant le code suivant sur mon serveur:

allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:3000'); // your website
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
if ('OPTIONS' === req.method) {
    res.send(200);
} else {
    next();
}};
1
MmtBkn

Lorsque vous utilisez une requête http côté client, n'oubliez pas de joindre les informations d'identification . Dans Angular2, vous devez ajouter un argument d'option: {withCredentials: true}. Après cela, vous aurez le même req.sessionID jusqu'à ce que vous le réinitialisiez.

this._http.get("endpoint/something", { withCredentials: true })
1
Honzik

Une fois que vous avez configuré votre session express, assurez-vous que votre passeport est sérialisé et désérialisé, dans la fonction de désérialisation, à la génération de req.user. Voir l'explication ici d'une autre question de stackoverflow.

passport.serializeUser(function(user, done) {
 done(null, user);
});


passport.deserializeUser(function(user, done) {
 done(null, user);
});
1
Aric Sangchat

Si votre pile de middleware n'est pas claire, en supposant que vous disposiez d'un middleware de session quelque part , vous pouvez enregistrer la session avant la redirection:

if (req.user) {
    req.session.save(function (err) {
        if (err) {
            // ... panic!
        }
        res.redirect("/user/" + req.user._id);
    });
    return;
}
0
exclsr

Mes deux cents: Code ne fonctionne pas:

server.use(
session({
  secret: "secretsssss",
  rolling: false,
  resave: false,
  saveUninitialized: false,
  cookie: {
    sameSite: true, //this line
    maxAge: 60 * 60 * 1000
  }
})
);

code de travail:

server.use(
session({
  secret: "secretsssss",
  rolling: false,
  resave: false,
  saveUninitialized: false,
  cookie: {
    sameSite: false, // i think this is default to false
    maxAge: 60 * 60 * 1000
  }
})
);
0
Ruizhen Mai

En faisant passport.authenticate, vous pouvez ajouter session: true pour résoudre votre problème:

app.post("/login", passport.authenticate('local', {
    'failureRedirect': '/login',
    'session': true
}), (req, res)=>{ res.redirect("/"); });
0
Mahesh

Le serveur envoie l'en-tête SetCookie, puis le descripteur de navigateur pour le stocker, puis le cookie est envoyé avec les demandes adressées au même serveur à l'intérieur d'un en-tête HTTP Cookie.

Je devais définir withCredentials: true dans mon client. (axios.js)

const config = {
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json',
  },
};

axios.put(url, { page: '123' }, config)
  .then(res => console.log('axios', res))
  .catch(err => console.log('axios', err));

Ensuite, des problèmes de CORS surviennent.

J'ai donc ajouté ceci à mon serveur express:

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Origin', req.headers.Origin);
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
  if ('OPTIONS' == req.method) {
    res.send(200);
  } else {
      next();
  }
});
0
Sunny Sultan

Lorsque vous authentifiez un utilisateur, la valeur de la requête req.user est renseignée. Pour savoir si l'identifiant est l'utilisateur et remplissez cette valeur, un cookie est utilisé. Si, comme moi, vous configurez la session avec des cookies sécurisés, ceux-ci ne seront disponibles que sur HTTPS, ce qui n'est pas la configuration standard d'un serveur de développement local, par exemple. Pour que les cookies fonctionnent sur HTTP, commentez cookie: { secure: true } et la valeur req.user sera correctement configurée:

this.app.use(session({
    resave: true,
    saveUninitialized: true,
    secret: process.env.SESSION_SECRET || "a secret",
    // cookie: { secure: true },
}));

Si, raisonnablement, vous souhaitez utiliser des cookies supérieurs à HTTPS uniquement en production, vous pouvez procéder de la manière suivante:

cookie: { secure: process.env.ENV === 'PRODUCTION' }
0
Alain1405

Le mien était différent de tout cela. Auparavant, je développais un site Wordpress sur localhost, puis je passais à un projet distinct Node/React.

Le cookie du site Wordpress était toujours présent et envoyé depuis que les deux projets ont été exécutés sur localhost. Cela causait le problème.

J'ai dû effacer les cookies pour localhost et ensuite cela a fonctionné.

0
Breakpoint25

J'ai eu le même problème, à la fois avec req.isAuthenticated () et req.user, voici comment j'ai résolu

  • req.isAuthenticated () résolu en remplaçant findOne () par find () dans la méthode findById () à l'intérieur de deserialize (), je pourrais alors sauvegarder un req authentifié, sinon il ne renverrait rien.

  • req.user résolu en ajustant l'ordre, la première session express doit être stockée, puis le passeport doit être initialisé, puis la session suivante stockée dans passport.session (), après quoi nous pouvons accéder à req.user ()

app.use(session(...));
app.use(passport.initialize());
app.use(passport.session());
// Now we can access req.user so after we will call req.user, if we write it above these, it will always return underfined
app.use(function(req, res, next){
  res.locals.user = req.user || null
  next();
})

Voir, si vous accédez à req.user après passport.session(), sinon ajoutez votre route ci-dessous.

0
Syed Muhammad Asad

Avez-vous essayé d'insérer votre clé secrète dans le cookieParser?

var passport = require('passport');
var expressSession = require('express-session');

app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('mySecretKey'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(expressSession({
secret: 'mySecretKey',
  resave: false,
  saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
0
Marco Mantovani

Avait exactement le même problème. Pour moi, la solution consistait à utiliser "sessions client" au lieu de "session express". Probablement une mauvaise configuration de session?

Code non fonctionnel:

var session = require('express-session');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(session({
    secret: 'random string',
    resave: true,
    saveUninitialized: true,
    cookie: { secure: true }
}));

Code de travail:

var session = require('client-sessions');

        app.use(bodyParser.urlencoded({ extended: false }));
        app.use(express.static(path.join(__dirname, 'public')));
        app.use(cookieParser());
        app.use(bodyParser.json());
        app.use(session({
        cookieName: 'session',
        secret: 'random string',
        duration: 30 * 60 * 1000,
        activeDuration: 5 * 60 * 1000,
    }));
0
Luis