web-dev-qa-db-fra.com

Express ne place pas de cookie

J'ai un problème avec la mise en place de cookies via express. J'utilise Este.js dev stack Et j'essaie de définir un cookie dans la route d'authentification /login De l'API. Voici le code que j'utilise dans /api/v1/auth/login route

res.cookie('token', jwt.token, {expires: new Date(Date.now() + 9999999)});
res.status(200).send({user, token: jwt.token});

Dans src/server/main.js J'ai enregistré cookie-parser Comme premier middleware

app.use(cookieParser());

L'en-tête de réponse pour la route /api/v1/auth/login Contient

Set-Cookie:token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ.. 

mais le cookie n'est pas enregistré dans le navigateur (document.cookie est vide, également l'onglet Resources - Cookies dans les outils de développement est vide ) :(

EDIT: J'ai constaté que lorsque j'appelle ceci dans /api/v1/auth/login (Sans appeler res.send Ou res.json)

res.cookie('token', jwt.token, {expires: new Date(Date.now() + 9999999), httpOnly: false});next();

puis le cookie est défini ET l'en-tête de réponse a défini X-Powered-By:Este.js ... cela définit esteMiddleware dans expres frontend render part .

Lorsque j'utilise res.send

res.cookie('token', jwt.token, {expires: new Date(Date.now() + 9999999), httpOnly: false}).send({user, token: jwt.token});`
next();

alors j'obtiens l'erreur Can't set headers after they are sent. parce que la méthode send est utilisée, donc le rendu frontal renvoie cette erreur.

Mais je dois envoyer des données à partir de l'API, alors comment puis-je gérer cela?

Certains peuvent-ils m'aider s'il vous plaît? Merci!

16
Mira

J'ai eu le même problème. La réponse du serveur est fournie avec un jeu de cookies:

Set-Cookie:my_cookie=HelloWorld; Path=/; Expires=Wed, 15 Mar 2017 15:59:59 GMT 

Mais le cookie n'a pas été enregistré par un navigateur.

Voilà comment je l'ai résolu.

J'utilise fetch dans un code côté client. Si vous ne spécifiez pas credentials: 'include' dans les options fetch, les cookies ne sont ni envoyés au serveur ni enregistrés par un navigateur, bien que la réponse du serveur définisse des cookies.

Exemple:

var headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');

return fetch('/your/server_endpoint', {
    method: 'POST',
    mode: 'same-Origin',
    redirect: 'follow',
    credentials: 'include', // Don't forget to specify this if you need cookies
    headers: headers,
    body: JSON.stringify({
        first_name: 'John',
        last_name: 'Doe'
    })
})

J'espère que cela aide quelqu'un.

29
Green

je travaille avec express 4 et le noeud 7.4 et angulaire, j'ai eu le même problème pour moi aider ceci:
a) côté serveur: dans le fichier app.js je donne des en-têtes à toutes les réponses comme:

 app.use(function(req, res, next) {  
      res.header('Access-Control-Allow-Origin', req.headers.Origin);
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      next();
 });  

cela doit avoir avant tout routeur.
J'ai vu de nombreux en-têtes ajoutés:

res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

mais je n'en ai pas besoin,

b) lorsque vous définissez un cookie, vous devez ajouter httpOnly: false, comme:

 res.cookie( key, value,{ maxAge: 1000 * 60 * 10, httpOnly: false });

c) côté client: dans send ajax, vous devez ajouter: "withCredentials: true", comme:

$http({
     method: 'POST',
     url: 'url, 
     withCredentials: true,
     data : {}
   }).then(function(response){
        // code  
   }, function (response) {
         // code 
   });

bonne chance.

5
izik f

Il y a quelques problèmes:

  • un cookie qui n'est pas explicitement défini avec httpOnly : false sera pas accessible via document.cookie dans le navigateur. Il sera toujours envoyé avec des requêtes HTTP, et si vous vérifiez les outils de développement de votre navigateur, vous y trouverez probablement le cookie (dans Chrome ils peuvent être trouvés dans le Ressources onglet des outils de développement);
  • la next() que vous appelez ne doit être utilisée que si vous souhaitez différer l'envoi d'une réponse à une autre partie de votre application qui, à en juger par votre code, n'est pas ce que vous voulez.

Donc, il me semble que cela devrait résoudre vos problèmes:

res.cookie('token', jwt.token, {
  expires  : new Date(Date.now() + 9999999),
  httpOnly : false
});
res.status(200).send({ user, token: jwt.token });

En remarque: il y a une raison pour que httpOnly passe par défaut à true (pour empêcher les scripts XSS malveillants d'accéder aux cookies de session et autres). Si vous n'avez pas de très bonnes raisons d'accéder au cookie via JS côté client, ne le définissez pas sur false.

2
robertklep

Vérifiez la taille de votre cookie.

Pour moi, la façon dont je générais un jeton d'authentification à stocker dans mon cookie entraînait une augmentation de la taille du cookie avec les tentatives de connexion suivantes, ce qui finissait par empêcher le navigateur de définir le cookie car il était trop gros.

Aide-mémoire sur la taille des cookies du navigateur

1
Mr Derfenstien
app.post('/api/user/login',(req,res)=>{

    User.findOne({'email':req.body.email},(err,user)=>{
        if(!user) res.json({message: 'Auth failed, user not found'})
        
        user.comparePassword(req.body.password,(err,isMatch)=>{
            if(err) throw err;
            if(!isMatch) return res.status(400).json({
                message:'Wrong password'
            });
            user.generateToken((err,user)=>{
                if(err) return res.status(400).send(err);
                res.cookie('auth',user.token).send('ok')
            })
        }) 
    })
});

réponse

res.cookie ('auth', user.token) .send ('ok')

le serveur donne une réponse ok mais le cookie n'est pas stocké dans le navigateur

Solution :

Ajoutez Postman Interceptor Extension à chrome qui permet à postman de stocker des cookies dans le navigateur et de récupérer les demandes d'utilisation.

0
Prakash Karena