为什么req.cookies.session未定义?Firebase + Node + Express [英] Why is the req.cookies.session undefined? Firebase + Node + express

查看:41
本文介绍了为什么req.cookies.session未定义?Firebase + Node + Express的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试分配一个生成会话cookie,以换取所提供的ID令牌.此处是我关注的文档.

I'm trying to assign a generate a session cookie in exchange for the provided ID token. Here are the docs I'm following.

这是我的客户端登录代码:

Here is my client side sign-in code:

firebase.auth().signInWithEmailAndPassword(email, password)
    .then(function(user) {
        firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {
            return sendToken(idToken);
        });
    })
    // .then(() => {
    //     return firebase.auth().signOut();
    // })
    .then(() => {
        window.location.assign('/member');
    })
    .catch(function(error) {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        alert(errorMessage);
    });

我的send sendToken()将idToken发布到服务器:

My send sendToken() posts the idToken to the server:

function sendToken(idToken) {
console.log("Posting " + idToken);
var xhr = new XMLHttpRequest();
var params = `token=${idToken}`;
xhr.open('POST', "/login", true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
return new Promise(function(resolve, reject) {
   xhr.onreadystatechange = function() {//Call a function when the state changes.
        if (xhr.readyState == 4 && xhr.status == 200) {
            resolve();
        } else if (xhr.readyState == 4 && xhr.status != 200) {
            reject("Invalid http return status");
        }
    }
   return xhr.send(params);
});
}

然后在服务器上,我返回一个会话cookie:

And at the server, I'm returning a session cookie:

app.post('/login', (req, res) => {
if (req.body.token) {
   const idToken = req.body.token.toString();
  // Set session expiration to 1 day.
   const expiresIn = 60 * 60 * 24 * 1 * 1000;
   return firebase.auth().createSessionCookie(idToken, {expiresIn}).then((sessionCookie) => {
     const options = {maxAge: expiresIn, httpOnly: true, secure: true};
     res.cookie('session', sessionCookie, options);
     res.end(JSON.stringify({status: 'success'}));
  })
  .catch((error) => {
  res.status(401).send('UNAUTHORIZED REQUEST!');
 });
}
return res.status(400).send("MISSING TOKEN");
});

我还设置了一个中间件,以在服务器提供成员信息之前验证会话cookie:

I've also set up a middleware to verify the session cookie before the server serves the member info:

function authVerification(req, res, next){
 const sessionCookie = req.cookies.session || '';
 // Verify the session cookie. In this case an additional check is added to 
 detect
 // if the user's Firebase session was revoked, user deleted/disabled, etc.
 return firebase.auth().verifySessionCookie(
 sessionCookie, true /** checkRevoked */).then((decodedClaims) => {
   console.log("decoded claims: " + decodedClaims);
   next();
   // serveContentForUser('/profile', req, res, decodedClaims);
 }).catch(error => {
   // Session cookie is unavailable or invalid. Force user to login.
   res.send(error);
 });
}

但是,当我登录后尝试获取会员页面时:

But, when I try to get a member's page after signing in:

app.get("/member", authVerification, (req, res) => {
  res.send("member page");
});

我不断从authVerification中获取错误:

I keep getting error from authVerification:

代码:"auth/argument-error",消息:解码Firebase会话cookie失败.请确保您传递了代表会话cookie的整个字符串JWT.请参见 https://firebase.google.com/docs/auth/admin/manage-cookies 了解有关如何检索会话cookie的详细信息."

code: "auth/argument-error", message: "Decoding Firebase session cookie failed. Make sure you passed the entire string JWT which represents a session cookie. See https://firebase.google.com/docs/auth/admin/manage-cookies for details on how to retrieve a session cookie."

谁能给我指出正确的方向.预先谢谢你!

Can anyone please point me in the right direction. Thank you in advance!

推荐答案

quickstart-nodejs存储库中的解决方案.

Solution in the quickstart-nodejs repo.

在此处输入链接描述

您必须添加 cookie-parser body-parser .这是我使用Firebase Cloud Functions解决的方法:

You have to add cookie-parser and body-parser. Here is how I solved it with Firebase Cloud Functions:

const admin = require("firebase-admin");
const functions = require("firebase-functions");
const next = require("next");
const cors = require("cors");
const express = require("express");
const cookieParser = require("cookie-parser");
const bodyParser = require("body-parser");

const dev = process.env.NODE_ENV !== "production";
const app = next({ dev, conf: { distDir: "next" } });
const handle = app.getRequestHandler();

admin.initializeApp({
  credential: admin.credential.cert("Service account key"),
  databaseURL: "Path to database"
});

const server = express();
server.use(cors({ origin: true }));
server.use(bodyParser.json());
// Support URL-encoded bodies.
server.use(bodyParser.urlencoded({
  extended: true
}));
// Support cookie manipulation.
server.use(cookieParser());
// Attach CSRF token on each request.
server.use(attachCsrfToken('/', 'csrfToken', (Math.random()* 100000000000000000).toString()));


function attachCsrfToken(url, cookie, value) {
  return function(req, res, next) {
    if (req.url === url) {
      res.cookie(cookie, value);
    }
    next();
  }
}

server.post("/login", (req, res) => {
  if (req.body && req.body.idToken) {
    const idToken = `${req.body.idToken}`;
    const expiresIn = 60 * 60 * 24 * 5 * 1000;
    admin.auth().createSessionCookie(idToken, { expiresIn }).then((sessionCookie) => {
      const options = { maxAge: expiresIn, httpOnly: true, secure: true };
      res.cookie("session", sessionCookie, options);
      res.end(JSON.stringify({ sessionCookie }));
    }, error => {
      res.status(401).send(error);
    });
  } else {
    res.status(401).send("Token empty");
  }
});

server.post("/profile", (req, res) => {
  if (req.cookies && req.cookies.session) {
    const sessionCookie = `${req.cookies.session}`;
    admin.auth().verifySessionCookie(
      sessionCookie, true /** checkRevoked */).then((decodedClaims) => {
      res.end(JSON.stringify({ decodedClaims }));
    }).catch(error => {
      res.status(401).send(error);
    });
  } else {
    res.status(401).send("Session empty");
  }
});

exports.next = functions.https.onRequest((req, res) => {
  if (req.method === "POST") {
    if (!req.path) req.url = `/${request.url}`;
    return server(req, res);
  }

  return app.prepare().then(() => handle(req, res));
});

客户端没有什么特别的.您可以使用isomorphic-unfetch,axios或jQuery.

Nothing special on the client side. You can use isomorphic-unfetch, axios or jQuery.

这篇关于为什么req.cookies.session未定义?Firebase + Node + Express的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆